/* ==========================================================================
   Wallfahrer GmbH — Design-System „Goldemar in Blau"
   Nachtblau, Eisblau-Verläufe, Hanken Grotesk + Fraunces italic.
   ========================================================================== */

:root {
  --bg:        #070b12;
  --bg-soft:   #0c1220;
  --bg-card:   #0a101c;
  --ink:       #eef3f9;
  --muted:     #9fb0c4;
  --faint:     #697a92;
  --blue-1:    #cfe6ff;
  --blue-2:    #6aa5e8;
  --blue-3:    #2f6cb4;
  --line:      rgba(238, 243, 249, 0.10);
  --line-soft: rgba(238, 243, 249, 0.06);
  --overlay:   rgba(12, 18, 32, 0.96);
  --ease:      cubic-bezier(0.22, 1, 0.36, 1);
  --grad:      linear-gradient(105deg, var(--blue-1), var(--blue-2) 45%, var(--blue-3));
  /* Eigener Verlauf für Schaltflächen. Er endet bei --blue-2 statt bei
     --blue-3, weil die dunkle Textfarbe #06101c auf --blue-3 nur
     3,57:1 erreicht — WCAG AA verlangt 4,5:1, denn die Schrift ist
     15,68px bei 600 und damit kein „großer Text". Gemessen gegen die
     drei Farbstopps: 14,94 / 7,43 / 3,57 vorher, 14,94 / 7,43 / 7,43
     nachher. Der Flächen-Verlauf --grad bleibt unverändert; er trägt
     Überschriften-Akzente, Kennzahlen und den Backup-Preis, und dort
     ist er die Schrift und nicht der Grund. */
  --grad-btn:  linear-gradient(105deg, var(--blue-1), var(--blue-2) 45%, var(--blue-2));
  --grad-btn-ink: #06101c;
  /* Goldemar-Teaser: eigene Farbwelt. Der KI-Mitarbeiter tritt unter
     eigener Marke auf, deshalb Gold statt der Blau-Tokens des Themes.
     Die Werte stammen aus der Bestandsseite (Blockify-Fassung) und
     sind unverändert übernommen, damit der Teaser nach dem
     Theme-Wechsel gleich aussieht wie vorher. */
  --gold-1:    #ffe9b0;
  --gold-2:    #e9b667;
  --gold-3:    #c8923a;
  --gold-cta:  #e9b667;
  --gold-line: #a8761f;
  color-scheme: dark;
}

/* ---------- Light Mode (invertiert; Nav bleibt dunkel) ---------- */
html[data-theme="light"] {
  --bg:        #f3f6fa;
  --bg-soft:   #e9eef5;
  --bg-card:   #ffffff;
  --ink:       #16222f;
  --muted:     #4a5d72;
  --faint:     #667282;
  --blue-1:    #4a73a2;
  --blue-2:    #2f6cb4;
  --blue-3:    #1c4a85;
  --line:      rgba(22, 34, 47, 0.14);
  --line-soft: rgba(22, 34, 47, 0.08);
  --overlay:   rgba(255, 255, 255, 0.97);
  /* Im hellen Modus ist der ganze Verlauf zu dunkel für dunkle Schrift:
     #06101c erreicht auf #4a73a2 / #2f6cb4 / #1c4a85 nur
     3,88 / 3,57 / 2,16. Deshalb weiße Schrift — gemessen dann
     4,92 / 5,35 / 8,87 — und der Verlauf selbst bleibt, wie er ist. */
  --grad-btn:  var(--grad);
  --grad-btn-ink: #ffffff;
  color-scheme: light;
  /* Gold im hellen Modus: dieselbe Reihenfolge, dunklere Stufen —
     sonst verschwindet die Verlaufsschrift auf hellem Grund. */
  --gold-1:    #c8923a;
  --gold-2:    #a8761f;
  --gold-3:    #845911;
  --gold-cta:  #a8761f;
  --gold-line: #c8923a;
}
html[data-theme="light"] .aurora { opacity: 0.9; }
html[data-theme="light"] .aurora .a1 {
  background: radial-gradient(circle at 30% 30%, rgba(47, 108, 180, 0.45), rgba(47, 108, 180, 0) 70%);
}
html[data-theme="light"] .aurora .a2 {
  background: radial-gradient(circle at 60% 40%, rgba(28, 74, 133, 0.36), rgba(28, 74, 133, 0) 70%);
}
html[data-theme="light"] .aurora .a3 {
  background: radial-gradient(circle at 50% 50%, rgba(106, 165, 232, 0.42), rgba(106, 165, 232, 0) 70%);
}
html[data-theme="light"] .veil {
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(243,246,250,0) 55%, rgba(243,246,250,0.45) 100%),
    linear-gradient(180deg, rgba(243,246,250,0.25), rgba(243,246,250,0) 30%);
}
html[data-theme="light"] .spot {
  background: radial-gradient(460px circle at var(--mx, 50%) var(--my, 30%), rgba(47, 108, 180, 0.26), rgba(47, 108, 180, 0) 60%);
}
html[data-theme="light"] body::after { opacity: 0.025; }
html[data-theme="light"] .eyebrow { background: rgba(255, 255, 255, 0.6); }
/* weiße Knockout-Logos & weißes Footer-Logo im Light Mode invertieren.
   Das Partnerlogo wird über die Figur angesprochen, nicht über eine
   eigene Klasse am <img>: core/image legt className ausschließlich an
   das <figure>, nie an das Bild. Ein class="plogo-img" im Pattern
   machte den Block deshalb ungültig — 42 rote Blöcke im Site-Editor,
   und „Wiederherstellung versuchen" hätte die Klasse entfernt und
   damit genau diese Regel und die Größenregel unten ins Leere laufen
   lassen. Die Rechnung steht an .marquee .plogo img. */
html[data-theme="light"] .plogo img,
html[data-theme="light"] .footer-logo { filter: invert(1); }
html[data-theme="light"] .trust-thumb { box-shadow: 0 14px 36px rgba(22, 34, 47, 0.22); }

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  min-height: 100svh;
  background: var(--bg);
  color: var(--ink);
  font-family: "Hanken Grotesk", -apple-system, sans-serif;
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: -0.011em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  position: relative;
}

::selection { background: rgba(106, 165, 232, 0.35); }

/* ---------- Atmosphäre: Blau-Aurora ---------- */
.aurora {
  position: fixed;
  inset: -25%;
  z-index: -2;
  pointer-events: none;
  opacity: 1;
}
.aurora span {
  position: absolute;
  border-radius: 50%;
  display: block;
  will-change: transform;
}
.aurora .a1 {
  width: 46vw; height: 46vw;
  top: 2%; left: 8%;
  background: radial-gradient(circle at 30% 30%, rgba(106,165,232,0.55), rgba(106,165,232,0) 70%);
  animation: drift1 64s ease-in-out infinite;
}
.aurora .a2 {
  width: 40vw; height: 40vw;
  bottom: 0%; right: 4%;
  background: radial-gradient(circle at 60% 40%, rgba(47,108,180,0.45), rgba(47,108,180,0) 70%);
  animation: drift2 76s ease-in-out infinite;
}
.aurora .a3 {
  width: 34vw; height: 34vw;
  top: 38%; left: 44%;
  background: radial-gradient(circle at 50% 50%, rgba(207,230,255,0.26), rgba(207,230,255,0) 70%);
  animation: drift3 56s ease-in-out infinite;
}
/* Rundreisen über den ganzen Viewport — Ende = Anfang, nahtlose Schleife */
@keyframes drift1 {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  25%  { transform: translate3d(38vw, 22vh, 0) scale(1.18); }
  50%  { transform: translate3d(55vw, -8vh, 0) scale(0.92); }
  75%  { transform: translate3d(14vw, 38vh, 0) scale(1.1); }
  100% { transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes drift2 {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  25%  { transform: translate3d(-34vw, -26vh, 0) scale(1.12); }
  50%  { transform: translate3d(-58vw, 6vh, 0) scale(0.9); }
  75%  { transform: translate3d(-18vw, -42vh, 0) scale(1.06); }
  100% { transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes drift3 {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  25%  { transform: translate3d(-24vw, 26vh, 0) scale(0.92); }
  50%  { transform: translate3d(18vw, 44vh, 0) scale(1.15); }
  75%  { transform: translate3d(30vw, -18vh, 0) scale(1); }
  100% { transform: translate3d(0, 0, 0) scale(1); }
}

.veil {
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(7,11,18,0) 40%, rgba(7,11,18,0.55) 100%),
    linear-gradient(180deg, rgba(7,11,18,0.35), rgba(7,11,18,0) 30%);
}

.spot {
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  opacity: 0; transition: opacity 0.6s ease;
  background: radial-gradient(460px circle at var(--mx, 50%) var(--my, 30%), rgba(207,230,255,0.16), rgba(207,230,255,0) 60%);
}

/* Filmkorn */
body::after {
  content: "";
  position: fixed; inset: 0; z-index: 50; pointer-events: none;
  opacity: 0.04;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- Grundlayout ---------- */
.wrap {
  max-width: 1080px;
  margin: 0 auto;
  padding: 0 clamp(1.25rem, 4vw, 2.5rem);
}

section { padding: clamp(4rem, 10vh, 7.5rem) 0; }
section + section { border-top: 1px solid var(--line-soft); }

.accent {
  font-family: "Fraunces", Georgia, serif;
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.01em;
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  padding-right: 0.06em;
}

h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.03em; }

h2 {
  font-size: clamp(1.9rem, 4.4vw, 3.1rem);
  line-height: 1.08;
}

/* Zeilenumbrüche in Headlines sind redaktionell gesetzt (<br>);
   auf schmalen Screens natürliche Umbrüche statt erzwungener. */
@media (max-width: 700px) {
  .hero h1 br, section h2 br { display: none; }
}

.kicker {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  margin-bottom: 1.1rem;
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blue-2);
  font-weight: 600;
}
.kicker::before {
  content: "";
  width: 1.6rem; height: 1px;
  background: var(--grad);
}

.lede {
  margin: 1.4rem 0 0;
  max-width: 52ch;
  font-size: clamp(1.05rem, 1.8vw, 1.25rem);
  line-height: 1.62;
  font-weight: 350;
  color: var(--muted);
}
.lede strong { color: var(--ink); font-weight: 500; }

/* ---------- Navigation ---------- */
.nav {
  /* Nav bleibt in beiden Themes dunkel — Tokens hier festgepinnt */
  --ink:       #eef3f9;
  --muted:     #9fb0c4;
  --faint:     #697a92;
  --line:      rgba(238, 243, 249, 0.10);
  --line-soft: rgba(238, 243, 249, 0.06);
  position: sticky;
  top: 0;
  z-index: 40;
  backdrop-filter: blur(18px) saturate(1.4);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
  background: rgba(7, 11, 18, 0.78);
  border-bottom: 1px solid var(--line-soft);
}
.nav-inner {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  padding-top: 0.75rem;
  padding-bottom: 0.75rem;
}

/* „flex: 0 0 auto": .nav-inner ist eine Flexzeile, und die Marke ist
   dort ein Flex-Element. Ohne die Regel gilt der Vorgabewert
   „flex: 0 1 auto" — die Marke gibt als Erste nach, sobald Menü und
   Werkzeugleiste den Platz brauchen. Gemessen im Theme vor der Regel:
   126px bei 1440px Breite, 97px mit neun statt sechs Menüpunkten und
   nur noch 14px bei 390px.
   Im Entwurf ist die Marke ebenfalls schrumpfbar und hält trotzdem
   126px: Dort ist das Logo ein <img> ohne max-width, und ein
   Flex-Element kann nicht unter seine Mindestgröße aus dem Inhalt
   fallen. WordPress gibt dem Logo dagegen
   „img.custom-logo { max-width: 100% }" mit — damit sinkt die
   Mindestgröße auf null, und der ganze Behälter darf mitschrumpfen.
   Nachgemessen bei 390px: mit „max-width: none" hält die Marke auch
   ohne diese Regel ihre 126px, mit „max-width: 100%" fällt sie auf
   63px. Statt an WordPress' Logo-Regeln zu drehen, hält hier das
   Flex-Element den Platz. */
.brand {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 0.65rem;
  font-weight: 600;
  font-size: 1.1rem;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-decoration: none;
  margin-right: auto;
  white-space: nowrap;
}
.brand img {
  height: 34px;
  width: auto;
  display: block;
}
/* Im Entwurf ist .footer-logo das <img> selbst. core/image legt die
   Klasse dagegen auf das <figure> — dieselbe Falle wie bei core/button
   und core/search, wo die Klasse ebenfalls am Wrapper landet. Die Höhe
   band deshalb nur den Rahmen, das Bild darin blieb unbeschränkt:
   gemessen 226x61px in einem 40px hohen Rahmen bei 1440px, und bei
   390px 350x95px mit 31px Überlappung auf die Anschrift darunter. Die
   Maße gehören ans <img>, Abstand und Deckkraft bleiben am Rahmen.
   Der Entwurf rendert 148x40px. */
.footer-logo {
  margin-bottom: 0.9rem;
  opacity: 0.9;
}
.footer-logo img {
  height: 40px;
  width: auto;
  display: block;
}

/* .nav-links ist der Blockbehälter aus parts/header.html; die
   Menüpunkte selbst liegen seit Version 1.0.0 eine Ebene tiefer, in
   einem <ul class="nav-list">. Vorher lagen die <li> nackt in diesem
   <div> — ungültiges HTML, und ein Screenreader meldete keine Liste,
   sondern nur einzelne Links. Deshalb steht die waagerechte Zeile
   jetzt an .nav-list und nicht mehr hier; dieses <div> zentriert nur
   noch (WordPress' Flex-Layout des Blocks). */
.nav-links { display: flex; }
.nav-list {
  display: flex;
  gap: 1.1rem;
  font-size: 0.92rem;
  /* Der Browser gibt jedem <ul> von sich aus "margin: 1em 0" und einen
     Einzug mit. Beides muss weg — der Einzug schöbe die Zeile nach
     rechts, und der Außenabstand hat schon einmal Schaden angerichtet,
     siehe .sub-menu weiter unten. */
  margin: 0;
  padding: 0;
  list-style: none;
}
.nav-list li { list-style: none; margin: 0; position: relative; }
.nav-list a {
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.3s;
}
.nav-list a:hover { color: var(--ink); }

/* Untermenü "Leistungen": wp_nav_menu() mit depth:2 verschachtelt
   Kind-Seiten in ein .sub-menu — dafür gab es noch keine Regel. An
   .portals-menu angelehnt, damit es zum Rest der Nav passt. */
/* Zwischen Menüpunkt und Untermenü darf keine Lücke liegen: Fällt
   die Maus beim Hinuntergleiten hindurch, bricht der Hover ab, das
   Untermenü verschwindet — und weil es dann display:none ist, kommt
   die Maus auch nicht mehr hinein. Die Einträge sind praktisch
   unerreichbar.
   Genau das war noch der Fall, obwohl "top: 100%" es an den Menüpunkt
   kleben sollte: Der Browser gibt jedem <ul> "margin-block-start: 1em"
   mit, und die 14,72px schoben es wieder herunter. Gemessen bei
   1440px: Menüpunkt endet bei y=41,3, Untermenü begann bei y=56,0,
   die Brücke unten reichte bis 54,1 — in 1px-Schritten klappte es ab
   y=55 zu. Der Reset "margin: 0" nimmt den Abstand; der sichtbare
   Abstand entsteht jetzt wie vorgesehen durch den oberen Innenabstand,
   und die Hoverfläche bleibt durchgehend.
   Die Brücke bleibt trotzdem stehen — sie kostet nichts und fängt
   den Fall ab, dass ein Plugin dem <ul> wieder einen Abstand gibt. Sie
   hängt am Menüpunkt, nicht am Untermenü: Letzteres ist bis zum
   Hover display:none und kann selbst nichts überbrücken. */
.nav-list li:has(> .sub-menu)::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  height: 0.8rem;
}
.nav-list .sub-menu {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  min-width: 200px;
  margin: 0;
  padding: 1rem 0.45rem 0.45rem;
  list-style: none;
  border-radius: 14px;
  border: 1px solid var(--line);
  background: rgba(12, 18, 32, 0.92);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.5);
  z-index: 41;
}
.nav-list li:hover > .sub-menu,
.nav-list li:focus-within > .sub-menu {
  display: block;
}
.nav-list .sub-menu a {
  display: block;
  padding: 0.55rem 0.8rem;
  border-radius: 9px;
  white-space: nowrap;
  transition: background 0.25s, color 0.3s;
}
.nav-list .sub-menu a:hover { background: rgba(106,165,232,0.10); }

.nav-tools {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border-radius: 8px;
  border: 1px solid var(--line-soft);
  background: none;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.3s, border-color 0.3s;
}
.icon-btn:hover { color: var(--ink); border-color: var(--line); }
.icon-btn svg { width: 15px; height: 15px; }

/* Fernwartung: eigenständige Schnellaktion neben dem Sprachumschalter */
.nav-remote {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.42rem 0.7rem;
  border-radius: 100px;
  border: 1px solid var(--line-soft);
  color: var(--muted);
  font-size: 0.88rem;
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.3s, border-color 0.3s;
}
.nav-remote:hover { color: var(--ink); border-color: var(--line); }

/* Der Blitz vor der Beschriftung. Im Entwurf ist das ein <svg> im
   Link; core/button rendert aber genau einen <a> und lässt keine
   Kindelemente zu, das SVG ist beim Portieren deshalb weggefallen.
   Ersatz ist ein ::before mit CSS-Maske: Die Maske färbt sich über
   background-color, ein Hintergrundbild wäre starr. Das SVG steckt
   als data:-URI im Stylesheet — kein zusätzlicher Request, kein
   fremder Host. Gemessen bei 1440px: Entwurf 124px breite Pille,
   ohne Icon waren es 103px. */
.nav-remote::before {
  content: "";
  flex: none;
  width: 15px;
  height: 15px;
  background-color: var(--blue-2);
  -webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M13%202%204.5%2013H11l-1%209%208.5-11H12z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23000'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M13%202%204.5%2013H11l-1%209%208.5-11H12z'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Ab hier trägt die Pille nur noch das Icon.
   „font-size: 0" statt der alten Regel „.nav-remote-text{display:none}":
   Die hatte kein Ziel, weil es im Blockmarkup kein <span> um die
   Beschriftung gibt (siehe oben). Der Textknoten hängt direkt im <a>
   und lässt sich nur über die Schriftgröße einziehen; das ::before
   behält seine 15px, weil sie in px stehen.
   Der Selektor muss zwei Klassen tief sein: WordPress setzt in
   wp-includes/blocks/buttons/style.css
   „.wp-block-buttons .wp-block-button__link{width:100%}" — 0-2-0 gegen
   0-1-0, ein einzelnes „.nav-remote{width:32px}" verliert. Gemessen bei
   800px: 81x32px statt 32x32px, mit ausgeschriebenem „Fernwartung".
   font-size:0 nimmt dem Screenreader den Text; den Namen setzt
   wallfahrer_button_klassen() als aria-label an den Link. */
@media (max-width: 880px) {
  .wp-block-button__link.nav-remote,
  .nav-remote {
    padding: 0;
    width: 32px;
    height: 32px;
    justify-content: center;
    gap: 0;
    font-size: 0;
  }
}

/* Theme-Toggle: Sonne im Dark Mode (wechselt zu hell), Mond im Light Mode */
.ico-moon { display: none; }
html[data-theme="light"] .ico-moon { display: block; }
html[data-theme="light"] .ico-sun { display: none; }

.lang {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.85rem;
}
.lang a, .lang span.on {
  padding: 0.2rem 0.25rem;
  color: var(--faint);
  text-decoration: none;
  transition: color 0.3s;
}
.lang a:hover { color: var(--muted); }
.lang .on { color: var(--blue-2); font-weight: 600; }
.lang-sep { color: var(--faint); opacity: 0.5; }

/* Portale-Dropdown (CSS-only via details) */
.portals { position: relative; }
.portals summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.42rem 0.95rem;
  border-radius: 100px;
  border: 1px solid var(--line);
  background: linear-gradient(135deg, rgba(106,165,232,0.13), rgba(47,108,180,0.05));
  color: var(--ink);
  font-size: 0.88rem;
  font-weight: 600;
  transition: border-color 0.3s, box-shadow 0.3s;
  white-space: nowrap;
}
.portals summary::-webkit-details-marker { display: none; }
.portals summary:hover { border-color: rgba(106,165,232,0.5); box-shadow: 0 0 18px rgba(106,165,232,0.15); }
.portals[open] summary { border-color: rgba(106,165,232,0.5); }
.portals-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 0.6rem);
  min-width: 220px;
  padding: 0.45rem;
  border-radius: 14px;
  border: 1px solid var(--line);
  background: rgba(12, 18, 32, 0.92);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.5);
}
.portals-menu a {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.55rem 0.8rem;
  border-radius: 9px;
  color: var(--ink);
  text-decoration: none;
  font-size: 0.92rem;
  transition: background 0.25s;
}
.portals-menu a:hover { background: rgba(106,165,232,0.10); }
.portals-menu a small { color: var(--faint); font-size: 0.75rem; }

/* Mobile-Nav */
.nav-burger { display: none; }
@media (max-width: 1200px) {
  /* WPs generiertes "body .is-layout-flex{display:flex}" hat mit
     einem Typ- plus einem Klassenselektor mehr Spezifität als ein
     einzelnes ".nav-links" — ohne den Nav-Vorspann bliebe die Liste
     trotz "display:none" sichtbar. */
  .nav .nav-links { display: none; }
  .nav-burger { display: inline-flex; position: relative; }
  .nav-burger summary {
    list-style: none; cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px;
    border-radius: 8px; border: 1px solid var(--line-soft);
    color: var(--muted);
  }
  .nav-burger summary::-webkit-details-marker { display: none; }
  .nav-burger .portals-menu { left: auto; right: 0; }

  /* Ab hier trägt die Portale-Klappe nur noch ihr Chevron — derselbe
     Weg wie bei der Fernwartungs-Pille oben, und aus demselben Grund.
     Gemessen bei 390px Viewport: Die Navigationszeile braucht 413,2px
     in einem 350px breiten Kasten (Marke 125,9 + Abstand 19,2 +
     Werkzeugleiste 268,1). Die Klappe steht ganz rechts und endete
     bei 433,2px; „body { overflow-x: hidden }" (Zeile 96) macht daraus
     keinen Scrollbalken, sondern eine Wand. Von der Klappe blieben
     52,1px sichtbar, von den drei Portallinks im ausgeklappten Menü
     reichte der breiteste bis 425px.
     Die Klappe von 95,3px auf 32px zu ziehen spart 63,3px und bringt
     die Zeile auf 349,9px. Der Entwurf (localhost:8080) braucht an
     derselben Stelle 487,1px und schneidet zusätzlich den Burger an —
     er ist hier keine gültige Referenz.
     „font-size: 0" zieht den Textknoten „Portale" ein, wie bei der
     Pille; die Maße des Chevrons stehen in px und bleiben davon
     unberührt. Den Namen für Screenreader setzt
     wallfahrer_nav_portale() als aria-label an das <summary>. */
  .portals > summary {
    padding: 0;
    width: 32px;
    height: 32px;
    justify-content: center;
    gap: 0;
    font-size: 0;
  }
  .portals > summary svg { flex: none; width: 12px; height: 12px; }

  /* Der Sprachumschalter verlässt hier die Zeile und steht im Burger.
     Gemessen bei 390px Viewport, Inhaltskasten 350px, mit
     eingehängtem Umschalter (Polylang-Attrappe, s.
     tests/helpers/sprachumschalter.php):

       Platzbedarf der Zeile   349,9 → 424,2
       .nav-tools endet bei    370,0 → 444,2
       scrollWidth              390  →  444

     Der Umschalter ist 63,2px breit und bringt 11,2px Abstand mit —
     74,4px, wo nach dem Chevron-Fix aus Paket E noch 0,1px Luft
     waren. Ein Kürzel in der Zeile schließt die Lücke deshalb nicht:
     Ein 32x32-Icon-Knopf wie Suche oder Burger bräuchte 43,2px, ein
     nacktes „EN" rund 31px. Beides ist mehr als da ist.

     Der Kindkombinator ist Pflicht: Die Fassung im Burger steht
     ebenfalls unter .nav-tools, „.nav-tools .lang" würde beide
     ausblenden. Spezifität nachgemessen — „.lang { display:
     inline-flex }" ist 0-1-0, WordPress' Flex-Layout-Regeln greifen
     am Behälter und nicht am Kind; 0-2-0 genügt also. */
  .nav-tools > .lang { display: none; }

  /* Die Fassung im Burger ist keine Zeile im Kopf, sondern die letzte
     Zeile im Menü: eine Trennlinie darüber, zwei Schaltflächen
     darunter. Die Flächen sind bewusst großzügig — 24x24px sind das
     Minimum aus WCAG 2.5.8, auf einem Telefon trifft man 44px
     zuverlässiger. Nachgemessen bei 390px: 44 x 44px je Sprache,
     „DE" bei 170..214, „EN" bei 219,6..263,6, beide von
     elementFromPoint() auf ihre Mitte getroffen. */
  .nav-burger .lang {
    display: flex;
    justify-content: center;
    gap: 0.35rem;
    margin-top: 0.45rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--line-soft);
  }
  /* „.nav-burger .lang a" (0-2-1) muss „.portals-menu a" (0-1-1)
     schlagen — sonst wird aus der Sprache eine volle Menüzeile mit
     Innenabstand und space-between. */
  .nav-burger .lang a,
  .nav-burger .lang span.on {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    padding: 0 0.75rem;
    border-radius: 9px;
    font-size: 0.92rem;
  }
  .nav-burger .lang a { color: var(--muted); }
  .nav-burger .lang a:hover {
    color: var(--ink);
    background: rgba(106, 165, 232, 0.10);
  }
  /* Der Schrägstrich trennt zwei Wörter, nicht zwei Schaltflächen. */
  .nav-burger .lang .lang-sep { display: none; }
}

/* ---------- Hero ---------- */
.hero { padding: clamp(5rem, 14vh, 9rem) 0 clamp(4rem, 10vh, 7rem); }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.4rem 0.85rem 0.4rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: 100px;
  background: rgba(10, 16, 28, 0.55);
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  color: var(--muted);
  text-transform: uppercase;
}
.dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--blue-2);
  animation: pulse 2.4s ease-out infinite;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(106,165,232,0.55); }
  70%  { box-shadow: 0 0 0 9px rgba(106,165,232,0); }
  100% { box-shadow: 0 0 0 0 rgba(106,165,232,0); }
}

.hero h1 {
  margin: 1.6rem 0 0;
  font-size: clamp(2.5rem, 7vw, 5.2rem);
  line-height: 1.02;
  letter-spacing: -0.035em;
}

.cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
  margin-top: 2.2rem;
}
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.78rem 1.5rem;
  border-radius: 100px;
  font-size: 0.98rem;
  font-weight: 600;
  text-decoration: none;
  letter-spacing: -0.01em;
  transition: transform 0.35s var(--ease), box-shadow 0.35s, border-color 0.3s;
}
.btn-primary {
  background: var(--grad-btn);
  color: var(--grad-btn-ink);
  box-shadow: 0 6px 30px rgba(106, 165, 232, 0.28);
}
.btn-primary:hover { transform: translateY(-2px); box-shadow: 0 10px 40px rgba(106,165,232,0.4); }
.btn-ghost {
  border: 1px solid var(--line);
  color: var(--ink);
}
.btn-ghost:hover { border-color: rgba(106,165,232,0.5); transform: translateY(-2px); }

/* ---------- Karten-Grids (Hairline-Look) ---------- */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1px;
  background: var(--line-soft);
  border: 1px solid var(--line-soft);
  border-radius: 18px;
  overflow: hidden;
  margin-top: 2.6rem;
}
.card {
  background: var(--bg-card);
  padding: 1.9rem;
  transition: background 0.4s;
}
.card:hover { background: var(--bg-soft); }
.card .icon {
  display: inline-flex;
  margin-bottom: 1.1rem;
  color: var(--blue-2);
  transition: color 0.3s, transform 0.4s var(--ease);
}
.card:hover .icon { color: var(--blue-1); transform: translateY(-2px); }
.card .icon svg { width: 26px; height: 26px; }
.card h3 {
  font-size: 1.12rem;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin-bottom: 0.5rem;
}
.card p {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--muted);
  font-weight: 350;
}

/* Drei-Spalter (Cloud) */
.cards.cols-3 { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }

/* ---------- O365-Backup-Highlight ---------- */
.backup-price {
  margin: 2.4rem 0 0.6rem;
  font-family: "Fraunces", Georgia, serif;
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.8rem, 4.5vw, 3.2rem);
  letter-spacing: -0.01em;
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.backup-note { color: var(--faint); max-width: 52ch; font-size: 0.95rem; }

/* ---------- Kennzahlen ---------- */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 2rem 1rem;
  margin-top: 2.6rem;
}
.stat-num {
  display: block;
  font-size: clamp(2.4rem, 5vw, 3.8rem);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1;
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  font-variant-numeric: tabular-nums;
}
.stat-label {
  display: block;
  margin-top: 0.5rem;
  color: var(--muted);
  font-size: 0.95rem;
}

/* ---------- Portfolio-Marquee ---------- */
.marquee {
  position: relative;
  margin-top: 2.2rem;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.marquee-label {
  display: block;
  margin: 0 auto 0.8rem;
  max-width: 1080px;
  padding: 0 clamp(1.25rem, 4vw, 2.5rem);
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
}
.marquee-track {
  display: flex;
  width: max-content;
  animation: marquee 48s linear infinite;
}
.marquee.reverse .marquee-track { animation-direction: reverse; animation-duration: 56s; }
.marquee:hover .marquee-track, .paused .marquee-track { animation-play-state: paused; }
.marquee-set {
  display: flex;
  align-items: center;
  gap: clamp(2.4rem, 5vw, 4rem);
  padding-right: clamp(2.4rem, 5vw, 4rem);
}
/* Angesprochen wird das Bild IN der Figur, nicht über eine eigene
   Klasse am <img>.
   Ursache: core/image speichert className am <figure>. Sein save()
   kennt am <img> nur src und alt — ein zusätzliches class dort machte
   den Block ungültig. Gemessen am 25.08.2026 im Site-Editor auf
   front-page: 231 Blöcke, davon 44 ungültig (42 × core/image aus
   diesem Band, 2 × core/group aus der Urkunden-Leiste). Die
   Wiederherstellung hätte class="plogo-img" ersatzlos entfernt und
   allen 21 Partnerlogos ihre Gestaltung genommen.
   Der Entwurf (main.css) stellt das <img> direkt in .marquee-set und
   spricht es dort als .plogo-img an; im Theme steht die
   wp-block-image-Figur dazwischen. „flex: none" hängt deshalb an der
   Figur — im Entwurf war das <img> selbst das Flexkind.
   Gemessen vor und nach der Umstellung, Startseite bei 1440px:
   Bildhöhe 40px, Bildbreite 96px, opacity 0.7, im hellen Modus
   filter invert(1), Spurbreite 2904px — unverändert. */
.marquee .plogo {
  flex: none;
  margin: 0;
}
.marquee .plogo img {
  display: block;
  height: 40px;
  width: auto;
  opacity: 0.7;
  transition: opacity 0.35s;
}
.marquee .plogo img:hover { opacity: 1; }
@keyframes marquee { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: none !important; }
  .marquee { overflow-x: auto; }
}

/* ---------- Gruppenbild-Band (zwischen Hero und Leistungen) ---------- */
.team-photo-band {
  padding-bottom: clamp(2rem, 6vh, 4rem);
}
.team-photo {
  background: radial-gradient(55% 75% at 50% 72%, rgba(106, 165, 232, 0.16), transparent 72%);
}
.team-photo img {
  width: 100%;
  height: auto;
  display: block;
}

/* ---------- Team ---------- */

.team-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 2.2rem 1.6rem;
  margin-top: 2.6rem;
}
.member img {
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border-radius: 16px;
  border: 1px solid var(--line-soft);
  filter: saturate(0.88);
  transition: filter 0.4s, transform 0.4s var(--ease);
}
.member:hover img { filter: saturate(1.05); transform: translateY(-3px); }
.member h3 { margin-top: 1rem; font-size: 1.05rem; }
.member .role {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.82rem;
  letter-spacing: 0.02em;
  color: var(--blue-2);
}
.member p {
  margin: 0.6rem 0 0;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--muted);
  font-weight: 350;
}

/* ---------- Trust-Leiste ---------- */
.trust {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(2rem, 6vw, 4.5rem);
  padding: 2.6rem 0;
}
.trust-mark {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45rem;
  text-decoration: none;
  text-align: center;
}
.trust-thumb {
  height: 150px;
  width: auto;
  margin-bottom: 0.6rem;
  border-radius: 8px;
  border: 1px solid var(--line);
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.45);
  opacity: 0.9;
  transition: opacity 0.35s, transform 0.4s var(--ease);
}
figure.trust-thumb img {
  height: 100%;
  width: auto;
}
a.trust-mark:hover .trust-thumb { opacity: 1; transform: translateY(-3px) scale(1.02); }
.trust-big {
  font-family: "Fraunces", Georgia, serif;
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  letter-spacing: -0.01em;
  color: var(--ink);
  transition: opacity 0.35s;
}
.trust-big .accent, .trust-big.accent { font-size: inherit; }
.trust-sub { font-size: 0.8rem; color: var(--faint); letter-spacing: 0.04em; }
a.trust-mark:hover .trust-big { opacity: 0.8; }
a.trust-mark:hover .trust-sub { color: var(--muted); }

/* ---------- Kontakt ---------- */
.contact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 2.5rem;
  margin-top: 2.6rem;
}
.contact-card h3 {
  font-size: 0.82rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blue-2);
  margin-bottom: 0.9rem;
}
.contact-card p {
  margin: 0;
  font-style: normal;
  color: var(--muted);
  line-height: 1.8;
}
.contact-card a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--line); transition: border-color 0.3s; }
.contact-card a:hover { border-color: var(--blue-2); }
.contact-note { margin-top: 0.6rem; font-size: 0.85rem; color: var(--faint); }

/* ---------- Footer ---------- */
footer.site {
  border-top: 1px solid var(--line-soft);
  padding: 3rem 0 2.5rem;
  font-size: 0.88rem;
  color: var(--faint);
}
.footer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 2rem;
}
.footer-grid h4 {
  margin: 0 0 0.8rem;
  font-size: 0.78rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
.footer-grid ul { list-style: none; margin: 0; padding: 0; }
.footer-grid li { margin: 0.35rem 0; }
.footer-grid a { color: var(--faint); text-decoration: none; transition: color 0.3s; }
.footer-grid a:hover { color: var(--blue-2); }
.footer-mail { color: var(--muted); text-decoration: none; transition: color 0.3s; }
.footer-mail:hover { color: var(--blue-2); }
.footer-meta {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line-soft);
}
.footer-meta a { color: inherit; text-decoration: none; }

/* ---------- Such-Overlay ---------- */
dialog.search {
  width: min(640px, calc(100vw - 2rem));
  margin: 10vh auto auto;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--overlay);
  color: var(--ink);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
}
dialog.search::backdrop {
  background: rgba(4, 6, 10, 0.6);
  backdrop-filter: blur(6px);
}
.search-inner { padding: 1.1rem 1.2rem; max-height: 70vh; overflow: auto; }
.search-hint { margin: 0.8rem 0 0; font-size: 0.8rem; color: var(--faint); text-align: right; }

/* ---------- Unterseiten (Rechtstexte) ---------- */
/* „prose" steht am core/post-content-Block (templates/page.html und
   single.html). Im Frontend ist das immer dasselbe Element, ein
   <div class="wp-block-post-content prose"> — deshalb genügt hier
   in aller Regel eine Klasse.

   Bis Version 1.0.0 standen sechs dieser Regeln weiter unten ein
   zweites Mal, als „.wp-block-post-content.prose": zwei Blöcke für
   dasselbe Element, und der untere gewann mit 0-2-0 gegen 0-1-0. Wer
   oben die Schriftgröße der h2 änderte, sah keine Wirkung.
   Zusammengeführt stehen hier die Werte, die vorher tatsächlich
   galten — nachgemessen an /impressum/, /agb/ und
   /datenschutzerklaerung/ in beiden Modi, über fünfzehn berechnete
   Eigenschaften an je neun Elementen. Eine der sechs Regeln braucht ihre
   zweite Klasse wirklich; sie steht unten mit Begründung. */
.prose {
  max-width: 70ch;
  padding: clamp(3rem, 8vh, 5rem) 0 clamp(4rem, 10vh, 7rem);
}
.prose h1 { font-size: clamp(2rem, 5vw, 3rem); margin-bottom: 1.5rem; letter-spacing: -0.03em; }
.prose h2 {
  margin: 2.5em 0 0.7rem;
  font-size: clamp(1.4rem, 2.6vw, 1.9rem);
  max-width: none;
}
.prose h3 { margin-top: 2em; font-size: 1.2rem; }
/* Die erste Überschrift im Inhalt braucht eine Klasse mehr. Der
   Inhaltsblock ist „is-layout-constrained"; WordPress setzt dafür
   „:root :where(.is-layout-constrained) > :first-child
   { margin-block-start: 0 }" — 0-2-0, und das schlägt „.prose h2"
   mit 0-1-1. Nachgemessen auf /impressum/ und
   /datenschutzerklaerung/, in beiden Modi: 0px statt 76px über der
   ersten Zwischenüberschrift. Genau
   dafür stand diese eine Angabe bis Version 1.0.0 ein zweites Mal
   weiter unten im Stylesheet. */
.wp-block-post-content.prose h2 { margin-top: 2.5em; }
.prose p, .prose li { color: var(--muted); font-weight: 350; line-height: 1.7; }
.prose strong { color: var(--ink); font-weight: 500; }
.prose a { color: var(--blue-2); }
.prose img { border-radius: 14px; }

/* ---------- 404 ---------- */
.notfound {
  min-height: 60svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* ---------- Entrance (nur mit JS aktiv — kein unsichtbarer Inhalt ohne JS) ---------- */
.js .reveal { opacity: 0; transform: translateY(18px); filter: blur(6px); }
.js .reveal.in { animation: rise 1s var(--ease) forwards; animation-delay: var(--d, 0s); }
@keyframes rise { to { opacity: 1; transform: none; filter: blur(0); } }

/* Tab versteckt → Animationen pausieren */
.paused .aurora span, .paused .dot { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .aurora span, .dot { animation: none !important; }
  .reveal { opacity: 1 !important; transform: none !important; filter: none !important; animation: none !important; }
  .spot { display: none; }
  .btn, .card .icon, .member img { transition: none; }
}

@media (max-width: 560px) {
  .stats { grid-template-columns: repeat(2, 1fr); }
  .cta-row .btn { width: 100%; justify-content: center; }
}

/* ---------- Brücke: theme.json-Presets folgen den Design-Tokens ---------- */
:root {
  --wp--preset--color--bg: var(--bg);
  --wp--preset--color--bg-soft: var(--bg-soft);
  --wp--preset--color--bg-card: var(--bg-card);
  --wp--preset--color--ink: var(--ink);
  --wp--preset--color--muted: var(--muted);
  --wp--preset--color--faint: var(--faint);
  --wp--preset--color--blau-1: var(--blue-1);
  --wp--preset--color--blau-2: var(--blue-2);
  --wp--preset--color--blau-3: var(--blue-3);
}

/* ---------- WordPress-Blockklassen an das Design anschließen ---------- */

/* WordPress legt auf Sektionsblöcke ein globales horizontales Padding
   (Klasse has-global-padding, aus styles.spacing.padding in theme.json).
   Der Entwurf gibt Sektionen dagegen nur vertikalen Innenabstand —
   `section { padding: clamp(4rem, 10vh, 7.5rem) 0 }` in main.css:169.
   Den horizontalen bringt allein `.wrap` mit. Beides zusammen zählt
   doppelt: 1080 → 1000 → 920 px, und das Team-Raster bricht dadurch auf
   drei statt vier Spalten um. */
main > .wp-block-group {
  padding-inline: 0;
}

/* Das Gruppenbild-Band ist keine Sektion und trägt deshalb nicht deren
   Innenabstand. main.css:605 gibt ihm nur unten Luft, damit das Foto
   dicht unter dem Hero sitzt. */
main > .wp-block-group.team-photo-band {
  padding-block: 0 clamp(2rem, 6vh, 4rem);
}
.wp-site-blocks > * { margin-block: 0; }

/* Nur der .wrap-Container wird begrenzt — nicht jeder constrained
   Group-Block. Der zweite Selektor traf auch die Sektionen selbst und
   stauchte sie auf 1080px; im Entwurf laufen sie über die volle Breite
   und tragen Hintergrund und Trennlinie, während allein .wrap den
   Inhalt begrenzt. */
.wp-block-group.wrap {
  max-width: 1080px;
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 4vw, 2.5rem);
}

main > .wp-block-group { padding-block: clamp(4rem, 10vh, 7.5rem); }

.wp-block-post-content > * + * { margin-top: 1.1em; }

/* WordPress rendert die Kachelreihen als core/columns und setzt darauf
   display:flex mit höherer Spezifität als die .cards-Regel aus main.css.
   Das Raster wird dadurch zur Flexzeile: gleich hohe Spalten statt
   gleich breiter Kacheln, und der Hairline-Look bricht. */
.wp-block-columns.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1px;
}
.wp-block-columns.cards.cols-3 {
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
.wp-block-columns.cards > .wp-block-column { flex-basis: auto !important; }

/* Dieselbe Ursache bei den übrigen Rastern: core/columns bringt
   display:flex mit, main.css will grid. Ohne das werden aus gleich
   breiten Spalten Flexzeilen, die sich nach Inhalt verteilen. */
.wp-block-columns.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 2rem 1rem;
}
.wp-block-columns.footer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 2rem;
}
.wp-block-columns.contact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 2.5rem;
}
.wp-block-columns.stats > .wp-block-column,
.wp-block-columns.footer-grid > .wp-block-column,
.wp-block-columns.contact-grid > .wp-block-column {
  flex-basis: auto !important;
}

/* WordPress gibt Geschwisterblöcken einen Abstand nach oben. In einem
   Raster ist das falsch: Das erste Element bleibt ohne, alle anderen
   rutschen — im Team-Raster saß die erste Person 24px höher als ihre
   Reihe.
   „.cards > *" statt „.wp-block-columns.cards > *": Leistungen und
   IT-Souveränität führen ihr Raster als core/group (ein Raster mit
   sechs Kacheln), Cloud weiterhin als core/columns. Beide Fälle
   brauchen dieselbe Nullstellung. */
.team-grid > *,
.cards > *,
.wp-block-columns.stats > *,
.wp-block-columns.footer-grid > *,
.wp-block-columns.contact-grid > * {
  margin-block-start: 0;
}

/* Dieselbe WordPress-Regel trifft auch INNERHALB einer Kachel:
   „:root :where(.is-layout-flow) > * { margin-block-start: 24px }",
   dazu „> :first-child { margin-block-start: 0 }". Solange die
   Überschrift das erste Kind der Kachel war, fiel das nicht auf. Seit
   die Leistungskacheln ihr Icon tragen, ist sie das zweite und rutschte
   um 24px nach unten: gemessen bei 1440px eine Kartenhöhe von 254,2px
   statt der 236,5px des Entwurfs.
   Getroffen wird nur die Überschrift, nicht der Absatz darunter —
   „.card p { margin: 0 }" ist 0-1-1 und gewinnt ohnehin, „h1, h2, h3
   { margin: 0 }" mit 0-0-1 dagegen nicht.
   Deshalb genau das Element hinter dem Icon, und keine breitere Regel:
   Die Beitragskarten in home.html und archive.html heißen ebenfalls
   „.card", tragen kein Icon und behalten ihre Abstände. */
.card .icon + * { margin-block-start: 0; }

/* Dieselbe WordPress-Regel, dieselbe Ursache, eine Ebene höher: der
   Sektionskopf. Jede Sektion beginnt mit Kicker, Überschrift, Lede,
   dann dem Inhalt. Die Überschrift ist das zweite Kind und bekommt
   „margin-block-start: 24px"; im Entwurf hat sie „margin: 0" und der
   ganze Abstand kommt aus „.kicker { margin-bottom: 1.1rem }" = 17,6px.

   Warum sich die beiden Werte ADDIEREN statt zu verschmelzen: „.kicker"
   ist „display: inline-flex". Ränder benachbarter Kästen fallen nur
   zwischen Elementen auf Blockebene zusammen (CSS 2.1, 8.3.1) — der
   Kicker ist inline-level, also bleiben 17,6 + 24 = 41,6px stehen. Bei
   Blockkästen wäre der Fehler nur 6,4px groß gewesen.

   Gemessen bei 1440px, Entwurf (localhost:8080) gegen Theme, Abstand
   von Unterkante zu Oberkante:

     Kicker → Überschrift   17,6 → 41,6   +24,0
     Überschrift → Lede     22,4 → 22,4     0
     Lede → Inhalt          41,6 → 41,6     0

   Nur die erste Lücke geht auseinander, dafür in acht Sektionen
   zugleich: services, portfolio, souveraenitaet, cloud, backup,
   zahlen, team, kontakt. Deshalb eine Regel und nicht acht.

   Spezifität nachgemessen, nicht geschätzt: WordPress' Regel steht als
   „:root :where(.is-layout-flow) > *" da — „:where()" zählt nichts,
   „:root" zählt eine Klasse, macht 0-1-0. „.kicker + *" ist ebenfalls
   0-1-0, entschieden wird also über die Reihenfolge, und theme.css
   steht im <head> hinter „global-styles-inline-css". Gegenprobe im
   Browser: „.kicker + *", „.wrap > .kicker + *" (0-2-0) und
   „body .kicker + *" (0-2-0) liefern alle drei margin-block-start: 0
   und eine Lücke von 17,6px. Die einfachste gewinnt, wie schon bei
   „.cards > *" und „.wp-site-blocks > *" weiter oben.

   „.kicker + *" und nicht „.wrap > * + *": Der Hero führt keinen
   Kicker, sondern einen „.eyebrow", und dort will der Entwurf 25,6px
   („.hero h1 { margin: 1.6rem 0 0 }"). Eine Regel über alle
   Geschwister würde die einziehen. */
.kicker + * { margin-block-start: 0; }

/* Und derselbe Blockabstand ein drittes Mal, in der
   Auszeichnungs-Leiste. „.trust-mark" ist eine Flexspalte mit
   „gap: 0.45rem"; darin stehen im Entwurf ein <img> und zwei <span>,
   im Theme ein core/image und zwei core/paragraph. Die beiden
   Absätze sind Blöcke und bekommen je „margin-block-start: 24px",
   und weil ein Flexbehälter keine Ränder verschmelzen lässt, kommen
   sie ungekürzt zum Gap dazu.

   Gemessen bei 1440px, Entwurf gegen Theme:

     Lücke unter dem Vorschaubild    16,8 → 40,8   +24
     Lücke zwischen den Zeilen        7,2 → 31,2   +24
     Höhe je Auszeichnung       243,5/217,2 → 291,5/265,2   +48
     Sektionshöhe                   507,7 → 555,7   +48

   Beide Marken stehen nebeneinander, deshalb schlägt der Fehler nur
   einmal auf die Sektion durch. „.trust-mark > *" ist 0-1-0 wie
   WordPress' Regel und gewinnt über die Reihenfolge — dieselbe
   Rechnung wie bei „.cards > *" weiter unten. */
.trust-mark > * { margin-block-start: 0; }

/* Und ein viertes Mal, im Logoband der Portfolio-Sektion. Beschriftung
   und laufende Spur sind in Entwurf und Theme dieselben Kästen: Die
   12,8px Abstand kommen aus „.marquee-label { margin: 0 auto 0.8rem }",
   die Spur trägt keinen eigenen Rand. Im Theme ist sie der zweite
   Block im Fluss und bekommt WordPress' 24px; beide Ränder liegen auf
   Blockebene, verschmelzen also — und der größere gewinnt.

   Gemessen bei 1440px, Entwurf gegen Theme:

     Lücke Beschriftung → Spur   12,8 → 24,0   +11,2
     Höhe je Band                70,6 → 81,8   +11,2
     Sektion portfolio          630,5 → 653,3  +22,8 (zwei Bänder)

   Anders als bei „.trust-mark" verschmelzen die Ränder hier, deshalb
   kostet es nur 11,2 statt 24px. */
.marquee > * { margin-block-start: 0; }

/* WordPress färbt jede Schaltfläche mit seinem Standardton #32373c
   und setzt eigene Innenabstände. Wo eine .btn-Klasse am Link sitzt,
   gelten stattdessen die Regeln aus main.css: .btn-primary trägt den
   Blau-Verlauf, .btn-ghost nur einen Rahmen. Die Spezifität muss dafür
   zwei Klassen tief sein, sonst gewinnt WordPress über die
   Ladereihenfolge. */
.wp-block-button__link.btn {
  background: none;
  background-color: transparent;
  box-shadow: none;
  border-radius: 100px;
}
.wp-block-button__link.btn-primary {
  background: var(--grad-btn);
  color: var(--grad-btn-ink);
  box-shadow: 0 6px 30px rgba(106, 165, 232, 0.28);
}
/* core/search legt die Klasse auf das <form>, nicht auf den Knopf — wie
   bei core/button. Die Hülle bleibt deshalb neutral, und der Knopf
   darin bekommt die Optik aus main.css:292: 32x32, transparenter Grund,
   feiner Rahmen. WordPress gibt ihm sonst seinen Standardton und eigene
   Innenabstände. */
.wp-block-search.icon-btn {
  border: 0;
  padding: 0;
}
.wp-block-search.icon-btn .wp-block-search__button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  min-width: 0;
  padding: 0;
  margin: 0;
  border-radius: 8px;
  border: 1px solid var(--line-soft);
  background: none;
  background-color: transparent;
  color: var(--muted);
  box-shadow: none;
  cursor: pointer;
  transition: color 0.3s, border-color 0.3s;
}
.wp-block-search.icon-btn .wp-block-search__button:hover {
  color: var(--ink);
  border-color: var(--line);
}
.wp-block-search.icon-btn .wp-block-search__button svg {
  width: 15px;
  height: 15px;
  fill: currentColor;
}

/* Die Fernwartungs-Pille sitzt in der stets dunklen Navigation und
   trägt dort nur einen Rahmen — WordPress' Standardton würde sie zu
   einem grauen Klotz machen. */
.wp-block-button__link.nav-remote {
  background: none;
  background-color: transparent;
  box-shadow: none;
}

.wp-block-button__link.btn-ghost {
  border: 1px solid var(--line);
  color: var(--ink);
}

/* Schaltflächen aus vorhandenen Seiteninhalten tragen keine .btn-Klasse
   — sie stammen aus dem Editor, nicht aus einem Pattern. WordPress gibt
   ihnen seinen Standardton #32373c, auf dem die Linkfarbe des Themes im
   hellen Modus auf 2,25:1 fällt. Sie bekommen deshalb dieselbe Optik wie
   .btn-primary. Das gilt gerade dann, wenn das Theme über einen
   bestehenden Seitenbestand gelegt wird, in dem solche Schaltflächen
   verstreut sind. */
.wp-block-button__link:not(.btn):not(.nav-remote):not(.goldemar-cta) {
  background: var(--grad-btn);
  color: var(--grad-btn-ink);
  border-radius: 100px;
  padding: 0.78rem 1.5rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-decoration: none;
  box-shadow: 0 6px 30px rgba(106, 165, 232, 0.28);
}
.wp-block-button.is-style-outline .wp-block-button__link:not(.btn):not(.nav-remote):not(.goldemar-cta) {
  background: none;
  border: 1px solid var(--line);
  color: var(--ink);
  box-shadow: none;
}

/* ---------- Innenseiten ---------- */
/* ".wrap > .seiten-kopf" statt ".seiten-kopf" — braucht mehr
   Spezifität als "main > .wp-block-group" weiter oben, sonst gewinnt
   dessen symmetrisches padding-block und der Abstand zum Inhalt wird
   doppelt so groß wie geplant. Gemessen: 90px/90px statt 108px/36px. */
.wrap > .seiten-kopf {
  padding-block: clamp(5rem, 12vh, 8rem) clamp(1.5rem, 4vh, 2.5rem);
}
.seiten-kopf h1 { margin: 0; }

/* ---------- Suchfeld im Dialog (statt Pagefind-UI) ---------- */
.search-inner input[type="search"] {
  width: 100%;
  padding: 1rem 1.2rem;
  font-family: inherit;
  font-size: 1.1rem;
  color: var(--ink);
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: 14px;
  outline: none;
}
.search-inner input[type="search"]:focus {
  border-color: var(--blue-2);
}
.suchtreffer .card { margin-bottom: 1px; }

/* ---------- Goldemar-Teaser ---------- */

/* Die Marke: Linktext plus G-Logo als ::before. Ein <img> im Link
   bräuchte wp:html (im Theme verboten) oder einen weiteren
   render_block-Filter; das Logo ist rein dekorativ, der Linktext
   nennt das Ziel bereits. flex: 0 0 auto, damit das Icon nicht
   gestaucht wird — dieselbe Falle wie bei .brand im Kopf. */
.goldemar-brand {
  margin-block: 0 1.4rem;
}
.goldemar-brand a {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  color: inherit;
  font-size: 1.0625rem;
  letter-spacing: 0.01em;
}
.goldemar-brand a::before {
  content: "";
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  background: url("../img/goldemar-g.png") center / contain no-repeat;
}

/* Die zweite Überschriftenzeile trägt den Goldverlauf als Schrift,
   analog zu .accent im blauen Teil des Themes. */
.goldemar-akzent {
  font-family: "Fraunces", Georgia, serif;
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.01em;
  background: linear-gradient(105deg, var(--gold-1), var(--gold-2) 45%, var(--gold-3));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  padding-right: 0.06em;
}

.goldemar-note {
  color: var(--muted);
}

/* Die Schaltfläche steht bewusst außerhalb der Verlaufs-Rückfallregel
   (siehe :not(.goldemar-cta) dort): Sie trägt Goldrand auf
   durchsichtigem Grund, nicht den blauen Verlauf. core/button legt
   className auf den Wrapper — wallfahrer_button_klassen() schiebt sie
   auf den Link, deshalb greift die Regel hier am <a>. */
.wp-block-button__link.goldemar-cta {
  padding: 12px 26px;
  border: 1px solid var(--gold-line);
  border-radius: 999px;
  background: none;
  background-color: transparent;
  background-image: none;
  box-shadow: none;
  color: var(--gold-cta);
  font-size: 1rem;
  line-height: 1.4;
}
.wp-block-button__link.goldemar-cta:hover {
  background-color: rgba(233, 182, 103, 0.12);
  color: var(--gold-1);
}
html[data-theme="light"] .wp-block-button__link.goldemar-cta:hover {
  background-color: rgba(200, 146, 58, 0.10);
  color: var(--gold-3);
}

/* Die Navigation muss beim Scrollen oben bleiben — und das tut sie
   nur, wenn auch der Wrapper klebt, den WordPress um jedes
   Template-Part legt.

   .nav trägt seit jeher position: sticky; top: 0. Im Entwurf sitzt sie
   direkt im <body> und klebt damit über die ganze Seitenhöhe. Im Theme
   steckt sie in <header class="wp-block-template-part">, und ein
   sticky Element klebt nur, solange sein Elternelement im Viewport
   ist. Der header-Wrapper ist aber genau so hoch wie die Nav selbst,
   also war sie nach dem ersten Bildschirm weg.

   Gemessen auf der Zielsite bei 1440 px: Vor dem Scrollen stand die
   Nav bei top 0, nach 1500 px Scrollen bei -1380 — vollständig aus
   dem Bild. Mit dieser Regel bleibt sie bei 0. */
header.wp-block-template-part {
  position: sticky;
  top: 0;
  z-index: 40;
}

/* Das G-Logo am Goldemar-Menüpunkt. Es hängt am Ziel des Links, nicht
   am Menütitel: Ein <img> im Titel würde in der Datenbank stehen und
   beim nächsten Bearbeiten des Menüs verlorengehen — über den href
   greift es, solange der Punkt auf goldemar.de zeigt, und der
   Redakteur muss nichts wissen. Maße wie in der Bestandsseite:
   19x19 px, 6 px Abstand, 4 px tiefer gesetzt. */
.nav-list a[href^="https://goldemar.de"]::before,
.nav-burger a[href^="https://goldemar.de"]::before {
  content: "";
  display: inline-block;
  width: 19px;
  height: 19px;
  margin-right: 6px;
  vertical-align: -4px;
  background: url("../img/goldemar-g.png") center / contain no-repeat;
}

/* Der Suchknopf saß 5 px höher als der Theme-Schalter daneben.
   Ursache ist nicht der Knopf, sondern das eingeklappte Suchfeld:
   core/search lässt es im DOM stehen (der Dialog braucht es), es ist
   0 px breit — aber 42 px hoch, aus 8 px Innenabstand oben und unten
   plus Zeilenhöhe. Das Formular ist display:flex, also macht das Feld
   die Flexzeile höher als den 32-px-Knopf, und der Knopf verschiebt
   sich.

   Gemessen auf der Zielsite bei 1440 px: Knopf-Mitte 25, Schalter
   mitte 30. Im Entwurf liegen beide auf 71. Mit dieser Regel liegen
   sie gleichauf.

   Die Regel greift nur, solange WordPress die eigene Klasse
   __searchfield-hidden setzt — also genau im eingeklappten Zustand.
   Klappt der Dialog auf, fällt sie weg und das Feld bekommt seine
   Höhe zurück. */
.wp-block-search__searchfield-hidden .wp-block-search__input {
  height: 0;
  min-height: 0;
  padding-block: 0;
  border-block: 0;
}

/* Der Goldemar-Teaser schließt direkt an das Bildband an, so wie in
   der Bestandsseite. Zwei Abstände standen dazwischen: WordPress'
   Flow-Layout setzt 24 px Blockabstand zwischen die Geschwister
   (gemessen: Band endet bei 1185, Sektion beginnt bei 1209), und
   `section { padding: clamp(4rem, 10vh, 7.5rem) 0 }` legt oben noch
   einmal bis zu 120 px darauf. Zusammen war die Lücke mehr als
   doppelt so groß wie im Original.

   Unten bleibt der volle Sektionsabstand, damit der Übergang zu den
   Leistungen sitzt wie bei allen anderen Sektionen. */
.team-photo-band + .sektion-goldemar {
  margin-block-start: 0;
}

/* Bewusste Abweichung vom Entwurf: engere Sektionsabstände.

   Der Entwurf setzt clamp(4rem, 10vh, 7.5rem) oben wie unten — bei
   1100 px Fensterhöhe sind das 110 px je Seite, zwischen zwei
   Sektionen also 220 px plus dem Abstand bis zum ersten Inhalt (136
   px). Auf einem hohen Fenster reißt das die Seite auseinander;
   gemessen wurde es auf der Zielsite und im Entwurf identisch, es ist
   also kein Portierungsfehler, sondern eine Entscheidung des
   Auftraggebers gegen den Entwurf.

   Neu: clamp(2.5rem, 6.5vh, 5rem) — bei 1100 px sind das 71 px statt
   110, bei 900 px 58 statt 90. Der Anteil an der Fensterhöhe bleibt
   erhalten, damit hohe Fenster weiterhin luftiger wirken als flache.

   Die Spezifität muss main > .wp-block-group schlagen (0,1,1); eine
   Regel auf section allein (0,0,1) reicht nicht. */
main > section,
main > .wp-block-group {
  padding-block: clamp(2.5rem, 6.5vh, 5rem);
}

/* Der Goldemar-Teaser schließt oben direkt an das Bildband an. Ohne
   den main-Vorfahren im Selektor verliert die Regel gegen
   main > .wp-block-group — gemessen: padding-top blieb bei 110 px,
   obwohl .sektion-goldemar clamp(1.5rem, 4vh, 3rem) setzt. */
main > .sektion-goldemar {
  padding-block-start: clamp(1.5rem, 4vh, 3rem);
}

/* Ausnahme von „.hero h1 br, section h2 br { display: none }" weiter
   oben: Im Goldemar-Teaser trennt der Umbruch zwei Sinnabschnitte, und
   ohne ihn stand auf dem Telefon „derschon" zusammengeschrieben da —
   das Markup trägt an der Stelle jetzt zusätzlich ein Leerzeichen,
   damit auch ohne den Umbruch nichts zusammenklebt. */
@media (max-width: 700px) {
  .sektion-goldemar h2 br { display: inline; }
}

/* Untermenüs im Burger-Menü.

   Bis Version 1.0.0 lief das Burger-Menü mit depth 1 und nackten <a>:
   Der Entwurf ist ein Onepager mit sechs Ankern und kennt keine
   Untermenüs. Auf der gewachsenen Installation hängen an drei
   Menüpunkten echte Unterseiten — die waren auf dem Telefon über
   keinen Weg erreichbar, und die Elternpunkte zeigten auf „#".

   Jetzt liefert wp_nav_menu die volle Struktur, und diese Regeln
   tragen sie: Die Liste verliert ihre Aufzählungszeichen, Unterpunkte
   werden eingerückt und leiser gesetzt, und ein Elternpunkt ohne
   eigenes Ziel wird als Überschrift dargestellt statt als toter Link. */
.portals-menu .burger-list,
.portals-menu .sub-menu {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* .portals-menu a zieht Link und Beschreibung mit space-between
   auseinander — das ist für die Portale gedacht, wo rechts ein <small>
   steht. Im Burger stehen keine, und beim Goldemar-Punkt riss es das
   G-Logo vom Text weg. */
.portals-menu .burger-list a {
  justify-content: flex-start;
}

.portals-menu .sub-menu a {
  padding-left: 1.9rem;
  font-size: 0.86rem;
  color: var(--muted);
}

/* Ein Elternpunkt, dessen Ziel nur „#" ist, führt nirgendwohin. Er
   bleibt als Beschriftung stehen, nimmt aber weder Zeiger noch
   Hover-Fläche — sonst wirkt er wie ein Link, der nicht funktioniert. */
.portals-menu .burger-list > li > a[href="#"],
.portals-menu .burger-list > li > a[href$="/#"] {
  color: var(--faint);
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: default;
  padding-bottom: 0.2rem;
}
.portals-menu .burger-list > li > a[href="#"]:hover,
.portals-menu .burger-list > li > a[href$="/#"]:hover {
  background: none;
}

/* Zwei Nachbesserungen am Burger-Menü mit Untermenüs:

   Der Abstand zwischen Icon und Text stammt von „.portals-menu a
   { gap: 1rem }" — dort trennt er den Portalnamen von seiner
   Beschreibung. Im Burger steht keine, und beim Goldemar-Punkt riss
   er das G weit vom Wort weg. 0,4rem entspricht dem Abstand, den
   derselbe Punkt in der Navigationszeile hat.

   Und die Liste ist mit allen Ebenen 714 px hoch (gemessen bei
   390x844). Auf einem kleineren Display oder mit eingeblendeter
   Adminleiste reicht der Platz nicht — deshalb eine Höhengrenze mit
   eigenem Bildlauf statt eines Menüs, dessen Ende niemand erreicht. */
.portals-menu .burger-list a {
  gap: 0.4rem;
}
.nav-burger .portals-menu {
  max-height: calc(100vh - 5.5rem);
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* ====================================================================
   CI für die gewachsenen Seiteninhalte

   Die elf Themenseiten stammen aus dem alten Theme und tragen dessen
   Gestaltung im Markup: zentrierte Überschriften, eigene Größen,
   zweispaltige Blöcke. Technisch laufen sie sauber durch page.html —
   gestalterisch fielen sie aus der Reihe. Diese Schicht fängt sie ein.

   Gemessen am 2026-08-25 auf der Zielsite bei 1440 px, gegen die
   Startseite als Maßstab:

                        Startseite      Unterseiten (vorher)
     Überschrift 2      50px, links     30px, zentriert
     Überschrift 4      –               16px, zentriert
     Textbreite         1080er Raster   627px, alles darin
     Abstand unter H1   –               208px

   ==================================================================== */

/* --- Breite: Text schmal, Struktur breit --------------------------

   .prose stand auf max-width: 627px. Für Fließtext ist das richtig
   (rund 72 Zeichen je Zeile), aber die Bestandsseiten stellen darin
   zweispaltige Blöcke und Bilder auf — die wurden mit
   hineingequetscht. Team-Karten hatten dadurch 302px Textbreite.

   Jetzt trägt der Inhaltsblock die volle Rasterbreite, und die
   Lesebreite hängt an den Textelementen selbst. Spalten, Bilder und
   Tabellen dürfen ausbrechen. */
.wp-block-post-content.prose,
.entry-content.prose {
  max-width: none;
}
/* Die Lesebreite muss LINKS anliegen, nicht mittig sitzen. WordPress
   gibt jedem direkten Kind eines constrained-Layouts
   „margin-left: auto; margin-right: auto" — zusammen mit einer
   max-width zentriert das den Text im Rahmen. Gemessen: Die
   Überschriften standen dadurch bei 632 statt bei 500, also 132px
   eingerückt gegenüber der Marke im Kopf. */
:root .prose > p,
:root .prose > ul,
:root .prose > ol,
:root .prose > h2,
:root .prose > h3,
:root .prose > h4,
:root .prose > h5,
:root .prose > h6,
:root .prose > blockquote,
:root .prose > hr {
  max-width: 46rem;
  /* Links anliegend, nicht mittig. Seit page.html den Inhalt als
     „default" statt „constrained" führt, zentriert WordPress die
     Kinder nicht mehr selbst — diese Angabe hält das fest, falls
     jemand das Layout im Site-Editor zurückstellt. */
  margin-left: 0;
  margin-right: auto;
}
/* Spalten und Bilder nutzen die volle Rasterbreite und liegen
   ebenfalls links an. */
:root .prose > .wp-block-columns,
:root .prose > figure,
:root .prose > .wp-block-image,
:root .prose > .wp-block-group {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
}

/* --- Ausrichtung: linksbündig wie überall sonst -------------------

   Das alte Theme zentrierte Überschriften — im Markup steht dafür
   WordPress' eigene Klasse has-text-align-center an den Blöcken. Ein
   erster Versuch nahm genau die aus, in der Annahme, sie sei bewusst
   gesetzt; gemessen blieb danach alles zentriert. Sie IST die
   Altlast. Bilder und Schaltflächen bleiben unberührt, nur Text wird
   ausgerichtet. */
/* Der :root-Vorspann ist Pflicht, nicht Zierde: WordPress setzt die
   Zentrierung als „:root .has-text-align-center" (0,2,0), eine Regel
   auf „.prose :is(h1…h6)" kommt nur auf (0,1,1) und verliert.
   Nachgemessen — ohne den Vorspann blieben 22 Überschriften und
   Absätze über elf Seiten zentriert. */
:root .prose :is(h1, h2, h3, h4, h5, h6),
:root .prose p {
  text-align: left;
}
/* Bildunterschriften dürfen zentriert bleiben — dort ist es Absicht
   und keine Altlast. */
:root .prose figure p,
:root .prose figcaption {
  text-align: center;
}

/* --- Größen: dieselbe Staffel wie auf der Startseite -------------- */
.prose h2 {
  font-size: clamp(1.75rem, 3vw, 2.25rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
}
.prose h3 {
  font-size: clamp(1.2rem, 1.8vw, 1.4rem);
  line-height: 1.25;
}
.prose h4 {
  font-size: 1.15rem;
  line-height: 1.35;
  color: var(--ink);
}
.prose h5,
.prose h6 {
  font-size: 1.02rem;
  line-height: 1.35;
  color: var(--ink);
}

/* Kleine Auszeichnungen aus dem Bestand („Private Cloud", „Was Sie
   davon haben") standen als 16px-Fettung mitten im Text und waren als
   Überschrift nicht zu erkennen. Sie bekommen die Anmutung der
   Kicker von der Startseite. */
.prose .wp-block-column > h4:first-child,
.prose .wp-block-column > h5:first-child,
.prose .wp-block-column > h6:first-child {
  margin-block-start: 0;
  color: var(--blue-2);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* --- Abstände ----------------------------------------------------

   Unter der Seitenüberschrift standen 208px: 36px Innenabstand des
   Kopfes, 72px des Inhaltsblocks, 24px Außenabstand dazwischen, plus
   der Abstand des ersten Elements. Zusammen mehr als ein Drittel
   eines Bildschirms, bevor der erste Satz kam. */
/* Auch hier braucht es den :root-Vorspann. „main > .wp-block-group"
   (0,1,1) schlägt „.seiten-kopf" (0,1,0) — nachgemessen blieb der
   Innenabstand bei 120px statt der gesetzten 70. Und das erste
   Element im Inhalt trug 90px Außenabstand von der allgemeinen
   Überschriftenregel; zusammen standen zwischen Seitentitel und
   erstem Satz rund 210px. */
:root main > .seiten-kopf,
:root .seiten-kopf {
  padding-block: clamp(3rem, 7vh, 5rem) clamp(2rem, 4vh, 3rem);
}
:root main > .wp-block-post-content.prose,
:root main .wp-block-post-content.prose {
  padding-block-start: 0;
  margin-block-start: 0;
}
:root .prose > :first-child {
  margin-block-start: 0;
}

/* --- Spalten: Luft zwischen den Säulen ---------------------------

   Zweispaltige Blöcke aus dem Bestand standen ohne Abstand
   nebeneinander; bei Team-Karten klebte der Text am Bild. */
.prose .wp-block-columns {
  gap: clamp(1.5rem, 3vw, 2.75rem);
  margin-block: 2rem;
}
.prose .wp-block-column > :first-child {
  margin-block-start: 0;
}

/* Bilder in Spalten (Personenfotos) bekommen die Rundung und das
   Seitenverhältnis, das die Startseite für .member-Bilder nutzt —
   sonst steht ein hartes Rechteck neben weichen Karten. */
.prose .wp-block-column img {
  border-radius: 14px;
}

/* --- Trennlinien --------------------------------------------------
   Der Bestand setzt <hr> als Gliederung. Ohne Regel erscheinen sie
   als harte Linie quer über die neue, breitere Fläche. */
.prose hr {
  max-width: 46rem;
  margin-block: 2.5rem;
  border: 0;
  border-top: 1px solid var(--line-soft);
}

/* Seitentitel und Inhalt fluchten mit der Navigation.

   Der Seitenkopf ist ein core/group mit layout:constrained. WordPress
   gibt solchen Gruppen die contentSize aus theme.json — hier 760px —
   und zentriert sie im Rahmen. Gemessen bei 2000px Fensterbreite:
   Die Marke im Kopf steht bei 500, die Seitenüberschrift stand bei
   620, also 120px weiter rechts; der Fließtext darunter begann
   wieder bei 500. Auf der Startseite tritt das nicht auf, weil dort
   die Sektionen ihre Breite selbst setzen.

   Die Regel nimmt dem Seitenkopf die Verengung. Die Lesebreite des
   Textes bleibt davon unberührt — sie hängt an den Textelementen
   selbst, nicht am Rahmen. */
:root .seiten-kopf,
:root .seiten-kopf > * {
  max-width: none;
  margin-left: 0;
  margin-right: 0;
}

/* ---------- Hervorgehobene Kästen aus dem Bestand ----------

   Einzelne Abschnitte der Themenseiten sind Gruppen mit einer
   Hintergrundfarbe des alten Themes (has-neutral-100-background-color
   und Verwandte). Diese Farben stehen nicht in theme.json, also
   rendern die Kästen durchsichtig — übrig blieb eine Einrückung ohne
   erkennbaren Grund. Gemessen auf /cloud/: Der Kasten „Was wir dabei
   übernehmen" stand bei 450 mit transparentem Grund, seine Überschrift
   durch das constrained-Layout noch einmal 104px weiter innen.

   Sie bekommen die Anmutung der Karten von der Startseite. */
.prose .wp-block-group[class*="-background-color"] {
  /* Erst als Karte gesetzt (Grund --bg-card, Rahmen ringsum) — im
     hellen Modus wird daraus ein weisser Kasten auf hellem Grund, der
     wie ein Fremdkoerper wirkt. Jetzt nur ein Akzentstrich links und
     etwas Luft: Der Abschnitt bleibt als zusammengehoerig erkennbar,
     draengt sich aber nicht vor den Fliesstext. */
  padding: 0.2rem 0 0.2rem clamp(1rem, 2vw, 1.5rem);
  border-left: 2px solid var(--blue-2);
  background: none;
}

/* Und ihre Kinder liegen links an. Der Vorspann reicht hier nicht:
   WordPress' Regel für constrained-Layouts ist spezifischer als ihr
   sichtbarer Teil vermuten lässt — nachgemessen wirkte eine
   gleichlautende Regel nur mit !important, während dieselbe Regel
   ohne den Zusatz wirkungslos blieb (margin-left 132px statt 0). Die
   Templates des Themes führen ihre Blöcke deshalb als „default";
   für Gruppen, die im Seiteninhalt stehen, geht das nicht — dort
   steht das Layout im gespeicherten Markup. */
.prose .wp-block-group.is-layout-constrained > * {
  margin-left: 0 !important;
  margin-right: auto !important;
  max-width: none;
}

/* ---------- Kontaktformular des Ticketsystems ----------

   Der Knopf „Schreiben Sie uns!" öffnet kein Formular der Seite,
   sondern das Modal von ZammadForm — nachgeladen von
   ticket.mwcld.net/assets/form/form.js. Es bringt eigene Stile mit,
   die zu einer hellen Seite gehören: weißer Kasten, graue Felder,
   dunkler Knopf. Auf dunklem Grund steht es als Fremdkörper da.

   Diese Regeln geben ihm die Anmutung des Themes. Sie greifen an den
   Klassen, die form.js vergibt — ändert das Ticketsystem sie bei
   einem Update, fällt das Modal auf seine eigenen Stile zurück: Es
   bleibt bedienbar, sieht nur wieder fremd aus. */

.zammad-form-modal .zammad-form-modal-backdrop {
  background: rgba(4, 8, 16, 0.72);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

/* Der Vorspann .zammad-form-modal ist noetig: form.js laedt seine
   Stile erst zur Laufzeit nach, also nach diesem Stylesheet — bei
   gleicher Spezifitaet gewinnt es. Nachgemessen blieb der Kasten
   sonst weiss mit 5px Radius. */
.zammad-form-modal .zammad-form-modal-body {
  max-width: 34rem;
  padding: clamp(1.25rem, 3vw, 2rem);
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--bg-card);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55);
  color: var(--ink);
}

.zammad-form h2 {
  margin: 0 0 1.25rem;
  color: var(--ink);
  font-size: 1.6rem;
  font-weight: 600;
  letter-spacing: -0.02em;
}

.zammad-form .zammad-form-group {
  margin-bottom: 1rem;
}
.zammad-form label {
  display: block;
  margin-bottom: 0.35rem;
  color: var(--muted);
  font-size: 0.9rem;
}

.zammad-form .zammad-form-control {
  width: 100%;
  padding: 0.65rem 0.85rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--bg-soft);
  color: var(--ink);
  font: inherit;
  font-size: 0.98rem;
}
.zammad-form textarea.zammad-form-control {
  min-height: 7.5rem;
  resize: vertical;
}
.zammad-form .zammad-form-control:focus-visible {
  border-color: transparent;
  outline: 2px solid var(--blue-2);
  outline-offset: 2px;
}

/* Die Dateiauswahl bringt einen Browser-Knopf mit, der sich nicht
   umfärben lässt — sie bekommt wenigstens denselben Rahmen wie die
   übrigen Felder und etwas Luft. */
.zammad-form input[type="file"].zammad-form-control {
  padding: 0.5rem;
  font-size: 0.9rem;
}

/* Das Datenschutz-Häkchen steht mit seinem Text in einem label; der
   Link darin muss sich vom Fließtext abheben. */
.zammad-form .zammad-form-checkbox {
  margin-right: 0.5rem;
  accent-color: var(--blue-2);
}
.zammad-form label a {
  color: var(--blue-2);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Der Absendeknopf trägt den Verlauf der Startseiten-Schaltflächen.
   Der Selektor nennt .zammad-form ausdrücklich: „btn" ist auch eine
   Theme-Klasse, und ohne den Vorspann würden sich die Regeln
   gegenseitig überschreiben. */
.zammad-form button.btn {
  padding: 0.7rem 1.6rem;
  border: 0;
  border-radius: 100px;
  background: var(--grad-btn);
  color: var(--grad-btn-ink);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  transition: filter 0.25s;
}
html[data-theme="light"] .zammad-form button.btn {
  color: #fff;
}
.zammad-form button.btn:hover {
  filter: brightness(1.08);
}

/* Rückmeldungen nach dem Absenden — ohne Regel stehen sie in der
   Grundfarbe des Browsers. */
.zammad-form .js-danger,
.zammad-form .has-error .help-block {
  color: #ff9b9b;
  font-size: 0.85rem;
}
.zammad-form .js-thankyou,
.zammad-form .zammad-form-thankyou {
  color: var(--ink);
}

/* Der Briefumschlag verlässt die Werkzeugleiste, sobald es eng wird.

   Gemessen bei 390px: Mit dem zusätzlichen Knopf braucht die Zeile
   43px mehr (32px Knopf plus 11,2px Abstand) — nach den Fixes aus
   den vorherigen Runden waren dort noch 0,1px Luft, die Seite lief
   also um 10px über. Unter 1200px steht er stattdessen im
   Burger-Menü, wie der Sprachumschalter. */
@media (max-width: 1200px) {
  .nav-tools #kontaktOeffnen { display: none; }
}

/* Der Eintrag im Burger ist ein <button> — er öffnet ein Modal und
   führt nicht auf eine Adresse. Damit er wie die Links daneben
   aussieht, bekommt er deren Regeln; ein Knopf bringt eigene
   Browservorgaben mit, die hier stören. */
.portals-menu .burger-kontakt {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  width: 100%;
  padding: 0.55rem 0.8rem;
  border: 0;
  border-radius: 9px;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 0.92rem;
  text-align: left;
  cursor: pointer;
  transition: background 0.25s;
}
.portals-menu .burger-kontakt:hover {
  background: rgba(106, 165, 232, 0.10);
}

/* ---------- Überschriften der Unterseiten ----------

   Gemessen bei 1440px gegen die Startseite:

                        Startseite        Unterseite (vorher)
     grosse Zeile       83px / Zeile 85   50px / Zeile 74
     Sperrung           -2,9px            -1,5px
     Akzent (Fraunces)  vorhanden         fehlt

   Der Seitentitel war nicht nur kleiner — seine Zeilenhöhe von 74px
   auf 50px Schrift liess ihn auseinanderfallen, während die Hero-Zeile
   mit 85 auf 83 eng steht. Diese Staffel zieht beide zusammen: Der
   Titel bekommt die Anmutung der Hero-Zeile eine Stufe kleiner, die
   Überschriften darunter folgen im selben Verhältnis wie auf der
   Startseite. */
:root .seiten-kopf h1,
:root main h1.wp-block-post-title {
  font-size: clamp(2.6rem, 5.5vw, 4.2rem);
  line-height: 1.04;
  letter-spacing: -0.035em;
  font-weight: 600;
}

:root .prose h2 {
  font-size: clamp(1.9rem, 3.2vw, 2.6rem);
  line-height: 1.1;
  letter-spacing: -0.025em;
}
:root .prose h3 {
  font-size: clamp(1.3rem, 2vw, 1.6rem);
  line-height: 1.2;
  letter-spacing: -0.015em;
}
:root .prose h4 {
  font-size: 1.2rem;
  line-height: 1.3;
}

/* Der Akzent aus dem Hero steht auch hier zur Verfügung: Wer im
   Editor ein Wort mit der Klasse „accent" auszeichnet, bekommt
   Fraunces kursiv mit dem Blau-Verlauf — dieselbe Regel wie auf der
   Startseite, hier nur in der Größe der jeweiligen Zeile. */
:root .prose .accent,
:root .seiten-kopf .accent {
  font-size: inherit;
}

/* Die Unterzeile im Seitenkopf — dieselbe Rolle wie die Lede unter
   der Hero-Zeile auf der Startseite, eine Stufe kleiner. Der Akzent
   darin erbt seine Größe, damit Fraunces und Hanken Grotesk auf einer
   Linie sitzen. */
:root .seiten-lede {
  margin: 0.9rem 0 0;
  max-width: 46rem;
  color: var(--muted);
  font-size: clamp(1.05rem, 1.6vw, 1.3rem);
  line-height: 1.5;
}
:root .seiten-lede .accent {
  font-size: inherit;
  line-height: inherit;
}

/* Die grosse Zeile bricht ausgewogen statt am Rand.

   „Microsoft sichert das nicht. Wir schon." braucht bei 67px mehr als
   die 1000px des Rasters und bricht deshalb um — ohne Regel fiel der
   Bruch zwischen „Wir" und „schon.", der Akzent stand also auf zwei
   Zeilen verteilt. text-wrap: balance verteilt die Woerter
   gleichmaessig auf die Zeilen; Browser ohne Unterstuetzung brechen
   wie bisher, es geht nichts verloren. */
:root .seiten-kopf h1,
:root main h1.wp-block-post-title {
  text-wrap: balance;
}

/* Der Akzent bleibt zusammen, solange er in eine Zeile passt. Reicht
   der Platz nicht, bricht er normal — nowrap wuerde ihn sonst aus dem
   Raster schieben. */
:root .seiten-kopf h1 .accent {
  white-space: nowrap;
}
@media (max-width: 900px) {
  :root .seiten-kopf h1 .accent { white-space: normal; }
}
