/* ==========================================================================
   Hausmeisterservice Steinbiß — Stylesheet
   Design angelehnt an starplatethemes.com/php/billdins (Envato-Theme "Billdins"),
   eigene Markenfarben (Blau/Rot/Navy aus dem Logo), eigenes schlankes Vanilla-JS
   statt der Original jQuery-Plugin-Sammlung. Siehe CLAUDE.md.
   ========================================================================== */

@font-face {
  font-family: "Oswald";
  src: url("../fonts/oswald/oswald-v57-latin-variable.woff2") format("woff2");
  font-weight: 200 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Work Sans";
  src: url("../fonts/worksans/worksans-v24-latin-variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Great Vibes";
  src: url("../fonts/greatvibes/greatvibes-v21-latin-regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --navy: #142B4B;
  --navy-light: #1D3B66;
  --blue: #1F5AA6;
  --red: #C21F2F;
  --red-dark: #9B1622;
  --gray: #55606E;
  --gray-light: #647080; /* darkened from #8A93A0 — that shade failed WCAG AA contrast (3.1:1 on white, 2.8:1 on cream) for the small/body text it's used on; this passes 4.5:1+ on both */
  --cream: #F6F3EC;
  --white: #ffffff;
  --radius: 6px;
  --heading-font: "Oswald", "Arial Narrow", sans-serif;
  --body-font: "Work Sans", Arial, sans-serif;
  --script-font: "Great Vibes", cursive;
  --shadow: 0 20px 50px rgba(20, 43, 75, 0.12);
}

* { box-sizing: border-box; }

/* Explicit, on-brand keyboard focus indicator — deliberately set rather than relying
   on default browser focus-ring behavior, which the custom cursor's `cursor: none`
   on interactive elements could otherwise make easy to overlook if it were ever
   suppressed. Only shows for real keyboard navigation (:focus-visible), not mouse
   clicks. */
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
}

html { scroll-behavior: smooth; }

/* ---------- Scroll-reveal ---------- */
/* Slide + fade into view once, the first time an element scrolls into the viewport
   (js/main.js's IntersectionObserver adds .is-visible and stops watching — this never
   re-triggers on scrolling back up). Client feedback: the original up-only, 28px
   version was "kaum sichtbar" — barely noticeable. Now each block slides in from a
   side (further distance, slower/eased transition, so the motion actually reads while
   scrolling) and alternates left/right per section for variety rather than every
   block doing the same thing. Direction is chosen per element via a modifier class
   (.reveal--left / .reveal--right / .reveal--up, default is up) rather than baked into
   the base .reveal rule. Repeated items (service cards, FAQ entries) get a small
   transition-delay per nth-child on top of that, so a row reveals in sequence instead
   of popping in all at once. */
.reveal {
  opacity: 0;
  transform: translateY(36px);
  transition: opacity 0.9s ease, transform 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}
.reveal--left { transform: translateX(-90px); }
.reveal--right { transform: translateX(90px); }
.reveal--up { transform: translateY(36px); }
.reveal.is-visible { opacity: 1; transform: none; }
.service-card.reveal:nth-child(2) { transition-delay: 0.1s; }
.service-card.reveal:nth-child(3) { transition-delay: 0.2s; }
.service-card.reveal:nth-child(4) { transition-delay: 0.3s; }
.service-card.reveal:nth-child(5) { transition-delay: 0.4s; }
/* Client: the alternating left/right slide looked odd for the service cards
   specifically on desktop — .services__grid lays several cards side by side there
   (flex-wrap, several per row), so neighboring cards sliding in toward each other
   from opposite directions cross paths and read as messy. On mobile the cards stack
   one per row, where the same alternation reads fine (client confirmed). Rather than
   drop the alternation everywhere, only the service cards fall back to a plain
   up-fade once the grid is wide enough to actually show cards side by side. */
@media (min-width: 650px) {
  /* .services__grid fits 2+ cards per row from ~630px container width up (flex-basis
     280px + 26px gap), so this matches where cards actually start sitting side by
     side rather than an arbitrary tablet/desktop breakpoint. */
  .service-card.reveal--left, .service-card.reveal--right { transform: translateY(36px); }
}
.faq__item.reveal:nth-child(2) { transition-delay: 0.1s; }
.faq__item.reveal:nth-child(3) { transition-delay: 0.2s; }
.faq__item.reveal:nth-child(4) { transition-delay: 0.3s; }
.faq__item.reveal:nth-child(5) { transition-delay: 0.4s; }
@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal--left, .reveal--right, .reveal--up { opacity: 1; transform: none; transition: none; }
}

/* CSS text-transform:uppercase converts lowercase ß to "SS" per spec (no capital ß
   glyph in most fonts, including Oswald here) — wrap just the ß in this class inside
   any uppercase-styled heading so "Steinbiß" doesn't silently become "Steinbiss". */
.no-uc { text-transform: none; }

body {
  margin: 0;
  font-family: var(--body-font);
  color: var(--gray);
  font-size: 16px;
  line-height: 1.7;
  background: var(--white);
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }

a { color: inherit; text-decoration: none; }

ul { margin: 0; padding: 0; list-style: none; }

h1, h2, h3, h4 {
  font-family: var(--heading-font);
  color: var(--navy);
  margin: 0;
  font-weight: 600;
  line-height: 1.2;
}

.container {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 24px;
}

/* ---------- Buttons ---------- */
.thm-btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--red);
  color: var(--white);
  font-family: var(--heading-font);
  font-weight: 600;
  font-size: 14px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 15px 30px;
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background 0.3s ease, transform 0.3s ease;
}
.thm-btn:hover { background: var(--red-dark); transform: translateY(-2px); }
.thm-btn.outline {
  background: transparent;
  border: 2px solid rgba(255,255,255,0.6);
}
.thm-btn.outline:hover { background: rgba(255,255,255,0.12); }

/* ---------- Section title ---------- */
.sec-title { margin-bottom: 44px; }
.sec-title.center { text-align: center; }
.sec-title__tagline {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}
.sec-title.center .sec-title__tagline { display: flex; justify-content: center; }
.sec-title__tagline .line { width: 40px; height: 2px; background: var(--red); }
/* Was a real <h4>, which put a heading between the page's <h1> and each section's
   own <h2> title with no h2/h3 in between on the way down, and no consistent level
   coming back up between sections — a real "headings not sequentially descending"
   issue (PageSpeed a11y audit). This eyebrow label is decorative context for the
   heading right below it, not a heading in its own right, so it's a <span> now. */
.sec-title__tagline .eyebrow {
  font-family: var(--heading-font);
  color: var(--red);
  text-transform: uppercase;
  font-size: 15px;
  letter-spacing: 0.15em;
  font-weight: 600;
}
.sec-title__title {
  font-size: clamp(28px, 4vw, 42px);
  text-transform: uppercase;
}


/* ---------- Header ---------- */
.site-header {
  background: var(--white);
  position: sticky;
  top: 0;
  z-index: 200;
  box-shadow: 0 2px 20px rgba(20,43,75,0.08);
  transition: box-shadow 0.3s ease;
}
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding-top: 36px;
  padding-bottom: 36px;
  transition: padding 0.3s ease;
}
.site-header.is-scrolled .container { padding-top: 10px; padding-bottom: 10px; }
.brand {
  display: flex;
  align-items: center;
  gap: 12px;
}
.brand img { height: 72px; width: auto; transition: height 0.3s ease; }
.site-header.is-scrolled .brand img { height: 42px; }
.brand-name {
  font-family: var(--script-font);
  font-size: 38px;
  color: var(--navy);
  line-height: 1;
  white-space: nowrap;
  display: flex;
  flex-direction: column;
  transition: font-size 0.3s ease;
}
.site-header.is-scrolled .brand-name { font-size: 24px; }
.brand-name small {
  font-family: var(--heading-font);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gray-light);
  line-height: 1;
  margin-top: 4px;
}
.site-header.is-scrolled .brand-name small { margin-top: 2px; }
.site-footer .brand-name small { color: rgba(255,255,255,0.55); }
.main-nav { display: flex; align-items: center; gap: 34px; }
.main-nav__cta { display: none; }
.main-nav a {
  font-family: var(--heading-font);
  font-weight: 500;
  font-size: 15px;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--navy);
  position: relative;
  padding: 6px 0;
}
.main-nav a::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 0; height: 2px;
  background: var(--red);
  transition: width 0.3s ease;
}
.main-nav a:hover::after,
.main-nav a.active::after { width: 100%; }
.main-nav a.main-nav__cta::after { content: none; }
.header-actions { display: flex; align-items: center; gap: 20px; }
.nav-toggle {
  display: none;
  position: relative;
  z-index: 1001;
  background: none;
  border: 2px solid var(--navy);
  border-radius: var(--radius);
  width: 44px; height: 40px;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  cursor: pointer;
}
.nav-toggle span { width: 20px; height: 2px; background: var(--navy); transition: transform 0.25s ease, opacity 0.25s ease; }
.nav-toggle.is-active span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle.is-active span:nth-child(2) { opacity: 0; }
.nav-toggle.is-active span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.nav-backdrop {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(20,43,75,0.5);
  z-index: 150;
}
.nav-backdrop.is-open { display: block; }

/* ---------- Hero ---------- */
.hero {
  position: relative;
  background: var(--navy);
  overflow: hidden;
}
/* Fills the space beyond .hero__inner's max-width on ultrawide screens with a huge,
   blurred, darkened copy of the currently active slide instead of a flat color bar —
   kept in sync with the active slide by js/main.js. Hidden below the cap (no visible
   letterboxing) so it costs nothing on ordinary screens. */
.hero__backdrop {
  position: absolute;
  inset: -2%;
  background-size: cover;
  background-position: center;
  filter: blur(14px) brightness(0.6) saturate(1.1);
  transform: scale(1.03);
  opacity: 0;
  transition: opacity 1s ease;
  z-index: 0;
}
/* Crossfading opacity between one stacked layer per slide (same pattern as
   .hero__slide) instead of transitioning background-image directly — browsers
   implement that as an internal cross-fade() between the two source photos, which
   produces a muddy double-exposure blend of two unrelated images mid-transition. */
.hero__backdrop.is-active { opacity: 1; }
/* .hero__inner is capped at a sane max-width and centered — on very wide/ultrawide
   monitors (e.g. 34"+), the hero photo stops growing past that point and the extra
   space on either side is simply the plain navy .hero background instead of stretching
   the crop further. A fixed pixel height combined with a full-width cover image would
   otherwise crop away more of the photo vertically the wider the screen gets (the box
   becomes relatively wider/shorter than the photo); locking the inner box's own aspect
   ratio keeps the crop fraction constant up to the cap, so a background-position tuned
   once stays correct instead of drifting on wider monitors. */
.hero__inner {
  position: relative;
  z-index: 1;
  max-width: 1920px;
  margin: 0 auto;
  min-height: 560px;
  display: flex;
  align-items: center;
  overflow: hidden;
  /* Soft depth cue against the blurred backdrop on ultrawide monitors — replaces the
     removed edge-fade (see .hero__slide above). Invisible below the 1920px cap, since
     there's no backdrop margin for a shadow to fall onto there. */
  box-shadow: 0 0 70px rgba(0,0,0,0.35);
}
@media (min-width: 992px) {
  .hero__inner { aspect-ratio: 2.1 / 1; min-height: 560px; height: auto; }
}
.hero__slide {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity 1s ease;
  background-size: cover;
  background-position: center;
}
/* Round 31: the round-19 edge-fade (mask-image transparency on the sharp photo's own
   left/right edges) was removed again — client found the soft blur-into-photo
   transition didn't actually look good in practice. .hero__inner now meets the blurred
   backdrop with a plain hard edge; the depth cue on ultrawide monitors comes from a
   soft drop shadow on .hero__inner instead (see below), not from blurring the photo
   itself. */
.hero__slide.is-active { opacity: 1; visibility: visible; z-index: 1; }
/* Client feedback (round 27): the old heavy navy gradient here (72% down to 4%) hid
   too much of the actual photo — especially bad once a real, showcase-quality garden
   photo replaced the stock hero image, since the whole point of that photo is to be
   seen. Replaced with only a faint darkening for edge legibility; the text now sits on
   its own white panel (.hero__content) instead of relying on darkening the whole photo. */
.hero__slide::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, rgba(20,43,75,0.14) 0%, rgba(20,43,75,0.05) 35%, rgba(20,43,75,0) 65%);
}
.hero__art {
  position: absolute;
  right: -60px;
  bottom: -30px;
  width: 46%;
  max-width: 560px;
  opacity: 0.9;
}
/* Translucent white panel instead of white text over a darkened photo (see
   .hero__slide::before above) — keeps the text readable while letting the photo show
   through clearly behind and around it, rather than hiding most of the photo under a
   heavy dark gradient. */
.hero__content {
  position: relative;
  z-index: 2;
  max-width: 620px;
  margin: 60px 0;
  padding: 40px 44px;
  background: rgba(255,255,255,0.86);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border-radius: var(--radius);
  box-shadow: 0 20px 46px rgba(20,43,75,0.22);
}
.hero__tag {
  display: inline-block;
  color: var(--red);
  font-family: var(--heading-font);
  text-transform: uppercase;
  letter-spacing: 0.15em;
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 18px;
}
.hero__title {
  color: var(--navy);
  font-size: clamp(32px, 5vw, 54px);
  text-transform: uppercase;
  margin-bottom: 20px;
}
.hero__text {
  color: var(--gray);
  font-size: 17px;
  max-width: 480px;
  margin-bottom: 34px;
}
/* Per-slide alignment (see [data-content-align] on .hero__content in index.html):
   the panel isn't pinned to the same spot on every slide — on the winterdienst photo
   the Multicar/plow sits left-of-center, exactly where the panel used to sit, hiding
   it almost entirely. Moving that slide's panel to the right instead keeps the
   actual subject of each photo uncovered. */
.hero__content[data-content-align="right"] { margin-left: auto; margin-right: 0; }
.hero__actions { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; }
.hero__secondary { color: var(--navy); font-weight: 600; display: flex; align-items: center; gap: 8px; }
.hero__secondary:hover { color: var(--red); }
.hero__dots {
  position: absolute;
  z-index: 3;
  left: 50%;
  transform: translateX(-50%);
  bottom: 26px;
  display: flex;
  gap: 10px;
}
/* Buttons enlarged to a 24px hit area (PageSpeed a11y: "Berührungszielbereiche haben
   eine unzureichende Größe") while keeping the same small 10px visual dot — the dot
   itself moved to a ::after pseudo-element so the clickable button box can be bigger
   than what's actually drawn. */
.hero__dots button {
  width: 24px; height: 24px;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.hero__dots button::after {
  content: "";
  width: 10px; height: 10px;
  border-radius: 50%;
  border: 2px solid rgba(255,255,255,0.6);
  background: transparent;
  transition: background 0.2s ease, border-color 0.2s ease;
}
.hero__dots button.is-active::after { background: var(--red); border-color: var(--red); }

/* ---------- About ---------- */
.about { padding: 100px 0; background: var(--white); }
.about .container { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: 60px; align-items: center; }
.about__visual { position: relative; }
.about__panel {
  aspect-ratio: 4 / 5;
  border-radius: var(--radius);
  background-color: var(--navy);
  background-size: cover;
  /* Real photo of Jörn now in place (portrait 1000x1334, very close to the panel's
     own 4:5 ratio already — only a few percent gets cropped) — center crop works
     cleanly, unlike the old placeholder. */
  background-position: center 10%;
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow);
}
.about__panel .icon-house {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.9;
}
.about__panel .icon-house svg { width: 55%; height: 55%; }
.about__badge {
  position: absolute;
  right: -22px;
  bottom: -22px;
  background: var(--red);
  color: var(--white);
  border-radius: var(--radius);
  padding: 22px 26px;
  box-shadow: var(--shadow);
  text-align: center;
}
.about__badge strong { display: block; font-family: var(--heading-font); font-size: 30px; }
.about__badge span { font-size: 13px; text-transform: uppercase; letter-spacing: 0.06em; }
.about__content-text { font-size: 16.5px; margin-bottom: 26px; }
.about__list { margin-bottom: 32px; }
.about__list li {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid #eceae2;
  font-weight: 600;
  color: var(--navy);
}
.about__list li:last-child { border-bottom: none; }
.about__list .check {
  width: 24px; height: 24px;
  flex: none;
  border-radius: 50%;
  background: var(--red);
  color: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
}
.about__stats {
  display: flex;
  gap: 40px;
  margin-top: 36px;
  padding-top: 30px;
  border-top: 1px solid #eceae2;
}
.about__stats strong {
  display: block;
  font-family: var(--heading-font);
  font-size: 34px;
  color: var(--navy);
}
.about__stats span { font-size: 13.5px; color: var(--gray-light); text-transform: uppercase; letter-spacing: 0.04em; }

/* ---------- Services ---------- */
.services { padding: 100px 0; background: var(--cream); position: relative; overflow: hidden; }
.services > .container { position: relative; z-index: 1; }
.services__grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 26px;
}
.service-card {
  flex: 1 1 280px;
  max-width: 340px;
  background: var(--white);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: 0 12px 30px rgba(20,43,75,0.06);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.service-card:hover { transform: translateY(-6px); box-shadow: var(--shadow); }
/* Height raised from 160px (round 26 feedback: at 160px, a tall portrait work photo
   only had room to show a narrow band — face-only or work-only, never both, since the
   window covered barely a third of the image). At 220px the window covers roughly half
   the image height on the portrait real photos, enough to fit both Jörn and the actual
   work he's doing in the same crop. */
.service-card__img {
  height: 220px;
  background-size: cover;
  background-position: center;
  background-color: var(--navy);
}
.service-card__body { padding: 26px 26px 30px; }
.service-card h3 {
  font-size: 19px;
  text-transform: uppercase;
  margin-bottom: 12px;
}
.service-card p { font-size: 15px; margin: 0; }

/* ---------- Working process ---------- */
.process { padding: 100px 0; background: var(--white); position: relative; overflow: hidden; }
.process__silhouette {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 340px;
  opacity: 0.05;
  transform: scaleX(-1);
  pointer-events: none;
  z-index: 0;
}
.process .container { position: relative; z-index: 1; }
.process__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 22px;
  margin-bottom: 44px;
}
.process__arrow {
  flex: none;
  width: 48px; height: 48px;
  border-radius: 50%;
  border: 2px solid #e4e0d5;
  background: var(--white);
  color: var(--navy);
  font-size: 18px;
  cursor: pointer;
  transition: all 0.3s ease;
}
.process__arrow:hover { background: var(--navy); border-color: var(--navy); color: var(--white); }
.process__tabs {
  display: flex;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
}
.process__tab-btn {
  font-family: var(--heading-font);
  font-size: 20px;
  width: 62px; height: 62px;
  border-radius: 50%;
  border: 2px solid #e4e0d5;
  background: var(--white);
  color: var(--navy);
  cursor: pointer;
  transition: all 0.3s ease;
}
.process__tab-btn.is-active {
  background: var(--red);
  border-color: var(--red);
  color: var(--white);
}
.process__panel {
  display: none;
  position: relative;
  overflow: hidden;
  background: var(--cream);
  border-radius: var(--radius);
  padding: 54px 60px;
  max-width: 720px;
  margin: 0 auto;
}
.process__panel.is-active { display: block; }
.process__panel::before {
  content: attr(data-num);
  position: absolute;
  top: -0.15em;
  right: 30px;
  font-family: var(--heading-font);
  font-size: 180px;
  font-weight: 600;
  line-height: 1;
  color: var(--navy);
  opacity: 0.06;
  pointer-events: none;
}
.process__panel h3 { position: relative; font-size: 26px; text-transform: uppercase; margin-bottom: 16px; }
.process__panel p { position: relative; max-width: 480px; }
.process__points {
  position: relative;
  margin-top: 22px;
  padding-top: 22px;
  border-top: 1px solid #e4e0d5;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
}
.process__points li {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--navy);
  padding-left: 18px;
  position: relative;
}
.process__points li::before {
  content: "";
  position: absolute;
  left: 0; top: 7px;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--red);
}

/* ---------- Trust / testimonial-style ---------- */
.trust { padding: 100px 0; background: var(--navy); color: rgba(255,255,255,0.85); position: relative; overflow: hidden; }
.trust__silhouette {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 400px;
  opacity: 0.035;
  filter: invert(1);
  pointer-events: none;
  z-index: 0;
}
.trust .container { position: relative; z-index: 1; display: grid; grid-template-columns: 0.9fr 1.1fr; gap: 60px; align-items: center; }
.trust__intro { font-size: 16px; line-height: 1.7; max-width: 480px; }
.trust .sec-title__title { color: var(--white); }
.trust__count {
  margin-top: 30px;
  padding-top: 26px;
  border-top: 1px solid rgba(255,255,255,0.15);
}
.trust__count { font-size: 17px; line-height: 1.6; }
.trust__count strong { display: block; font-family: var(--heading-font); font-size: 24px; text-transform: uppercase; color: var(--white); margin-bottom: 4px; }
.trust__card {
  position: relative;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: var(--radius);
  padding: 40px;
}
/* Client: switching between quotes visibly resized the card, since the three texts
   are different lengths and the card's height (min-height only) followed whichever
   one was currently shown. All three quotes now sit stacked in the same CSS Grid
   cell (grid-area 1/1) — a grid cell auto-sizes to its tallest child regardless of
   which is visible, so the stack (and therefore the card) always reserves room for
   the longest quote, and the card's height never changes when the quote rotates. */
.trust__quote-stack { display: grid; }
.trust__quote {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s ease;
  font-size: 18px;
  line-height: 1.6;
}
.trust__quote.is-active { opacity: 1; visibility: visible; }
.trust__quote strong { display: block; margin-top: 20px; color: var(--white); font-family: var(--heading-font); font-size: 15px; text-transform: uppercase; letter-spacing: 0.04em; }
.trust__dots { display: flex; gap: 8px; margin-top: 24px; }
/* Same enlarged-hit-area pattern as .hero__dots above. */
.trust__dots button {
  width: 24px; height: 24px;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.trust__dots button::after {
  content: "";
  width: 9px; height: 9px;
  border-radius: 50%;
  background: rgba(255,255,255,0.3);
  transition: background 0.2s ease;
}
.trust__dots button.is-active::after { background: var(--red); }

/* ---------- Appointment / Contact ---------- */
.contact { padding: 100px 0; background: var(--cream); }
.contact .container { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: 50px; }
.contact__list li {
  display: flex;
  gap: 18px;
  padding: 20px 0;
  border-bottom: 1px solid #e4e0d5;
}
.contact__list li:first-child { padding-top: 0; }
.contact__icon {
  width: 52px; height: 52px;
  flex: none;
  border-radius: 50%;
  background: var(--red);
  color: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
}
.contact__icon svg { width: 24px; height: 24px; }
.contact__list h2 { font-size: 18px; text-transform: uppercase; margin-bottom: 4px; }
.contact__list p { margin: 0; }
.contact__list a:hover { color: var(--red); }
.contact__form {
  background: var(--white);
  border-radius: var(--radius);
  padding: 46px;
  box-shadow: var(--shadow);
}
.contact__form h2 { font-size: 24px; text-transform: uppercase; margin-bottom: 6px; }
.contact__form > p { margin: 0 0 26px; color: var(--gray-light); }
/* Visually hidden but screen-reader-accessible — placeholders disappear once a field
   has content or focus, so they're not a substitute for a real <label>. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.form-group { margin-bottom: 18px; }
.form-group input,
.form-group select,
.form-group textarea {
  width: 100%;
  border: 1px solid #e4e0d5;
  border-radius: var(--radius);
  padding: 14px 16px;
  font-family: var(--body-font);
  font-size: 15px;
  background: var(--cream);
}
.form-group textarea { min-height: 110px; resize: vertical; }
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus { outline: 2px solid var(--blue); background: var(--white); }
.form-consent { display: flex; align-items: flex-start; gap: 10px; font-size: 13.5px; margin-bottom: 22px; }
.form-consent input { width: auto; margin-top: 4px; }
.form-note { font-size: 13.5px; margin-top: 14px; min-height: 18px; }
.form-note.success { color: #1c7c3c; }
.form-note.error { color: var(--red); }

/* ---------- FAQ ---------- */
.faq { padding: 100px 0; background: var(--white); position: relative; overflow: hidden; }
.faq__silhouette {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 320px;
  opacity: 0.05;
  pointer-events: none;
  z-index: 0;
}
.faq .container { position: relative; z-index: 1; }
.faq .container { max-width: 760px; }
.faq .sec-title { text-align: center; }
.faq .sec-title__tagline { justify-content: center; }
.faq__item {
  border: 1px solid #e4e0d5;
  border-radius: var(--radius);
  margin-bottom: 14px;
  overflow: hidden;
}
.faq__q {
  width: 100%;
  text-align: left;
  background: var(--cream);
  border: none;
  padding: 18px 22px;
  font-family: var(--heading-font);
  font-size: 16px;
  color: var(--navy);
  display: flex;
  justify-content: space-between;
  align-items: center;
  cursor: pointer;
}
.faq__q .plus { font-size: 20px; color: var(--red); transition: transform 0.3s ease; }
.faq__item.is-open .plus { transform: rotate(45deg); }
.faq__a {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
  padding: 0 22px;
}
.faq__item.is-open .faq__a { max-height: 220px; padding: 16px 22px 22px; }

/* ---------- Floating call button (mobile only — see .call-fab in the 860px media
   query below; desktop already has "Kostenlos anfragen" prominent in the header, a
   second sticky CTA there would be redundant clutter, not extra value). ---------- */
.call-fab {
  display: none;
  position: fixed;
  right: 18px;
  bottom: 18px;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--red);
  color: var(--white);
  align-items: center;
  justify-content: center;
  box-shadow: 0 10px 24px rgba(20,43,75,0.35);
  z-index: 500;
  transition: transform 0.2s ease, background 0.2s ease;
}
.call-fab:hover, .call-fab:active { background: var(--red-dark); transform: scale(1.06); }
.call-fab svg { width: 24px; height: 24px; }

/* ---------- Footer ---------- */
.site-footer { background: var(--navy); color: rgba(255,255,255,0.7); position: relative; overflow: hidden; }
.site-footer__silhouette {
  position: absolute;
  bottom: 0;
  width: 560px;
  max-width: 38vw;
  opacity: 0.035;
  filter: invert(1);
  pointer-events: none;
  z-index: 0;
}
/* 1.svg's figure already pushes the mower ahead of him toward the right in the
   source art (hands reach forward-right to the handle) — natural orientation already
   reads as walking rightward INTO the footer from the left edge, mower leading. No
   mirroring needed (an earlier pass mirrored this and had it backwards). */
.site-footer__silhouette--left { left: -30px; }
/* ---------- Footer mower drive-in ---------- */
/* Client: the mower silhouette should drive in from the left, but only once the
   visitor has scrolled all the way to the very bottom of the page, and slowly rather
   than snapping in. Separate from the generic .reveal mechanism above (which targets
   opacity:1 — wrong here, this graphic's "revealed" state is its normal, barely-there
   0.035 decorative opacity, not fully opaque) and separately gated in js/main.js on
   the footer's bottom bar being fully (not just partially) in view, plus an added
   delay before the drive-in starts. Placed after the base .site-footer__silhouette
   rule above (same 0,1,0 specificity) so its opacity:0 actually wins the cascade
   instead of being overridden back to the resting 0.035 by source order. */
.site-footer__silhouette--left {
  transform: translateX(-480px);
  opacity: 0;
  /* Client: with opacity and transform animating over similar durations (2s / 1.6s),
     the two blurred together into what read as "a slow fade-in", not a mower driving
     across the footer. Split them apart on purpose: opacity now settles quickly
     (0.6s) so the figure is at its normal faint visibility almost immediately, while
     the position keeps sliding for much longer (4s) with an ease-out (decelerating,
     like coming to a stop) — since opacity is no longer changing for most of that
     time, what's left to perceive is purely the horizontal motion. */
  transition: transform 4s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.6s ease;
}
.site-footer__silhouette--left.is-driven-in {
  transform: translateX(0);
  opacity: 0.035;
}
@media (prefers-reduced-motion: reduce) {
  .site-footer__silhouette--left { transform: none; opacity: 0.035; transition: none; }
}
.site-footer__top, .site-footer__middle, .site-footer__bottom { position: relative; z-index: 1; }
.site-footer__top {
  border-bottom: 1px solid rgba(255,255,255,0.1);
  /* Fades out on the left so the divider line doesn't cut across the mower
     silhouette standing there (it spans the full footer height) — the line still
     reads clearly under the actual content on the right. */
  border-image: linear-gradient(to right, transparent 0, transparent 40vw, rgba(255,255,255,0.1) 46vw) 1;
  padding: 34px 0;
}
.site-footer__top .container { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 20px; }
.site-footer__top .brand-name { color: var(--white); }
.site-footer__top-text { font-size: 15px; max-width: 420px; text-align: right; }
.site-footer__middle { padding: 64px 0; }
.site-footer__middle .container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 40px;
}
.footer-widget h2 {
  color: var(--white);
  font-size: 17px;
  text-transform: uppercase;
  margin-bottom: 18px;
}
.footer-widget ul li { margin-bottom: 11px; }
/* Safety net for the reconstructed email/phone links (js/main.js): the non-breaking
   hyphen + <wbr> after "@" handle the normal case, but this still lets the browser
   break as a last resort in an extremely narrow column instead of overflowing it. */
.js-email, .js-phone { overflow-wrap: break-word; }
/* Client asked for the footer's email to stay on one line. A 13px size (small enough
   to fit even the grid's narrowest possible column) made the email visibly smaller
   than its neighboring list items ("kleiner fällt sofort auf") — too subtle a
   difference wasn't achievable, so instead this uses only a mild reduction (15px, vs
   16px elsewhere) that fits on one line at the footer's normal/common column widths
   without standing out, and left wrapping-capable (not forced nowrap) so that on an
   unusually narrow in-between window it still wraps cleanly at "kontakt@" (via the
   <wbr> in js/main.js) rather than overflowing the column. */
.footer-widget .js-email { font-size: 15px; }
.footer-widget ul li a:hover { color: var(--red); }
.footer-widget .area-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.footer-widget .area-chips span {
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: 30px;
  padding: 6px 14px;
  font-size: 13px;
}
.site-footer__bottom {
  border-top: 1px solid rgba(255,255,255,0.1);
  border-image: linear-gradient(to right, transparent 0, transparent 40vw, rgba(255,255,255,0.1) 46vw) 1;
  padding: 22px 0;
}
.site-footer__bottom .container { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px; font-size: 13.5px; }
.site-footer__bottom-menu { display: flex; gap: 22px; }
.site-footer__bottom-menu a:hover { color: var(--red); }

/* ---------- Honeypot (hidden from humans, visible to bots) ---------- */
.hp-field {
  position: absolute !important;
  left: -9999px !important;
  width: 1px; height: 1px;
  opacity: 0;
}

/* ---------- Legal pages ---------- */
.legal-page { padding: 70px 0 100px; max-width: 820px; margin: 0 auto; }
.legal-page h1 { font-size: clamp(28px, 4vw, 40px); text-transform: uppercase; margin-bottom: 30px; }
.legal-page h3 { font-size: 19px; text-transform: uppercase; margin: 34px 0 12px; }
.legal-page p { margin: 0 0 14px; }
.legal-page a { color: var(--blue); text-decoration: underline; }
.legal-back { display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; font-weight: 600; color: var(--navy); }
.legal-back:hover { color: var(--red); }

/* ---------- Custom cursor (desktop-with-mouse only, feature-detected in JS) ----------
   Grow-and-label circle, chosen by the client after comparing 6 options in a demo
   Artifact (a plain dot+ring "agency" cursor felt too generic for a local trade
   business). Real cursor stays hidden entirely except while hovering an element that
   opts in via [data-cursor-label] — everywhere else the normal pointer shows. */
.custom-cursor__label {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--red);
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  transform: translate(-50%, -50%);
  transition: width 280ms cubic-bezier(.2,.9,.3,1.3), height 280ms cubic-bezier(.2,.9,.3,1.3), opacity 200ms ease;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
}
.custom-cursor__label span {
  font-family: var(--heading-font);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: #fff;
  opacity: 0;
  transition: opacity 150ms ease;
  white-space: nowrap;
}
.custom-cursor__label.is-hover {
  width: 60px;
  height: 60px;
  opacity: 1;
}
.custom-cursor__label.is-hover span { opacity: 1; }
[data-cursor-label] { cursor: none; }

/* ---------- Utility icons (inline SVG currentColor) ---------- */
.icon { display: inline-flex; }

/* ---------- Responsive ---------- */
@media (max-width: 991px) {
  .about .container,
  .contact .container,
  .faq .container,
  .trust .container { grid-template-columns: 1fr; }
  .process__panel.is-active { grid-template-columns: 1fr; }
  .site-footer__top-text { text-align: left; }
}

@media (max-width: 860px) {
  .call-fab { display: flex; }
  .main-nav {
    position: fixed; top: 0; right: -320px; width: 300px; height: 100vh;
    background: var(--white); flex-direction: column; align-items: stretch;
    padding: 100px 30px 40px; gap: 4px;
    box-shadow: -10px 0 30px rgba(0,0,0,0.15);
    transition: right 0.3s ease;
    z-index: 999;
    overflow-y: auto;
  }
  .main-nav.is-open { right: 0; }
  .main-nav a { padding: 12px 0; border-bottom: 1px solid #eee; }
  .nav-toggle { display: flex; }
  .header-actions > .thm-btn { display: none; }
  .main-nav a.main-nav__cta {
    display: flex; justify-content: center;
    margin-top: 22px; padding-top: 15px; border-bottom: none;
    width: 100%;
  }
  .about__badge { position: static; margin-top: 20px; display: inline-block; }
}

@media (max-width: 600px) {
  .hero { min-height: 560px; }
  .hero__art { display: none; }
  .hero__content { padding: 28px 24px; margin: 40px 0; }
  .contact__form { padding: 30px; }
  .site-footer__top .container { flex-direction: column; text-align: center; }
  .site-footer__top-text { text-align: center; }
  /* Decorative silhouette accents (footer, trust, process, faq) are tuned for wide
     layouts and can crowd/overlap real content on narrow screens — simplest and
     safest is to just hide them below 600px rather than trying to rescale each one. */
  .site-footer__silhouette, .trust__silhouette, .process__silhouette, .faq__silhouette {
    display: none;
  }
}
