/* ============================================================================
   SAPPER Gebäudemanagement — site styles
   Translated 1:1 from the Claude Design prototype (project/SAPPER Website.dc.html).
   Values (colours, clamps, timings, easings) are carried over verbatim.
   ========================================================================== */

/* ── Fonts ────────────────────────────────────────────────────────────────── */
@font-face {
  font-family: "Plus Jakarta Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/plus-jakarta-sans-latin-400-normal.woff2")
    format("woff2");
}
@font-face {
  font-family: "Plus Jakarta Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/fonts/plus-jakarta-sans-latin-500-normal.woff2")
    format("woff2");
}
@font-face {
  font-family: "Plus Jakarta Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/fonts/plus-jakarta-sans-latin-600-normal.woff2")
    format("woff2");
}
@font-face {
  font-family: "Plus Jakarta Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/assets/fonts/plus-jakarta-sans-latin-700-normal.woff2")
    format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-sans-latin-400-normal.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-sans-latin-500-normal.woff2") format("woff2");
}
@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/fonts/ibm-plex-sans-latin-600-normal.woff2") format("woff2");
}

/* ── Tokens ───────────────────────────────────────────────────────────────── */
:root {
  --bg: #0a0a0a;
  --bg-alt: #101010;
  --card: #131313;
  --panel: #1c1c1c;
  --line: #1e1e1e;
  --line-2: #2e2e2e;
  --line-3: #3a3a3a;
  --head: #ecd7f7;
  --accent: #f0bcc4;
  --cta: #f7cdd2;
  --cta-line: #e6a8b2;
  --blue: #7ba2e8;
  --ink: #f2f2f2;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --sans: "IBM Plex Sans", system-ui, sans-serif;
  --display: "Plus Jakarta Sans", "IBM Plex Sans", system-ui, sans-serif;
}

/* ── Base ─────────────────────────────────────────────────────────────────── */
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
body {
  margin: 0;
  background: var(--bg);
  color: #d8d8d8;
  font-family: var(--sans);
  overflow-x: hidden;
}
* {
  box-sizing: border-box;
}
/* `manual` (the default) means only the soft hyphens that shy() injects may
   break — `auto` would let the browser's German syllable dictionary break
   "Au-ßenanlagengestaltung" too. overflow-wrap stays as the last resort for
   long words that are not in app/hyphenation.php. */
h1,
h2,
h3 {
  overflow-wrap: break-word;
  hyphens: manual;
}
a {
  color: var(--head);
  text-decoration: none;
}
a:hover {
  color: var(--cta);
}
button,
input,
textarea,
select {
  font: inherit;
  color: inherit;
}
img {
  max-width: 100%;
}
::selection {
  background: var(--cta);
  color: #131313;
}
:focus-visible {
  outline: 2px solid var(--cta);
  outline-offset: 2px;
}

.wrap {
  max-width: 1200px;
  margin: 0 auto;
}
.section {
  padding: clamp(58px, 8vw, 108px) 20px;
  scroll-margin-top: 76px;
}
/* Ziel des Skip-Links: ohne scroll-margin landete "Zum Inhalt springen" unter
   dem Sticky-Header (mobil bis 88px hoch). */
main {
  scroll-margin-top: 90px;
}
.band {
  background: var(--bg-alt);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  padding: 12px 18px;
  background: var(--cta);
  color: #131313;
  z-index: 200;
}
.skip:focus {
  left: 12px;
  top: 12px;
}

/* Icons render from the inlined sprite; both packs stroke with currentColor. */
.ico {
  flex: none;
  display: block;
  color: inherit;
}

/* ── Shared type / buttons ────────────────────────────────────────────────── */
.eyebrow {
  margin: 0 0 16px;
  display: inline-block;
  padding: 6px 11px;
  border: 1px solid var(--cta-line);
  color: var(--accent);
  font-size: 10.5px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
.eyebrow--plain {
  margin: 0 0 16px;
  display: block;
  padding: 0;
  border: 0;
  color: #8a8a8a;
}
.h2 {
  margin: 0;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(26px, 5vw, 52px);
  line-height: 1.08;
  letter-spacing: -0.03em;
  color: var(--head);
  text-wrap: balance;
}
.lede {
  margin: 16px 0 0;
  font-size: clamp(15.5px, 2vw, 18px);
  color: #a8a8a8;
}
.lede--italic {
  font-style: italic;
}
.kicker {
  margin: 0 0 14px;
  font-size: 12.5px;
  letter-spacing: 0.18em;
  color: var(--accent);
  text-transform: uppercase;
}

.btn {
  min-height: 52px;
  display: inline-flex;
  align-items: center;
  padding: 16px 26px;
  font-weight: 600;
  font-size: 16px;
  border: 0;
  cursor: pointer;
}
.btn--primary {
  background: var(--cta);
  color: #131313;
}
.btn--primary:hover {
  background: #fff;
  color: #131313;
}
.btn--ghost {
  border: 1px solid #fff;
  color: var(--ink);
  background: none;
}
.btn--ghost:hover {
  background: #1c1c1c;
  color: var(--ink);
}

/* ── Header ───────────────────────────────────────────────────────────────── */
.site-header {
  position: sticky;
  top: 0;
  z-index: 80;
  background: rgba(10, 10, 10, 0.9);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid #262626;
  transition: box-shadow 520ms ease;
}
[data-scrolled] .site-header {
  box-shadow: 0 16px 44px rgba(0, 0, 0, 0.55);
}
.header-bar {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 106px;
  transition: min-height 520ms var(--ease);
}
.logo-link {
  display: flex;
  align-items: center;
  color: var(--ink);
}
.logo-box {
  position: relative;
  display: block;
  height: 80px;
  width: 112px;
  flex: none;
  transition:
    height 520ms var(--ease),
    width 520ms var(--ease);
}
.logo-box img {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  object-fit: contain;
  object-position: left center;
  transition:
    opacity 380ms ease,
    transform 520ms var(--ease);
}
.logo-box .logo-icon {
  opacity: 0;
  transform: scale(0.86);
}
[data-scrolled] .header-bar {
  min-height: 68px;
}
[data-scrolled] .logo-box {
  height: 46px;
  width: 58px;
}
[data-scrolled] .logo-box .logo-full {
  opacity: 0;
  transform: scale(0.92);
}
[data-scrolled] .logo-box .logo-icon {
  opacity: 1;
  transform: none;
}

.nav-desktop {
  display: flex;
  align-items: center;
  gap: 24px;
}
.nav-desktop a {
  font-size: 14.5px;
  color: #bdbdbd;
}
.nav-desktop a:hover {
  color: #fff;
}
.nav-phone {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 14.5px;
  color: var(--ink) !important;
  font-weight: 600;
}
.nav-cta {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 14.5px;
  font-weight: 600;
  color: #131313 !important;
  background: var(--cta);
  padding: 12px 18px;
}
.nav-cta:hover {
  background: #fff;
}

.nav-mobile-tools {
  display: none;
  align-items: center;
  gap: 8px;
}
.call-btn {
  min-width: 46px;
  min-height: 46px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 14px;
  border: 1px solid #fff;
  color: var(--ink);
  font-size: 13.5px;
  font-weight: 600;
  gap: 8px;
}
.burger {
  position: relative;
  width: 46px;
  height: 46px;
  display: block;
  padding: 0;
  background: #1a1a1a;
  border: 1px solid #333;
  cursor: pointer;
}
/* Die drei Balken liegen absolut im Button, damit sie zur Mitte wandern und
   dort um den eigenen Mittelpunkt zum X drehen können. Position (`top`) und
   Drehung (`transform`) sind bewusst getrennt: so lassen sie sich nacheinander
   schalten — erst zusammenschieben, dann drehen (beim Schließen umgekehrt). */
.burger span {
  position: absolute;
  left: 50%;
  display: block;
  width: 18px;
  height: 1px;
  margin: -0.5px 0 0 -9px;
  background: var(--ink);
  transition:
    top 170ms var(--ease) 170ms,
    transform 170ms var(--ease);
}
.burger span:nth-child(1) {
  top: calc(50% - 6px);
}
.burger span:nth-child(3) {
  top: calc(50% + 6px);
}
/* Der mittlere Balken hat nichts zu wandern und blendet einfach aus, während
   die äußeren zusammenlaufen. */
.burger span:nth-child(2) {
  top: 50%;
  transition:
    transform 170ms var(--ease) 170ms,
    opacity 140ms linear 170ms;
}
.burger[aria-expanded="true"] span {
  transition:
    top 170ms var(--ease),
    transform 170ms var(--ease) 170ms;
}
.burger[aria-expanded="true"] span:nth-child(1) {
  top: 50%;
  transform: rotate(45deg);
}
.burger[aria-expanded="true"] span:nth-child(2) {
  transform: scaleX(0);
  opacity: 0;
  transition:
    transform 170ms var(--ease),
    opacity 140ms linear;
}
.burger[aria-expanded="true"] span:nth-child(3) {
  top: 50%;
  transform: rotate(-45deg);
}
/* Aufklappen wie bei den FAQ: die Zeile wächst von 0fr auf 1fr, damit die Höhe
   des Inhalts nirgends bekannt sein muss. Drei Ebenen, wie beim Akkordeon auch:
   das <nav> misst, das leere <div> schneidet ab, erst die Liste darin trägt
   Rahmen und Innenabstand. Läge beides eine Ebene höher, könnte die Zeile nicht
   auf 0 schrumpfen — Rahmen und Padding bleiben als Mindesthöhe stehen. */
.nav-mobile {
  display: grid;
  grid-template-rows: 0fr;
  background: var(--bg-alt);
  transition: grid-template-rows 380ms var(--ease);
}
.nav-mobile[data-open] {
  grid-template-rows: 1fr;
}
.nav-mobile > div {
  overflow: hidden;
  min-height: 0;
  /* Geschlossen ist das Panel nur optisch weg — ohne `visibility` blieben die
     Links in der Tab-Reihenfolge und im Screenreader. Der Wechsel wartet beim
     Schließen die Animation ab, beim Öffnen passiert er sofort. */
  visibility: hidden;
  transition: visibility 0s linear 380ms;
}
.nav-mobile[data-open] > div {
  visibility: visible;
  transition-delay: 0s;
}
.nav-mobile-list {
  display: grid;
  border-top: 1px solid #262626;
  padding: 10px 20px 24px;
}
.nav-mobile a {
  padding: 16px 4px;
  font-size: 17px;
  color: var(--head);
  border-bottom: 1px solid #222;
  opacity: 0;
  transform: translateY(-6px);
  transition:
    opacity 200ms ease,
    transform 280ms var(--ease);
}
/* Gestaffelter Einlauf. Die Liste kommt aus der Konfiguration und kann wachsen:
   alles ab dem siebten Link läuft mit der letzten Stufe mit, statt ohne
   Verzögerung vorauszueilen. Beim Schließen gilt überall 0s — zu bleibt zügig. */
.nav-mobile[data-open] a {
  opacity: 1;
  transform: none;
  transition-delay: 210ms;
}
.nav-mobile[data-open] a:nth-child(1) {
  transition-delay: 60ms;
}
.nav-mobile[data-open] a:nth-child(2) {
  transition-delay: 85ms;
}
.nav-mobile[data-open] a:nth-child(3) {
  transition-delay: 110ms;
}
.nav-mobile[data-open] a:nth-child(4) {
  transition-delay: 135ms;
}
.nav-mobile[data-open] a:nth-child(5) {
  transition-delay: 160ms;
}
.nav-mobile[data-open] a:nth-child(6) {
  transition-delay: 185ms;
}
.nav-mobile .nav-mobile-cta {
  margin-top: 14px;
  padding: 17px;
  text-align: center;
  font-size: 16px;
  font-weight: 600;
  color: #131313;
  background: var(--cta);
  border-bottom: 0;
}
/* Oberhalb der Umbruchbreite hat das Panel nichts zu suchen; sonst stünde ein
   0 Pixel hohes Grid mitsamt Links dauerhaft im Dokument. */
@media (min-width: 901px) {
  .nav-mobile {
    display: none;
  }
}
/* Weniger Bewegung: Burger und Panel wechseln den Zustand, nur eben sofort. */
@media (prefers-reduced-motion: reduce) {
  .burger span,
  .burger span:nth-child(2),
  .burger[aria-expanded="true"] span,
  .burger[aria-expanded="true"] span:nth-child(2),
  .nav-mobile,
  .nav-mobile > div,
  .nav-mobile a,
  .nav-mobile[data-open] a {
    transition: none;
  }
  .nav-mobile a {
    opacity: 1;
    transform: none;
  }
}

@media (max-width: 900px) {
  .header-bar {
    min-height: 88px;
  }
  .logo-box {
    height: 62px;
    width: 88px;
  }
  [data-scrolled] .header-bar {
    min-height: 62px;
  }
  [data-scrolled] .logo-box {
    height: 40px;
    width: 50px;
  }
  .nav-desktop {
    display: none;
  }
  .nav-mobile-tools {
    display: flex;
  }
}

/* ── Motion / reveal ──────────────────────────────────────────────────────── */
/* Content is visible by default; JS opts in to hiding so a failed script or a
   no-JS visitor never sees a blank page. */
[data-reveal] {
  opacity: 1;
}
@keyframes sapperKen {
  from {
    transform: scale(1.02);
  }
  to {
    transform: scale(1.13);
  }
}
@media (prefers-reduced-motion: no-preference) {
  [data-kenburns] {
    animation: sapperKen 28s cubic-bezier(0.33, 0, 0.25, 1) both;
  }
}
/* Pre-reveal resting state. Plain declarations, so an element the observer
   never reaches (scrolled past, JS half-booted) simply stays hidden. */
[data-anim-on] [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 26px, 0);
}
[data-anim-on] [data-reveal="fade"] {
  transform: none;
}
[data-anim-on] [data-reveal="left"] {
  transform: translate3d(-30px, 0, 0);
}
[data-anim-on] [data-reveal="right"] {
  transform: translate3d(30px, 0, 0);
}
[data-anim-on] [data-reveal="scale"] {
  transform: scale(0.968);
  filter: blur(6px);
}
[data-anim-on] [data-reveal="hero"] {
  transform: translate3d(0, 34px, 0);
  filter: blur(9px);
}
[data-anim-on] [data-reveal="hero-img"] {
  transform: translate3d(30px, 0, 0) scale(0.965);
  filter: blur(8px);
}

/* The entrance is an animation rather than a transition, and that is the whole
   point: a transition has to be declared on the element itself, and
   `[data-anim-on] [data-reveal]` outranks `.svc-card`, so a card hovered while
   it was still revealing borrowed the 900ms reveal timing and its stagger
   delay instead of its own hover speed. Animations sit in their own cascade
   level and never touch `transition`, so hover keeps its own timing throughout.

   The reveal does still own `transform` on the [data-reveal] element itself
   for as long as it runs, and a running animation outranks any normal
   declaration for the property it animates. A hover effect on that same
   element would therefore be ignored mid-reveal and has to move a different
   property (standalone `scale` / `translate` compose rather than compete).
   Nested children are unaffected — .svc-text hovers on plain `transform`.

   Each @keyframes declares only `from`, so the implied `to` is whatever the
   element's own styles resolve to and no end state has to be duplicated here.
   `backwards` holds the from-state through the staggered `--rd` delay, and
   nothing is held afterwards — once the animation is done the element is back
   under its own rules. */
[data-anim-on] [data-reveal][data-shown] {
  opacity: 1;
  transform: none;
  filter: none;
  animation: sapperReveal 900ms var(--ease) var(--rd, 0ms) backwards;
}
[data-anim-on] [data-reveal="fade"][data-shown] {
  animation-name: sapperRevealFade;
}
[data-anim-on] [data-reveal="left"][data-shown] {
  animation-name: sapperRevealLeft;
}
[data-anim-on] [data-reveal="right"][data-shown] {
  animation-name: sapperRevealRight;
}
[data-anim-on] [data-reveal="scale"][data-shown] {
  animation-name: sapperRevealScale;
}
[data-anim-on] [data-reveal="hero"][data-shown] {
  animation-name: sapperRevealHero;
  animation-duration: 1150ms;
}
[data-anim-on] [data-reveal="hero-img"][data-shown] {
  animation-name: sapperRevealHeroImg;
  animation-duration: 1300ms;
}

/* The headline arrives sentence by sentence instead of as one block. The <h1>
   stays a normal reveal target so it keeps its slot in the hero cascade and
   still gets an `--rd` from the stagger pass, but nothing animates on the
   heading itself — the lines inside it do, each one `--ld` behind the first.
   `--rd` inherits, so a line's delay is the heading's own delay plus its
   offset, and the last line lands well inside the cleanup timeout in site.js.
   The lines stay in flow while hidden (inline-block, not absolute), so the
   heading occupies its final height from the first paint and nothing reflows
   as the sentences appear. */
[data-anim-on] [data-reveal="lines"] {
  opacity: 1;
  transform: none;
}
[data-anim-on] [data-reveal="lines"][data-shown] {
  animation: none;
}
[data-anim-on] [data-reveal="lines"] > .hero-line {
  opacity: 0;
  transform: translate3d(0, 34px, 0);
  filter: blur(9px);
}
[data-anim-on] [data-reveal="lines"][data-shown] > .hero-line {
  opacity: 1;
  transform: none;
  filter: none;
  animation: sapperRevealHero 950ms var(--ease)
    calc(var(--rd, 0ms) + var(--ld, 0ms)) backwards;
}
@keyframes sapperReveal {
  from {
    opacity: 0;
    transform: translate3d(0, 26px, 0);
  }
}
@keyframes sapperRevealFade {
  from {
    opacity: 0;
  }
}
@keyframes sapperRevealLeft {
  from {
    opacity: 0;
    transform: translate3d(-30px, 0, 0);
  }
}
@keyframes sapperRevealRight {
  from {
    opacity: 0;
    transform: translate3d(30px, 0, 0);
  }
}
@keyframes sapperRevealScale {
  from {
    opacity: 0;
    transform: scale(0.968);
    filter: blur(6px);
  }
}
@keyframes sapperRevealHero {
  from {
    opacity: 0;
    transform: translate3d(0, 34px, 0);
    filter: blur(9px);
  }
}
@keyframes sapperRevealHeroImg {
  from {
    opacity: 0;
    transform: translate3d(30px, 0, 0) scale(0.965);
    filter: blur(8px);
  }
}

/* ── Hero ─────────────────────────────────────────────────────────────────── */
.hero {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
}
.hero-bg {
  position: absolute;
  inset: -24px;
  width: calc(100% + 48px);
  height: calc(100% + 48px);
  object-fit: cover;
  filter: blur(3px) saturate(0.85);
  transform: scale(1.06);
}
.hero-veil-a,
.hero-veil-b {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.hero-veil-a {
  background: linear-gradient(
    104deg,
    rgba(10, 10, 10, 0.86) 0%,
    rgba(10, 10, 10, 0.74) 42%,
    rgba(10, 10, 10, 0.42) 72%,
    rgba(10, 10, 10, 0.68) 100%
  );
}
.hero-veil-b {
  background: linear-gradient(
    180deg,
    rgba(10, 10, 10, 0.38) 0%,
    rgba(10, 10, 10, 0.06) 40%,
    var(--bg) 100%
  );
}
.hero-inner {
  position: relative;
  max-width: 1200px;
  margin: 0 auto;
  padding: clamp(52px, 8vw, 104px) 20px;
  display: grid;
  gap: clamp(32px, 5vw, 56px);
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  align-items: center;
}
.hero h1 {
  margin: 0;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(30px, 7.4vw, 74px);
  line-height: 1.06;
  letter-spacing: -0.033em;
  color: var(--head);
  text-wrap: balance;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
/* Unconditional, not part of the reveal rules: the lines animate with a
   transform, which needs a block-ish box, and the display must not change when
   site.js strips the reveal hooks afterwards or the heading would re-wrap. */
.hero-line {
  display: inline-block;
}
.hero .eyebrow {
  margin: 0 0 24px;
  padding: 7px 12px;
}
.hero-lede {
  margin: 24px 0 0;
  max-width: 560px;
  font-size: clamp(15.5px, 2vw, 18px);
  line-height: 1.68;
  color: #a8a8a8;
  text-wrap: pretty;
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 34px;
}
.trust {
  margin: 28px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  font-size: 14px;
  color: #7a7a7a;
}
.trust li {
  display: flex;
  align-items: center;
  gap: 9px;
}
.hero-media {
  position: relative;
  min-height: clamp(300px, 42vw, 470px);
}
.hero-media figure {
  margin: 0;
  position: relative;
  border-radius: 6px;
}
.hero-media img {
  display: block;
  width: 100%;
  /* The intrinsic width/height attributes would otherwise pin the height and
     defeat aspect-ratio. */
  height: auto;
  object-fit: cover;
  border: 1px solid var(--line-3);
  border-radius: 6px;
}
.hero-media .hero-fig-1 {
  width: 74%;
  margin-left: auto;
  box-shadow: 0 30px 70px rgba(0, 0, 0, 0.6);
}
.hero-media .hero-fig-1 img {
  aspect-ratio: 4 / 3;
}
.hero-media .hero-fig-2 {
  z-index: 2;
  width: 46%;
  margin-top: -16%;
  margin-left: 2%;
  box-shadow: 0 26px 60px rgba(0, 0, 0, 0.65);
}
.hero-media .hero-fig-2 img {
  aspect-ratio: 1 / 1;
}

/* ── Kennzahlen ───────────────────────────────────────────────────────────── */
.stats {
  position: relative;
  overflow: hidden;
  background: var(--bg-alt);
  border-bottom: 1px solid var(--line);
}
.stats-glow {
  position: absolute;
  left: 50%;
  top: -70%;
  width: min(1150px, 130%);
  height: 240%;
  transform: translateX(-50%);
  pointer-events: none;
  background: radial-gradient(
    ellipse at 50% 50%,
    rgba(240, 188, 196, 0.1) 0%,
    rgba(240, 188, 196, 0.035) 42%,
    rgba(16, 16, 16, 0) 72%
  );
}
.stats-grid {
  position: relative;
  max-width: 1200px;
  margin: 0 auto;
  padding: clamp(34px, 5vw, 62px) 20px;
  display: grid;
  gap: clamp(22px, 3vw, 36px);
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
}
/* Ruhezustand vor dem Count-up. Das Attribut setzt das Inline-Skript im <head>,
   also vor dem ersten Paint; site.js nimmt es wieder weg, sobald die
   Einblend-Animation die Kacheln übernommen hat oder gar nicht erst läuft. */
[data-stats-pending] [data-stats] > [data-stat] {
  opacity: 0;
}
.stat-num {
  display: flex;
  align-items: baseline;
  gap: 1px;
  font-family: var(--display);
  font-size: clamp(34px, 5vw, 52px);
  font-weight: 400;
  letter-spacing: -0.035em;
  line-height: 1;
  color: #fff;
  text-shadow:
    0 2px 2px rgba(0, 0, 0, 0.6),
    0 18px 40px rgba(255, 255, 255, 0.14);
}
.stat-num > span:first-child {
  font-variant-numeric: tabular-nums;
}
.stat-label {
  margin-top: 14px;
  font-size: 15px;
  font-weight: 600;
  color: #fff;
}
.stat-note {
  margin-top: 5px;
  font-size: 13.5px;
  color: #7a7a7a;
  line-height: 1.5;
}

/* ── Leistungen ───────────────────────────────────────────────────────────── */
#leistungen .h2 {
  max-width: 780px;
  font-size: clamp(26px, 5.4vw, 56px);
}
.section-note {
  margin: 18px 0 0;
  max-width: 640px;
  font-size: 16px;
  line-height: 1.68;
  color: #8f8f8f;
  text-wrap: pretty;
}
/* Flex rather than an auto-fit grid: 1fr tracks always fill their row, so a
   short last row can only ever be left-packed. Flex wraps on flex-basis and
   justify-content centres whatever is left over — ten cards read 4/4/2 with the
   pair centred, and 3/3/3/1 with the single card centred.
   The bases below reproduce exactly the column counts minmax(260px, 1fr) used
   to resolve to, so card widths are unchanged and the images' `sizes` attribute
   still holds. They key off the grid's own width rather than the viewport's:
   N columns need N*260 + (N-1)*gap, and a viewport breakpoint would have to
   guess at .wrap's max-width, the section padding, and whatever the platform
   reserves for a scrollbar — 15px of which is enough to push cards under 260. */
.svc-grid {
  --svc-gap: 10px;
  container: svc-grid / inline-size;
  margin-top: clamp(30px, 4vw, 48px);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--svc-gap);
}
/* grow:0 is load-bearing — grow:1 would stretch the two orphans across the full
   row and there would be nothing left to centre. */
.svc-card {
  flex: 0 1 100%;
  position: relative;
  overflow: hidden;
  border: 1px solid #fff;
  background: var(--card);
  min-height: 320px;
}
/* 2 * 260 + 1 gap */
@container svc-grid (min-width: 530px) {
  .svc-card {
    flex-basis: calc((100% - var(--svc-gap)) / 2);
  }
}
/* 3 * 260 + 2 gaps */
@container svc-grid (min-width: 800px) {
  .svc-card {
    flex-basis: calc((100% - 2 * var(--svc-gap)) / 3);
  }
}
/* 4 * 260 + 3 gaps. .wrap caps at 1200, so a fifth column never fits. */
@container svc-grid (min-width: 1070px) {
  .svc-card {
    flex-basis: calc((100% - 3 * var(--svc-gap)) / 4);
  }
}
.svc-card > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 42%;
  /* Deliberately slower than the text and the arrow. The photo is the largest
     thing in motion, and at their pace the zoom reads as a jolt instead of a
     drift. .svc-card clips it, so it grows inside the frame. */
  transition: transform 800ms var(--ease);
}
/* Keyed off the card, not the link: the <img> is a *preceding* sibling of
   .svc-link, so no sibling combinator can reach it from there. :has() gives
   the keyboard case the same treatment .svc-text gets from :focus-visible. */
.svc-card:hover > img,
.svc-card:has(.svc-link:focus-visible) > img {
  transform: scale(1.04);
}
.svc-shade {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    to top,
    rgba(8, 8, 8, 0.95) 0%,
    rgba(8, 8, 8, 0.88) 34%,
    rgba(8, 8, 8, 0.5) 62%,
    rgba(8, 8, 8, 0.12) 100%
  );
}
.svc-link {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  align-content: end;
  padding: clamp(20px, 2.6vw, 28px);
  color: inherit;
  text-decoration: none;
  transition: background 400ms var(--ease);
}
.svc-link:hover {
  background: rgba(25, 25, 25, 0.18);
  color: inherit;
}
/* The link fills the card edge to edge, so the global outline-offset:2px would
   land outside .svc-card and be cut off by its overflow:hidden. Draw it inside. */
.svc-link:focus-visible {
  outline-offset: -4px;
}
.svc-arrow {
  position: absolute;
  top: clamp(20px, 2.6vw, 28px);
  right: clamp(20px, 2.6vw, 28px);
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line-3);
  background: rgba(8, 8, 8, 0.55);
  color: var(--accent);
  font-size: 20px;
  line-height: 1;
  transition:
    transform 240ms cubic-bezier(0.2, 0.7, 0.2, 1),
    background 240ms ease,
    opacity 240ms ease;
}
@media (hover: hover) {
  .svc-arrow {
    opacity: 0;
  }
  .svc-card:hover .svc-arrow,
  .svc-link:focus-visible .svc-arrow {
    opacity: 1;
  }
}
.svc-link:hover .svc-arrow,
.svc-link:focus-visible .svc-arrow {
  transform: translate(5px, -5px);
  background: rgba(8, 8, 8, 0.75);
}
.svc-text {
  display: grid;
  gap: 5px;
  /* Shares the arrow's easing curve so the two read as one gesture, a touch
     slower because it travels further. Plain `transform` is fine here: the
     reveal animation only ever targets the [data-reveal] element itself — the
     <article> — so nothing competes for this property on a nested node. */
  transition: transform 480ms cubic-bezier(0.2, 0.7, 0.2, 1);
}
.svc-link:hover .svc-text,
.svc-link:focus-visible .svc-text {
  transform: translateX(4px) translateY(-4px);
}
.svc-card h3 {
  margin: 0;
  font-family: var(--display);
  font-size: clamp(16px, 2.4vw, 23px);
  font-weight: 500;
  letter-spacing: -0.015em;
  color: #f7f7f7;
}
.svc-sub {
  font-size: 14.5px;
  color: #b4b4b4;
  line-height: 1.5;
}

/* ── Spezialleistungen ────────────────────────────────────────────────────── */
#spezialleistungen .h2 {
  max-width: 720px;
}
.special-grid {
  margin-top: clamp(28px, 4vw, 44px);
  display: grid;
  gap: 14px 28px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.special {
  display: flex;
  gap: 14px;
  padding: 4px 0 4px 14px;
  border-left: 2px solid #fff;
}
.special .ico {
  color: #8a8a8a;
}
.special-text {
  display: grid;
  gap: 6px;
}
.special-title {
  font-size: 17px;
  font-weight: 600;
  color: var(--ink);
}
.special-sub {
  font-size: 14px;
  color: #8a8a8a;
  line-height: 1.55;
}
.special-foot {
  margin: 30px 0 0;
  max-width: 680px;
  font-size: 15.5px;
  color: #8a8a8a;
  line-height: 1.68;
}

/* ── Über uns ─────────────────────────────────────────────────────────────── */
.about-grid {
  margin-top: clamp(28px, 4vw, 44px);
  display: grid;
  gap: clamp(24px, 3.5vw, 44px);
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.about-panel {
  padding: clamp(22px, 3vw, 32px);
  background: var(--panel);
}
.about-panel p {
  margin: 0;
  font-size: 16.5px;
  line-height: 1.72;
  color: #d4d4d4;
  text-wrap: pretty;
}
.about-panel p + p {
  margin-top: 20px;
}
.about-aside p {
  margin: 0;
  font-size: 15.5px;
  line-height: 1.72;
  color: #a4a4a4;
  text-wrap: pretty;
}
.about-aside p + p {
  margin-top: 18px;
}
.values {
  margin-top: 28px;
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.value {
  padding-left: 14px;
  border-left: 2px solid var(--accent);
}
.value-title {
  font-size: 15.5px;
  font-weight: 600;
  color: var(--ink);
}
.value-text {
  margin-top: 5px;
  font-size: 14px;
  color: #8a8a8a;
  line-height: 1.55;
}

/* ── Warum SAPPER ─────────────────────────────────────────────────────────── */
#warum {
  padding: clamp(54px, 7.5vw, 96px) 20px;
}
#warum .h2 {
  max-width: 720px;
  font-size: clamp(27px, 5vw, 50px);
  color: var(--ink);
}
#warum .lede {
  color: var(--blue);
}
.reasons {
  margin-top: clamp(28px, 4vw, 44px);
}
.reason-track {
  position: relative;
  display: grid;
  overflow: hidden;
  background: var(--panel);
  border-left: 2px solid var(--accent);
}
.reason-slide {
  grid-area: 1 / 1;
  opacity: 0;
  transform: translate3d(5%, 0, 0) scale(0.985);
  filter: blur(5px);
  pointer-events: none;
  transition:
    opacity 620ms var(--ease),
    transform 780ms var(--ease),
    filter 620ms ease;
  will-change: opacity, transform;
}
.reason-track[data-dir="-1"] .reason-slide {
  transform: translate3d(-5%, 0, 0) scale(0.985);
}
.reason-slide[data-active] {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  filter: blur(0);
  pointer-events: auto;
}
.reason-inner {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  align-items: stretch;
  min-height: clamp(300px, 32vw, 380px);
}
.reason-media {
  position: relative;
  overflow: hidden;
  min-height: 220px;
  background: var(--card);
}
.reason-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.reason-media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    rgba(28, 28, 28, 0.18) 0%,
    rgba(28, 28, 28, 0.05) 55%,
    rgba(28, 28, 28, 0.75) 100%
  );
}
.reason-body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 14px;
  padding: clamp(24px, 3.4vw, 46px);
}
.reason-head {
  display: flex;
  align-items: center;
  gap: 14px;
}
.reason-head .ico {
  color: var(--accent);
}
.reason-num {
  font-family: var(--display);
  font-size: 11.5px;
  letter-spacing: 0.2em;
  color: #6e6e6e;
}
.reason-body h3 {
  margin: 0;
  max-width: 460px;
  font-family: var(--display);
  font-size: clamp(22px, 2.6vw, 31px);
  font-weight: 500;
  line-height: 1.14;
  letter-spacing: -0.025em;
  color: var(--ink);
  text-wrap: balance;
}
.reason-body p {
  margin: 0;
  max-width: 480px;
  font-size: clamp(15px, 1.5vw, 16.5px);
  line-height: 1.7;
  color: #a4a4a4;
  text-wrap: pretty;
}
.reason-controls {
  margin-top: 16px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}
.reason-tabs {
  display: flex;
  align-items: center;
  gap: 8px;
}
.reason-tab {
  width: 14px;
  height: 3px;
  padding: 0;
  border: none;
  background: var(--line-3);
  cursor: pointer;
  transition:
    width 620ms var(--ease),
    background 400ms ease;
}
.reason-tab[aria-selected="true"] {
  width: 44px;
  background: var(--accent);
}
.reason-nav {
  display: flex;
  align-items: center;
  gap: 8px;
}
.reason-nav button {
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line-2);
  background: transparent;
  color: #c4c4c4;
  cursor: pointer;
  transition:
    border-color 300ms ease,
    background 300ms ease;
}
.reason-nav button:hover {
  border-color: var(--accent);
  background: #232323;
}

/* ── Servicegebiet ────────────────────────────────────────────────────────── */
#servicegebiet .lede {
  max-width: 720px;
}
.region-grid {
  margin-top: clamp(28px, 4vw, 44px);
  display: grid;
  gap: clamp(24px, 3.5vw, 44px);
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.region-tiles {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.region-tile {
  position: relative;
  overflow: hidden;
  aspect-ratio: 1 / 1;
  background: var(--panel);
  border: 1px solid var(--line-2);
  display: flex;
  align-items: flex-end;
}
.region-tile img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.region-tile::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    to top,
    rgba(8, 8, 8, 0.94) 0%,
    rgba(8, 8, 8, 0.8) 38%,
    rgba(8, 8, 8, 0.35) 66%,
    rgba(8, 8, 8, 0.08) 100%
  );
}
.region-cap {
  position: relative;
  z-index: 1;
  padding: 16px 18px 18px;
}
.region-name {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--display);
  /* Caps at the design's 18.5px from ~465px viewport up; below that the tiles
     get too narrow for "Schwetzingen" and the name would be clipped. */
  font-size: clamp(14px, 4vw, 18.5px);
  font-weight: 500;
  color: var(--ink);
}
.region-name .ico {
  color: var(--accent);
}
.region-note {
  margin-top: 4px;
  font-size: 13.5px;
  color: #c0c0c0;
  line-height: 1.5;
}
.region-chips {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.region-chips li {
  padding: 10px 14px;
  border: 1px solid var(--line-2);
  font-size: 14.5px;
  color: #c4c4c4;
}
.map-col {
  display: grid;
  gap: 14px;
  align-content: start;
}
.map-frame {
  position: relative;
  border: 1px solid var(--line-2);
  background: #111;
  /* Eigener Stacking-Kontext: Leaflets Controls (z-index 1000) dürfen den
     Sticky-Header (80) und den Cookie-Hinweis (120) nicht übermalen. */
  isolation: isolate;
}
#map {
  aspect-ratio: 1 / 1;
  width: 100%;
}
.map-note {
  padding: clamp(20px, 2.6vw, 26px);
  background: var(--panel);
  border: 1px solid var(--line-2);
}
.map-note h3 {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--display);
  font-size: 19px;
  font-weight: 500;
  color: var(--ink);
}
.map-note h3 .ico {
  color: var(--accent);
}
.map-note p {
  margin: 10px 0 0;
  font-size: 15px;
  line-height: 1.65;
  color: #a4a4a4;
}
.map-note a {
  display: inline-block;
  margin-top: 16px;
  font-size: 15px;
  font-weight: 600;
  color: var(--accent);
}

/* Leaflet skin — matches the prototype's dark treatment. leaflet.css is injected
   at runtime, so it lands after this file in the cascade: the overrides that it
   also declares need !important to win. */
.leaflet-container {
  background: #111 !important;
  font-family: var(--sans) !important;
}
.leaflet-tile-pane {
  /* Die selbst gehosteten OSM-Standardkacheln sind hell; invert() holt den
     dunklen Look der früheren CARTO-dark-Kacheln zurück. */
  filter: grayscale(1) invert(1) brightness(0.88) contrast(0.92);
}
.leaflet-control-attribution {
  background: rgba(10, 10, 10, 0.72) !important;
  color: #5f5f5f !important;
  font-size: 9px !important;
}
.leaflet-control-attribution a {
  color: #7d7d7d !important;
}
.leaflet-bar {
  border: 1px solid var(--line-2) !important;
  box-shadow: none !important;
}
.leaflet-bar a {
  background: #141414 !important;
  color: #cfcfcf !important;
  border-bottom-color: var(--line-2) !important;
}
.leaflet-bar a:hover {
  background: #1f1f1f !important;
  color: var(--accent) !important;
}

/* ── Referenzen ───────────────────────────────────────────────────────────── */
#referenzen .h2 {
  max-width: 620px;
  font-size: clamp(27px, 5vw, 52px);
}
.quote-grid {
  margin-top: clamp(28px, 4vw, 44px);
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
/* The client asked for a 2x2 grid; below ~600px two columns leave ~18 characters
   per line, so phones fall back to a single column. */
@media (max-width: 599px) {
  .quote-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}
.quote {
  margin: 0;
  padding: clamp(20px, 2.6vw, 28px);
  border: 1px solid #fff;
  background: var(--card);
}
.stars {
  color: var(--blue);
  font-size: 14px;
  letter-spacing: 0.22em;
}
.quote blockquote {
  margin: 16px 0 0;
  font-size: 15.5px;
  font-style: italic;
  line-height: 1.7;
  color: #d4d4d4;
  text-wrap: pretty;
}
.quote figcaption {
  margin-top: 18px;
  font-size: 14px;
  color: #8a8a8a;
}
.quote figcaption strong {
  font-weight: 600;
  color: #e0e0e0;
}
.quote-foot {
  margin: 26px 0 0;
  font-size: 15px;
  color: #7a7a7a;
  text-align: center;
}

/* ── Kontakt ──────────────────────────────────────────────────────────────── */
#kontakt {
  background: var(--bg-alt);
  border-top: 1px solid var(--line);
}
#kontakt .h2 {
  max-width: 760px;
  font-size: clamp(28px, 6vw, 64px);
  line-height: 1.06;
}
#kontakt .lede {
  margin-top: 18px;
  max-width: 620px;
  line-height: 1.68;
  color: #a4a4a4;
}
.contact-grid {
  margin-top: clamp(30px, 4vw, 48px);
  display: grid;
  gap: clamp(20px, 3vw, 36px);
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  align-items: start;
}
.contact-card {
  padding: clamp(22px, 3vw, 32px);
  background: var(--panel);
}
.form-card {
  padding: clamp(22px, 3vw, 32px);
  border: 1px solid #fff;
}
.card-eyebrow {
  margin: 0 0 6px;
  font-size: 10.5px;
  letter-spacing: 0.18em;
  color: var(--accent);
  text-transform: uppercase;
}
.card-title {
  margin: 0 0 24px;
  font-family: var(--display);
  font-size: 23px;
  font-weight: 500;
  color: var(--ink);
}
.form-card .card-title {
  margin-bottom: 8px;
}
.form-intro {
  margin: 0 0 24px;
  font-size: 15px;
  line-height: 1.65;
  color: #8a8a8a;
}
.contact-list {
  margin: 0;
  display: grid;
  gap: 20px;
}
.contact-list > div {
  padding-left: 14px;
  border-left: 2px solid #fff;
}
/* Die Zeilen kaskadieren einzeln herein, einen Takt hinter der Karte selbst —
   erst steht der Rahmen, dann füllen sich die Angaben nacheinander. Nur die
   Verzögerung wird überschrieben, den Rest der Animation setzt die
   allgemeine Reveal-Regel. */
[data-anim-on] .contact-list > [data-reveal][data-shown] {
  animation-delay: calc(var(--rd, 0ms) + 220ms);
}
.contact-list dt {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: #8a8a8a;
}
.contact-list dd {
  margin: 6px 0 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  overflow-wrap: anywhere;
}
.contact-list dd a {
  color: var(--ink);
}

.form {
  display: grid;
  gap: 16px;
}
.form label {
  display: grid;
  gap: 7px;
}
.form label > span {
  font-size: 14px;
  color: #b4b4b4;
}
.form input[type="text"],
.form input[type="email"],
.form input[type="tel"],
.form select,
.form textarea {
  padding: 13px 14px;
  background: var(--card);
  border: 1px solid var(--line-3);
  color: var(--ink);
  font-size: 16px;
  width: 100%;
  border-radius: 0;
}
.form input[type="text"],
.form input[type="email"],
.form input[type="tel"],
.form select {
  min-height: 50px;
}
.form textarea {
  resize: vertical;
}
.form-row {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.form-consent {
  display: flex !important;
  gap: 11px;
  align-items: flex-start;
  font-size: 14px;
  color: #a4a4a4;
  line-height: 1.55;
}
.form-consent a {
  color: var(--accent);
  text-decoration: underline;
}
.form-consent input {
  margin-top: 3px;
  width: 18px;
  height: 18px;
  flex: none;
  accent-color: var(--cta);
}
.form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 6px;
}
.form-hint {
  margin: 4px 0 0;
  font-size: 13px;
  color: #6e6e6e;
}
.form-sent {
  padding: 20px;
  background: var(--panel);
  border-left: 2px solid var(--accent);
}
.form-sent p {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
}
.form-sent p + p {
  margin-top: 8px;
  font-size: 15px;
  font-weight: 400;
  line-height: 1.6;
  color: #a4a4a4;
}
.form-sent a {
  color: var(--accent);
}

/* Honeypot. Positioned off-screen rather than display:none — many bots skip
   hidden fields but happily fill ones that are merely moved out of view. */
.hp {
  position: absolute !important;
  left: -9999px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Server-side validation feedback. */
.form-errors {
  margin-bottom: 18px;
  padding: 16px 18px;
  background: var(--panel);
  border-left: 2px solid #e0574b;
}
.form-errors p {
  margin: 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink);
}
.form-errors p + p {
  margin-top: 6px;
  color: #a4a4a4;
}
.form-errors a {
  color: var(--accent);
}
.form-errors:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.field-error {
  font-size: 13px;
  color: #e0574b;
}
.form [aria-invalid="true"] {
  border-color: #e0574b;
}
.form button[data-busy="true"] {
  opacity: 0.6;
  cursor: progress;
}

[hidden] {
  display: none !important;
}

/* ── FAQ ──────────────────────────────────────────────────────────────────── */
.faq-grid {
  max-width: 1200px;
  margin: 0 auto;
  display: grid;
  gap: clamp(28px, 4vw, 52px);
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  align-items: start;
}
#faq .h2 {
  font-size: clamp(27px, 5vw, 52px);
}
.faq-intro {
  margin: 18px 0 0;
  max-width: 420px;
  font-size: 16px;
  line-height: 1.68;
  color: #a4a4a4;
}
.faq-figures {
  margin-top: 32px;
  display: grid;
  gap: 24px;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
}
.faq-fig-num {
  font-family: var(--display);
  font-size: clamp(30px, 4.4vw, 44px);
  line-height: 1;
  color: var(--ink);
}
.faq-fig-label {
  margin-top: 8px;
  font-size: 14.5px;
  color: #8a8a8a;
}
.faq-list {
  display: grid;
  gap: 10px;
}
.faq-item {
  border: 1px solid #fff;
  background: var(--card);
}
.faq-item h3 {
  margin: 0;
}
.faq-q {
  width: 100%;
  min-height: 60px;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 20px;
  background: none;
  border: 0;
  text-align: left;
  cursor: pointer;
}
.faq-q > span:first-child {
  flex: 1;
  font-family: var(--display);
  font-size: 16.5px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--ink);
}
.faq-plus {
  flex: none;
  position: relative;
  width: 30px;
  height: 30px;
  border: 1px solid var(--line-3);
}
.faq-plus i {
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--accent);
}
.faq-plus i:first-child {
  width: 11px;
  height: 1.5px;
  margin-top: -0.75px;
  margin-left: -5.5px;
}
.faq-plus i:last-child {
  width: 1.5px;
  height: 11px;
  margin-top: -5.5px;
  margin-left: -0.75px;
  transform: scaleY(1);
  transition: transform 340ms var(--ease);
}
.faq-q[aria-expanded="true"] .faq-plus i:last-child {
  transform: scaleY(0);
}
.faq-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 400ms var(--ease);
}
/* The button is wrapped in an <h3>, so it is not a sibling of the panel — JS
   marks the article instead of relying on a sibling combinator. */
.faq-item[data-open] .faq-panel {
  grid-template-rows: 1fr;
}
.faq-panel > div {
  overflow: hidden;
  min-height: 0;
  /* Wie beim mobilen Menü (.nav-mobile > div): zugeklappt auch aus dem
     Accessibility-Tree und der Seitensuche nehmen — sonst liest ein
     Screenreader alle Antworten trotz aria-expanded="false" vor. */
  visibility: hidden;
  transition: visibility 0s linear 400ms;
}
.faq-item[data-open] .faq-panel > div {
  visibility: visible;
  transition-delay: 0s;
}
.faq-panel p {
  margin: 0;
  padding: 0 20px 22px;
  font-size: 15.5px;
  line-height: 1.7;
  color: #a4a4a4;
  text-wrap: pretty;
  opacity: 0;
  transform: translateY(-8px);
  transition:
    opacity 300ms ease,
    transform 400ms var(--ease);
}
.faq-item[data-open] .faq-panel p {
  opacity: 1;
  transform: translateY(0);
  transition-delay: 80ms;
}

/* ── Footer ───────────────────────────────────────────────────────────────── */
.site-footer {
  border-top: 1px solid var(--line);
  background: var(--bg);
}
.footer-inner {
  max-width: 1200px;
  margin: 0 auto;
  padding: clamp(44px, 6vw, 76px) 20px clamp(28px, 3vw, 40px);
}
.footer-logo {
  display: block;
  height: 96px;
  width: auto;
  margin-bottom: clamp(22px, 3vw, 32px);
}
.footer-claim {
  margin: 0 0 clamp(28px, 4vw, 44px);
  max-width: 1100px;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(22px, 3.4vw, 38px);
  line-height: 1.14;
  letter-spacing: -0.025em;
  color: var(--ink);
  text-wrap: balance;
}
.footer-cols {
  display: grid;
  gap: clamp(24px, 3vw, 36px);
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.footer-cols h3 {
  margin: 0 0 14px;
  font-size: 12.5px;
  letter-spacing: 0.18em;
  color: var(--accent);
  text-transform: uppercase;
}
.footer-about {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.7;
  color: #8f8f8f;
}
.footer-cols ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 9px;
  font-size: 14.5px;
}
.footer-services a {
  color: #b4b4b4;
}
.footer-regions {
  color: #8f8f8f;
}
.footer-contact {
  color: #8f8f8f;
  overflow-wrap: anywhere;
}
.footer-contact li {
  display: flex;
  gap: 10px;
}
.footer-contact .ico {
  margin-top: 3px;
}
.footer-contact a {
  color: var(--ink);
}
.footer-bottom {
  margin-top: clamp(30px, 4vw, 48px);
  padding-top: 22px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 12px 24px;
  justify-content: space-between;
  align-items: center;
}
.footer-bottom p {
  margin: 0;
  font-size: 13.5px;
  color: #6e6e6e;
}
.footer-bottom nav {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}
.footer-bottom nav a {
  font-size: 13.5px;
  color: #8f8f8f;
}

/* ── Cookie-Hinweis ───────────────────────────────────────────────────────── */
.cookie {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: 12px;
  z-index: 120;
  padding: clamp(18px, 2.4vw, 24px);
  background: var(--card);
  border: 1px solid #fff;
  display: grid;
  gap: 16px;
  max-width: 1176px;
  margin: 0 auto;
}
.cookie-title {
  margin: 0 0 8px;
  font-family: var(--display);
  font-size: 16.5px;
  font-weight: 600;
  color: var(--ink);
}
.cookie-text {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.6;
  color: #a4a4a4;
  max-width: 780px;
}
.cookie-text a {
  color: var(--accent);
  text-decoration: underline;
}
.cookie-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.cookie-actions button {
  min-height: 48px;
  padding: 14px 22px;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.cookie-accept {
  background: var(--cta);
  color: #131313;
  border: 0;
}
.cookie-decline {
  background: none;
  border: 1px solid #fff;
  color: var(--ink);
}

/* ── Leistungsseiten ──────────────────────────────────────────────────────── */
.svc-page-hero {
  border-bottom: 1px solid var(--line);
}
.breadcrumb-bar {
  max-width: 1200px;
  margin: 0 auto;
  padding: clamp(22px, 3vw, 34px) 20px 0;
}
.breadcrumb {
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
  align-items: center;
  font-size: 13.5px;
  color: #6e6e6e;
}
.breadcrumb a {
  color: #8f8f8f;
}
.breadcrumb [aria-current] {
  color: #c4c4c4;
}
.svc-hero-grid {
  max-width: 1200px;
  margin: 0 auto;
  padding: clamp(26px, 3.5vw, 44px) 20px clamp(40px, 6vw, 76px);
  display: grid;
  gap: clamp(28px, 4vw, 52px);
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  align-items: center;
}
.svc-badge-row {
  display: flex;
  align-items: center;
  gap: 14px;
}
.svc-icon-tile {
  flex: none;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line-2);
  background: #191919;
  color: var(--accent);
}
.svc-index {
  font-family: var(--display);
  font-size: 11.5px;
  letter-spacing: 0.2em;
  color: #6e6e6e;
}
.svc-page-hero h1 {
  margin: 22px 0 0;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(28px, 5.6vw, 60px);
  line-height: 1.06;
  letter-spacing: -0.032em;
  color: var(--head);
  text-wrap: balance;
}
.svc-page-sub {
  margin: 18px 0 0;
  font-style: italic;
  font-size: clamp(16px, 2.2vw, 20px);
  color: var(--blue);
}
.svc-page-note {
  margin: 18px 0 0;
  max-width: 560px;
  font-size: clamp(15.5px, 2vw, 17.5px);
  line-height: 1.7;
  color: #a8a8a8;
  text-wrap: pretty;
}
.svc-page-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 32px;
}
.svc-figure {
  margin: 0;
}
.svc-figure img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: cover;
  border: 1px solid var(--line-2);
}
.svc-figure--hero img {
  aspect-ratio: 4 / 3;
}
.svc-figure--wide img {
  aspect-ratio: 3 / 2;
}
.scope {
  padding: clamp(52px, 7vw, 96px) 20px;
  background: var(--bg-alt);
  border-bottom: 1px solid var(--line);
}
.scope-grid {
  max-width: 1200px;
  margin: 0 auto;
  display: grid;
  gap: clamp(28px, 4vw, 52px);
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  align-items: start;
}
.scope h2 {
  margin: 0;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(24px, 4vw, 42px);
  line-height: 1.1;
  letter-spacing: -0.028em;
  color: var(--ink);
  text-wrap: balance;
}
.scope-list {
  margin-top: 26px;
  display: grid;
  gap: 12px 28px;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.scope-list > div {
  display: flex;
  gap: 12px;
  font-size: 15.5px;
  line-height: 1.55;
  color: #c4c4c4;
}
.scope-list i {
  flex: none;
  width: 2px;
  background: var(--accent);
  margin: 4px 0;
}
.scope-side {
  display: grid;
  gap: 12px;
}
.scope-box {
  padding: clamp(20px, 2.6vw, 28px);
  background: var(--panel);
  border-left: 2px solid var(--accent);
}
.scope-box h3 {
  margin: 0;
  font-family: var(--display);
  font-size: 19px;
  font-weight: 500;
  color: var(--ink);
}
.scope-box p {
  margin: 10px 0 0;
  font-size: 15px;
  line-height: 1.65;
  color: #a4a4a4;
}
.more {
  padding: clamp(52px, 7vw, 92px) 20px;
}
.more-head {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: space-between;
  align-items: center;
}
.more-head h2 {
  margin: 0;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(22px, 3.4vw, 36px);
  letter-spacing: -0.026em;
  color: var(--head);
}
.more-head a {
  font-size: 15px;
  font-weight: 600;
  color: var(--accent);
}
.more-grid {
  margin-top: clamp(24px, 3vw, 36px);
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.more-item {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px;
  border: 1px solid var(--line-2);
  background: var(--card);
  min-height: 72px;
  color: var(--ink);
}
.more-item:hover {
  background: var(--panel);
  color: var(--ink);
}
.more-item .ico {
  color: var(--accent);
}
.more-item span span {
  display: block;
}
.more-title {
  font-family: var(--display);
  font-size: 16.5px;
  font-weight: 500;
}
.more-sub {
  margin-top: 5px;
  font-size: 13.5px;
  color: #8a8a8a;
  line-height: 1.45;
}
.pager {
  margin-top: clamp(30px, 4vw, 44px);
  padding-top: 24px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: space-between;
}
.pager a {
  font-size: 15px;
  color: #b4b4b4;
}
.pager a:hover {
  color: #fff;
}
.pager .pager-next {
  margin-left: auto;
}

/* ── Rechtsseiten ─────────────────────────────────────────────────────────── */
.legal {
  padding: clamp(48px, 7vw, 96px) 20px;
}
.legal-inner {
  max-width: 800px;
  margin: 0 auto;
}
.legal-back {
  font-size: 14.5px;
  color: var(--accent);
}
.legal h1 {
  margin: 30px 0 0;
  font-family: var(--display);
  font-weight: 500;
  font-size: clamp(28px, 6vw, 56px);
  line-height: 1.06;
  letter-spacing: -0.03em;
  color: var(--head);
}
.legal-intro {
  margin: 22px 0 0;
  max-width: 68ch;
  font-size: 16px;
  line-height: 1.75;
  color: #b4b4b4;
}
.legal-body {
  margin-top: 36px;
  display: grid;
  gap: 30px;
  /* Rechtstexte sind Fließtext, kein Display-Satz: hier reicht die
     Silbentrennung des Browsers (lang="de") für "Verbraucherschlichtungsstelle"
     und Konsorten — die Wortliste in app/hyphenation.php ist nur für die
     Überschriften nötig, wo die Trennstelle sichtbar zählt. */
  hyphens: auto;
  overflow-wrap: break-word;
}
.legal-body--tight {
  margin-top: 32px;
  gap: 26px;
}
.legal-body h2 {
  margin: 0 0 10px;
  font-family: var(--display);
  font-size: 20px;
  font-weight: 500;
  color: var(--ink);
}

/* Widerruf der Cookie-Einwilligung am Ende der Datenschutzerklärung. */
.cookie-settings {
  margin-top: 34px;
  padding-top: 26px;
  border-top: 1px solid var(--line-3);
}
.cookie-settings h2 {
  margin: 0 0 10px;
  font-family: var(--display);
  font-size: 20px;
  font-weight: 500;
  color: var(--ink);
}
.cookie-settings p {
  margin: 0 0 16px;
  font-size: 15.5px;
  line-height: 1.75;
  color: #b4b4b4;
}
.cookie-settings .btn {
  display: inline-flex;
}
.legal-body p {
  margin: 0 0 14px;
  font-size: 15.5px;
  line-height: 1.75;
  color: #b4b4b4;
}
.legal-body p:last-child {
  margin-bottom: 0;
}
.legal-body ul {
  margin: 0 0 14px;
  padding: 0 0 0 20px;
  display: grid;
  gap: 8px;
  font-size: 15.5px;
  line-height: 1.7;
  color: #b4b4b4;
}
.legal-body strong {
  color: #e4e4e4;
  font-weight: 500;
}
.legal-body a {
  color: var(--accent);
  text-decoration: underline;
}

/* ── Ohne JavaScript ──────────────────────────────────────────────────────── */
/* Ohne JS schaltet niemand `data-open` um. Statt eines toten Knopfes über einer
   unerreichbaren Navigation steht das Panel dann einfach offen. */
html:not(.js) .nav-mobile {
  grid-template-rows: 1fr;
}
html:not(.js) .nav-mobile > div {
  visibility: visible;
}
html:not(.js) .nav-mobile a {
  opacity: 1;
  transform: none;
}
html:not(.js) .burger {
  display: none;
}
html:not(.js) .faq-panel {
  grid-template-rows: 1fr;
}
html:not(.js) .faq-panel > div {
  visibility: visible;
}
html:not(.js) .faq-panel p {
  opacity: 1;
  transform: none;
}
html:not(.js) .faq-plus i:last-child,
html:not(.js) .reason-controls {
  display: none;
}
html:not(.js) .reason-track {
  display: block;
}
html:not(.js) .reason-slide {
  opacity: 1;
  transform: none;
  filter: none;
  pointer-events: auto;
}
html:not(.js) .reason-slide + .reason-slide {
  border-top: 1px solid var(--line-2);
}
