/* styles.css – Layout & Komponenten, Forum historisches Handwerk e.V. */

/* ---------- Grundlagen ---------- */

body { overflow-x: hidden; }

.container {
  width: min(100% - 2 * var(--space-s), var(--maxw));
  margin-inline: auto;
}
.container--narrow { width: min(100% - 2 * var(--space-s), var(--maxw-narrow)); }

.section { padding-block: var(--space-xl); }
.section--tight { padding-block: var(--space-l); }

.section--dark {
  background: var(--color-dark);
  color: var(--color-on-dark);
}
.section--dark h2, .section--dark h3 { color: var(--color-on-dark); }
.section--tint { background: var(--color-bg-tint); }

h1, h2, h3 {
  font-family: var(--font-display);
  font-variation-settings: "SOFT" 20, "WONK" 0;
  font-weight: 500;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
h1 { font-size: var(--step-4); line-height: 1.02; letter-spacing: -0.03em; }
h2 { font-size: var(--step-3); line-height: 1.08; }
h3 { font-size: var(--step-1); line-height: 1.2; font-weight: 600; }

p { max-width: var(--maxw-text); }
.lead { font-size: var(--step-1); line-height: 1.5; color: var(--color-text-soft); }
.section--dark .lead { color: var(--color-on-dark-soft); }

/* Sektionskopf: Überschrift links, Vorspann rechts. Damit steht der Kopf
   nicht als schmale Säule in einer leeren Fläche. */
.section-head {
  display: grid;
  gap: var(--space-m);
  margin-bottom: var(--space-l);
}
@media (min-width: 900px) {
  .section-head {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: clamp(2rem, 6vw, 6rem);
    align-items: end;
  }
  .section-head .lead { margin-bottom: 0.35rem; }
  /* Ohne Vorspann gibt es nichts, was die rechte Spalte fuellt. Dann steht
     die Ueberschrift ueber die ganze Breite statt als schmale Saeule neben
     einer leeren Haelfte. */
  .section-head--solo { grid-template-columns: 1fr; }
}
.section-head h2 { margin: 0; }

.eyebrow {
  font-size: var(--step--1);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--color-text-faint);
  font-weight: 600;
  margin-bottom: var(--space-s);
}
.section--dark .eyebrow { color: var(--color-accent-soft); }
/* Dachzeile in der H1: trägt den Suchbegriff der Seite, die große Zeile
   darunter bleibt der Satz. Sieht aus wie jede andere Dachzeile. */
.h1-dach {
  display: block;
  font-family: var(--font-body);
  line-height: 1.4;
}

/* ---------- Buttons & Links ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  min-height: 3rem;
  padding: 0.85rem 1.6rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-weight: 600;
  font-size: var(--step-0);
  cursor: pointer;
  transition: background-color 0.25s var(--ease), color 0.25s var(--ease),
              border-color 0.25s var(--ease), transform 0.25s var(--ease);
}
.btn--primary { background: var(--color-dark); color: var(--color-on-dark); }
.btn--primary:hover { background: var(--color-text); transform: translateY(-1px); }
.btn--ghost { border-color: var(--color-line-strong); color: var(--color-text); }
.btn--ghost:hover { border-color: var(--color-text); background: var(--color-surface); }
.section--dark .btn--ghost { border-color: var(--color-line-dark); color: var(--color-on-dark); }
.btn--light { background: var(--color-accent-weak); color: var(--color-text); }
.btn--light:hover { background: var(--color-surface); }

/* Haupt-CTA. Der einzige Messington auf der Seite, der als Fläche auftritt.
   Dadurch ist immer klar, wo es weitergeht. */
.btn--cta {
  background: var(--color-accent);
  color: oklch(0.20 0.02 55);
  min-height: 3.5rem;
  padding: 1.05rem 2.1rem;
  font-size: var(--step-0);
  font-weight: 600;
  letter-spacing: 0.005em;
  box-shadow: 0 1px 0 oklch(0.45 0.07 70), 0 10px 24px -14px oklch(0.40 0.06 68 / 0.8);
}
.btn--cta:hover {
  background: var(--color-accent-soft);
  transform: translateY(-2px);
  box-shadow: 0 1px 0 oklch(0.45 0.07 70), 0 16px 30px -14px oklch(0.40 0.06 68 / 0.9);
}
.btn--cta:active { transform: translateY(0); }
.section--dark .btn--cta { color: oklch(0.18 0.02 55); }

.link-underline {
  border-bottom: 1px solid var(--color-line-strong);
  padding-bottom: 2px;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}
.link-underline:hover { border-color: var(--color-accent-ink); color: var(--color-accent-ink); }

:where(a, button, input, textarea, select, [tabindex]):focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

/* ---------- Kopfzeile ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in oklab, var(--color-bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--color-line);
}
.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem var(--space-m);
  padding-block: 0.9rem;
}
/* Signet und Wortmarke stehen nebeneinander und sind zusammen ein Link auf
   die Startseite. Das Bild traegt alt="" - der Vereinsname steht direkt
   daneben, und eine Vorlesehilfe soll ihn nicht zweimal ansagen. */
.wordmark { display: flex; align-items: center; gap: 0.7rem; line-height: 1.15; }
.wordmark__mark {
  width: 48px; height: 48px;
  flex: none;
  /* Das Signet ist ein Wappen und wirkt neben der Schrift sonst zu laut. */
  opacity: 0.92;
  transition: opacity 0.2s var(--ease);
}
.wordmark:hover .wordmark__mark { opacity: 1; }
.wordmark__text { display: block; }
.wordmark__name,
.wordmark__role { display: block; }
.wordmark__name {
  font-family: var(--font-display);
  font-variation-settings: "SOFT" 30;
  font-size: 1.15rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  max-width: 22ch;
}
.wordmark__ev { color: var(--color-text-faint); font-weight: 500; }
/* Mindestens 12px (27.10.2026): Vorher 10.9px am Rechner und 9.6px auf dem
   Tablet - kaum lesbar. */
.wordmark__role {
  font-size: 0.75rem;
  /* Versalien ohne Unterlaengen: 1 reicht, und der Kopf bleibt so hoch
     wie vorher. */
  line-height: 1;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-text-faint);
  margin-top: 0.1rem;
}
.site-nav { display: flex; align-items: center; gap: var(--space-m); }
.site-nav a { font-size: var(--step--1); color: var(--color-text-soft); white-space: nowrap; }
.site-nav a:hover { color: var(--color-text); }
.site-header__cta { min-height: 2.85rem; padding: 0.6rem 1.4rem; font-size: var(--step--1); }
.cta-short { display: none; }

/* Telefon im Kopf, seit 21.09.2026. Die Nummer stand nur im Hero und im Fuss
   und dort als nackter Text - "wenn die Nummer so alleine steht, sieht das
   nicht gut aus" (Feedback 18.09.2026). Als Knopf mit Hoerer erkennbar anklickbar
   und steht neben dem Hauptweg, ohne mit ihm zu konkurrieren: btn--ghost,
   nicht btn--cta. */
.site-header__aktionen {
  display: flex;
  align-items: center;
  gap: var(--space-2xs);
}
.site-header__tel {
  min-height: 2.85rem;
  padding: 0.6rem 1.1rem;
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
  gap: 0.5em;
}
.site-header__tel svg { flex: none; }

/* Ab hier wird es eng: Der Hoerer allein genuegt, die Nummer steht im Hero
   und im Fuss noch einmal. Der Knopf bleibt quadratisch und 44px gross. */
@media (max-width: 720px) {
  .tel-lang { display: none; }
  .site-header__tel {
    padding: 0;
    width: 2.85rem;
    justify-content: center;
  }
}
/* Auf sehr schmalen Schirmen kurzes CTA-Label, damit Name und Knopf
   in eine Zeile passen und der Kopf flach bleibt. */
@media (max-width: 420px) {
  .cta-long { display: none; }
  .cta-short { display: inline; }
  .site-header__cta { padding: 0.6rem 1.05rem; }
}

/* Auf schmalen Schirmen rutschen die Links in eine eigene, scrollbare Zeile.
   Kein Burger-Menü: vier Links brauchen keinen Klick zum Aufklappen. */
@media (max-width: 860px) {
  .site-nav {
    order: 3;
    flex: 1 0 100%;
    gap: var(--space-s);
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    margin-inline: calc(-1 * var(--space-s));
    padding-inline: var(--space-s);
  }
  .site-nav::-webkit-scrollbar { display: none; }
  /* Touch-Ziele auf 44 Pixel bringen, die Zeile bleibt trotzdem flach,
     weil die Fläche nach oben und unten in den vorhandenen Abstand geht. */
  .site-nav a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding-inline: 0.15rem;
  }
  .site-header__inner { padding-block: 0.6rem 0.1rem; row-gap: 0.2rem; column-gap: var(--space-s); }
  .wordmark__name { font-size: 0.98rem; line-height: 1.2; max-width: 18ch; }
  .wordmark__role { margin-top: 0; }

  /* Signet und Wortmarke bleiben beieinander. Ohne diese Zeile bricht der
     Kopf bei 390px so um, dass das Wappen allein in einer Zeile steht und
     der Name darunter - gemessen, nicht vermutet. */
  .wordmark { flex: 1 1 auto; min-width: 0; flex-wrap: nowrap; }
  .wordmark__mark { width: 36px; height: 36px; }
  .wordmark__text { min-width: 0; }

  /* Das Aufklappmenü darf nicht zwischen Link und Pfeil umbrechen. */
  .site-nav__group { flex-wrap: nowrap; flex: none; }
  .site-nav__toggle { flex: none; }

  /* Mobil-Navigation, 28.09.2026. Gemessen vorher: Auf 360–390px lagen
     „Über uns“ und „Kontakt“ außerhalb der wischbaren Zeile, ohne dass man
     sah, dass sie da sind. Deshalb: „Startseite“ entfällt (das Signet führt
     dorthin), die Abstände werden enger, und der Pfeil neben „Leistungen“
     rückt heran. Alle vier Punkte passen damit ab 360px in die Zeile. */
  .site-nav > a[href="/"] { display: none; }
  .site-nav { gap: 0.95rem; }
  .site-nav__group { gap: 0; }
  /* 44px Tippfläche direkt neben „Leistungen“, ohne in dessen Fläche zu
     ragen (überlappende Ziele meldet PageSpeed, WCAG 2.5.8). Der Pfeil sitzt
     links in der Fläche, der Rest geht in den Abstand zum nächsten Punkt. */
  .site-header .site-nav__toggle { width: 44px; margin-right: -0.95rem; justify-content: flex-start; padding-left: 0.2rem; }

  /* Kopf blendet sich beim Herunterscrollen aus und beim Hochscrollen ein
     (main.js, initKopf). Auf dem Telefon nimmt er sonst dauerhaft ein
     Fünftel des Bildschirms ein. transform statt Höhe: Der Inhalt darunter
     springt nicht. */
  .site-header { transition: transform 0.28s var(--ease); will-change: transform; }
  .site-header.is-versteckt { transform: translateY(-100%); }
}
@media (max-width: 860px) and (prefers-reduced-motion: reduce) {
  .site-header { transition: none; }
}
/* Signet, Name, Hörer und „Anfragen“ in einer Zeile, auch auf 360px. */
@media (max-width: 440px) {
  .site-header__inner { column-gap: 0.6rem; }
  .wordmark { gap: 0.5rem; }
  .wordmark__name { font-size: 0.92rem; max-width: none; }
  /* flex-basis 0: Die Wortmarke nimmt den Rest der Zeile und bricht darin
     um, statt die Knöpfe in eine eigene Zeile zu schieben. */
  .wordmark { flex: 1 1 0; }
  .wordmark picture { flex: none; }   /* sonst drückt die Wortmarke das Signet schmal */
  .site-header__aktionen { gap: 0.3rem; }
  .site-header__cta { padding: 0.6rem 0.85rem; }
}

/* Unter 380px reicht die Zeile sonst bis 2px an den Rand (gemessen 360px:
   „Kontakt“ endet bei 358). */
@media (max-width: 380px) {
  .site-nav { gap: 0.5rem; }
  .site-header .site-nav__toggle { margin-right: -0.5rem; }
}

/* Auf kleinen Schirmen entfällt die Rollenzeile im Kopf. Der Hero sagt
   unmittelbar darunter dasselbe, und die Kopfzeile bleibt zweizeilig.
   580 statt 520px, seit die Zeile 12px hat: Dazwischen schob sie die
   Knoepfe in eine eigene Zeile, der Kopf wuchs von 110 auf 161px. */
@media (max-width: 580px) {
  .wordmark__role { display: none; }
}

/* ---------- Hero ---------- */

.hero { padding-block: clamp(3rem, 7vw, 6rem) var(--space-xl); }
.hero__grid {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
@media (min-width: 900px) {
  .hero__grid { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }
}
.hero__title { margin-bottom: var(--space-s); }
.hero__title em {
  font-style: normal;
  font-variation-settings: "SOFT" 60, "WONK" 1;
  color: var(--color-accent);
}
.hero__text { font-size: var(--step-1); line-height: 1.5; color: var(--color-text-soft); }
.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-s) var(--space-m);
  margin-top: var(--space-l);
}
.hero__note {
  margin-top: var(--space-s);
  font-size: var(--step--1);
  color: var(--color-text-faint);
  max-width: 42ch;
}
.hero__figure { margin: 0; }
.hero__figure img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-img);
}
.hero__caption {
  margin-top: var(--space-xs);
  font-size: var(--step--1);
  color: var(--color-text-faint);
}
/* Telefon und Tablet: eigener Entwurf statt dieselben Elemente kleiner.
   Text zuerst, das Foto direkt darunter. Vorher stand das Bild oben und der
   Knopf lag auf allen Telefonen 150 bis 400 px unter dem Falz (gemessen
   29.09.2026, 360 bis 430 px Breite). Jetzt stehen Ort, Aussage und beide
   Wege im ersten Bildschirm, das Foto schaut unten an. */
@media (max-width: 899px) {
  .hero { padding-block: var(--space-m) var(--space-xl); }
  .hero__grid { grid-template-areas: "txt" "fig"; gap: var(--space-l); }
  .hero__figure { grid-area: fig; }
  .hero__body { grid-area: txt; }
  .hero__title { font-size: clamp(2rem, 8.4vw, 2.75rem); line-height: 1.04; }
  .hero__text, .seitenhero .lead { font-size: var(--step-0); line-height: 1.55; }
  .hero__actions { margin-top: var(--space-m); column-gap: var(--space-m); }
  .hero__figure img { aspect-ratio: 3 / 2; }
}

/* ---------- Werkschau ---------- */

/* Manuell bedienbare Werkschau. Kein Automatiklauf: Der Besucher klickt
   selbst weiter. Ein Bild, eine Geschichte, darunter der Streifen zum
   Direktanspringen. Der Rahmen ist fest und zeigt jedes Bild vollständig,
   damit Hoch- und Querformat nebeneinander funktionieren. */

.showcase { margin-top: var(--space-m); }

.showcase__stage { display: grid; }
.slide {
  grid-area: 1 / 1;
  margin: 0;
  display: grid;
  gap: var(--space-m) clamp(2rem, 4vw, 3.5rem);
}
/* Erst wenn die Steuerung läuft, wird versteckt. Ohne JavaScript bleiben
   alle Projekte sichtbar. */
.showcase[data-js="on"] .slide {
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.42s var(--ease), visibility 0.42s var(--ease);
}
.showcase[data-js="on"] .slide.is-active { opacity: 1; visibility: visible; }
/* Übernimmt GSAP, setzt es die Werte inline. Dann darf die CSS-Überblendung
   nicht zusätzlich laufen. */
.showcase[data-anim="gsap"] .slide { transition: none; }
@media (min-width: 900px) {
  .slide { grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr); align-items: center; }
}

.slide__frame {
  /* Heller Passepartout-Grund, damit das Bild auf der getönten Sektion steht
     und nicht darin verschwindet. */
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius-img);
  /* Fast quadratischer Rahmen. Bei gemischtem Material aus Hoch- und
     Querformat bleibt so bei beiden Orientierungen ein vernünftiges
     Verhältnis von Bild zu Passepartout. */
  aspect-ratio: 1 / 1;
  max-height: 68vh;
  padding: clamp(0.75rem, 2vw, 1.5rem);
  overflow: hidden;
  /* Die Zeile braucht eine bestimmte Größe. Ohne minmax(0, 1fr) löst
     max-height am Bild gegen eine unbestimmte Höhe auf und wird ignoriert,
     das Bild wächst dann über den Rahmen hinaus. */
  display: grid;
  grid-template-rows: minmax(0, 1fr);
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
}
.slide__frame img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  min-width: 0;
  min-height: 0;
  object-fit: contain;
  border-radius: 1px;
  box-shadow: 0 1px 2px oklch(0.30 0.02 60 / 0.10),
              0 12px 28px -12px oklch(0.30 0.02 60 / 0.30);
}

@media (min-width: 900px) {
  .slide__frame { aspect-ratio: 5 / 4; }
}
.slide__story { align-self: center; }
.slide__meta {
  font-size: var(--step--1);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-text-faint);
  font-weight: 600;
  margin-bottom: var(--space-xs);
}
.slide__story h3 { font-size: var(--step-2); margin-bottom: var(--space-s); }
.slide__story p:last-child { color: var(--color-text-soft); max-width: 46ch; margin: 0; }

/* Bedienleiste */
.showcase__bar {
  display: grid;
  gap: var(--space-m);
  margin-top: var(--space-l);
  padding-top: var(--space-m);
  border-top: 1px solid var(--color-line);
}
@media (min-width: 760px) {
  .showcase__bar { grid-template-columns: auto minmax(0, 1fr); align-items: center; gap: var(--space-l); }
}
.showcase__nav { display: flex; align-items: center; gap: var(--space-xs); }
.stepper {
  width: 3rem;
  height: 3rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--color-line-strong);
  border-radius: var(--radius);
  background: transparent;
  color: var(--color-text);
  font-size: 1.05rem;
  cursor: pointer;
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.stepper:hover { background: var(--color-surface); border-color: var(--color-text); }
.stepper:active { transform: scale(0.94); }
.stepper { transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease), transform 0.12s var(--ease); }
.showcase__counter {
  margin: 0 0 0 var(--space-xs);
  font-size: var(--step--1);
  letter-spacing: 0.12em;
  color: var(--color-text-faint);
  font-variant-numeric: tabular-nums;
}

.showcase__thumbs {
  display: flex;
  gap: var(--space-xs);
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 0.25rem;
}
.showcase__thumbs::-webkit-scrollbar { display: none; }
.thumb {
  flex: 0 0 auto;
  width: 4.5rem;
  height: 4.5rem;
  padding: 0;
  border: 1px solid var(--color-line);
  border-radius: var(--radius-img);
  background: var(--color-bg-tint);
  cursor: pointer;
  overflow: hidden;
  opacity: 0.5;
  transition: opacity 0.3s var(--ease), border-color 0.3s var(--ease),
              transform 0.35s var(--ease);
}
.thumb img { width: 100%; height: 100%; object-fit: cover; }
.thumb:hover { opacity: 0.85; transform: translateY(-2px); }
.thumb.is-active {
  opacity: 1;
  border-color: var(--color-accent);
  transform: translateY(-3px);
  box-shadow: 0 6px 14px -8px oklch(0.30 0.02 60 / 0.5);
}

.work__more { margin-top: var(--space-l); }

/* Ohne JavaScript werden alle Projekte untereinander gezeigt. */
.no-js .showcase__stage { display: block; }
.no-js .slide { margin-bottom: var(--space-l); }
.no-js .showcase__bar { display: none; }

/* ---------- Haltung ---------- */

.stance__intro { max-width: 58ch; margin-bottom: var(--space-l); }
.stance__list { display: grid; gap: var(--space-m); }
@media (min-width: 820px) {
  .stance__list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-l) var(--space-xl); }
  /* Erster Punkt bekommt mehr Gewicht, kein gleichförmiges Raster */
  .stance__item:first-child { grid-column: 1 / -1; max-width: 62ch; }
  .stance__item:first-child h3 { font-size: var(--step-2); }

  /* Bei nur zwei Punkten gibt es keine Rangfolge, die das erste Feld in die
     volle Breite rechtfertigt. Es bliebe die rechte Hälfte darunter leer -
     genau die tote Fläche, die sonst entsteht. Dann stehen beide
     nebeneinander und gleich gewichtet. */
  .stance__list:not(:has(> :nth-child(3))) .stance__item:first-child {
    grid-column: auto;
    max-width: none;
  }
  .stance__list:not(:has(> :nth-child(3))) .stance__item:first-child h3 {
    font-size: var(--step-1);
  }

  /* Seit die Versicherungsschäden in die Nummerierung gewandert sind, bleibt
     hier ein einziger Punkt übrig. Er stünde in der linken Spalte und ließe
     die rechte leer - dieselbe tote Fläche. Allein heißt deshalb: Bild neben
     Text über die volle Breite. */
  /* :first-child ist hier Pflicht, nicht Zierde: Ohne ihn hat die Regel
     oben fuer zwei Punkte (:not(:has(> :nth-child(3))) ... :first-child)
     die hoehere Spezifitaet, greift auch bei einem einzigen Punkt und setzt
     grid-column auf auto zurueck. Gemessen am 23.10.2026: der Punkt stand in
     573 von 1248 px, das Bild 209 px breit, die rechte Haelfte leer. */
  .stance__list:not(:has(> :nth-child(2))) .stance__item:first-child {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr);
    gap: 0 var(--space-xl);
    align-content: start;
  }
  .stance__list:not(:has(> :nth-child(2))) .stance__item > .craft__bild {
    grid-column: 1;
    grid-row: 1 / -1;
    margin: 0;
    align-self: start;
  }
  .stance__list:not(:has(> :nth-child(2))) .stance__item > :not(.craft__bild) {
    grid-column: 2;
  }
}
.stance__item h3 { margin-bottom: var(--space-2xs); }
.stance__item p { color: var(--color-text-soft); margin: 0; }
.section--dark .stance__item p { color: var(--color-on-dark-soft); }

/* ---------- Leistungen ---------- */

/* Leistungen: kein Kachelraster und keine zweispaltige Tabelle, sondern
   ein gesetztes Feld. Die erste Leistung ist die wichtigste und bekommt
   volle Breite und Bild, der Rest steht versetzt darunter. */
.craft { display: grid; gap: var(--space-l) clamp(2rem, 5vw, 5rem); }
@media (min-width: 900px) { .craft { grid-template-columns: repeat(12, minmax(0, 1fr)); } }

.craft__item { position: relative; padding-top: var(--space-m); border-top: 1px solid var(--color-line); }
.craft__no {
  display: block;
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--color-accent-ink);
  margin-bottom: var(--space-xs);
}
/* Die Regeln griffen nur auf h3. Auf /leistungen/ sind die Ueberschriften
   aber h2, weil sie auf die Unterseiten verlinken - dort stand die Zeile
   also ohne jeden Abstand direkt auf dem Absatz. Gemeldet am 21.09.2026 mit
   Screenshot. Seitdem gelten die Regeln fuer beide. */
.craft__item :is(h2, h3) {
  font-size: var(--step-2);
  margin-bottom: var(--space-s);
  line-height: 1.15;
}
.craft__item p { margin: 0 0 var(--space-xs); color: var(--color-text-soft); max-width: 46ch; }
.craft__item p:last-child { margin-bottom: 0; }

/* Der Weg weiter steht abgesetzt, nicht als vierter Absatz. */
.craft__mehr { margin-top: var(--space-s) !important; }

/* Bild ueber dem Text, direkt unter der Haarlinie: Es beantwortet "was ist
   das" schneller als der erste Satz. Nur bei den fuenf schmalen Feldern -
   das erste Feld hat sein Bild daneben. */
.craft__bild { margin: 0 0 var(--space-m); }
.craft__bild img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-img);
  background: var(--color-line);
}

/* Erste Leistung: breit, mit Bild daneben */
.craft__item--lead { display: grid; gap: var(--space-m) clamp(2rem, 5vw, 4rem); }
@media (min-width: 900px) {
  .craft__item--lead { grid-column: span 12; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); align-items: start; }
  .craft__item--lead :is(h2, h3) { font-size: var(--step-3); }
  .craft__item--lead p { max-width: 54ch; font-size: var(--step-1); line-height: 1.5; }
  .craft__item--lead .craft__mehr { font-size: var(--step-0); }
}
.craft__item--lead figure { margin: 0; }
.craft__item--lead img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-img);
  background: var(--color-line);
}
.craft__item--lead figcaption {
  margin-top: var(--space-2xs);
  font-size: var(--step--1);
  color: var(--color-text-faint);
}

/* Die übrigen Leistungen: zwei gleich breite Spalten.
   Vorher standen sie versetzt (5, 6, 5, 5, 6 Spalten) - ein Mittel gegen das
   gleichförmige Kachelraster. Mit Bildern kippt das Mittel in sein Gegenteil:
   Jede Kachel bekam ein anderes Bildformat, keine Unterkante traf die andere,
   und die Überschriften standen auf fünf verschiedenen Höhen (08.10.2026).
   Gegen das Raster wirkt jetzt die Hierarchie: Block 01 über die volle Breite
   mit Bild daneben, darunter gleich breite Paare, getrennt durch Haarlinien. */
@media (min-width: 900px) {
  .craft__item--a,
  .craft__item--c,
  .craft__item--e { grid-column: 1 / span 6; }
  .craft__item--b,
  .craft__item--d,
  .craft__item--f { grid-column: 7 / span 6; }
}

.craft__spotlight-grid { display: grid; gap: 0; margin-top: var(--space-xl); }
@media (min-width: 900px) {
  .craft__spotlight-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 0.42fr); }
}
.craft__spotlight-grid img {
  width: 100%; height: 100%;
  min-height: 22rem;
  object-fit: cover;
  background: var(--color-line);
}

.craft__spotlight {
  padding: clamp(1.75rem, 4vw, 3.5rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
  background: var(--color-dark);
  color: var(--color-on-dark);
  border-radius: var(--radius);
}
.craft__spotlight h3 { font-size: var(--step-2); margin-bottom: var(--space-s); color: var(--color-on-dark); }
.craft__spotlight p { color: var(--color-on-dark-soft); max-width: 58ch; }
/* Vorher step--1 in text-faint, zu klein zum Lesen (22.10.2026). Er traegt zwei Links, darunter den einzigen Weg
   von der Startseite zum Trockenbau, und gehoert deshalb in Fliesstextgroesse. */
.craft__aside {
  margin-top: var(--space-m);
  font-size: var(--step-0);
  color: var(--color-text-soft);
}
/* Eigene Zeile wie "Was dazugehoert" in den Feldern: Im Satz brach der Link
   mitten durch ("Alle" am Zeilenende), 26.10.2026. */
.craft__aside-mehr {
  margin-top: var(--space-s);
  font-size: var(--step-0);
  color: var(--color-text-soft);
}

/* ---------- Person & Verein ---------- */

.person__grid { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
@media (min-width: 900px) {
  .person__grid { grid-template-columns: minmax(0, 0.72fr) minmax(0, 1fr); align-items: start; }
}
.person__figure { margin: 0; }
.person__figure img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border-radius: var(--radius-img);
}
.person__figure figcaption {
  margin-top: var(--space-xs);
  font-size: var(--step--1);
  color: var(--color-text-faint);
}
.person__body p { max-width: 58ch; }
.person__body p + p { margin-top: var(--space-s); }

/* Kurze Faktenspalte. Füllt die Fläche neben dem Porträt mit Belegtem
   statt mit Weißraum. */
.facts {
  margin-top: var(--space-l);
  display: grid;
  gap: 0;
  border-top: 1px solid var(--color-line-strong);
}
@media (min-width: 640px) { .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--space-l); } }
.facts > div {
  display: grid;
  gap: 0.15rem;
  padding-block: var(--space-s);
  border-bottom: 1px solid var(--color-line);
}
.facts dt { font-size: var(--step--1); letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-text-faint); }
.facts dd { font-weight: 600; }

.club__intro { display: grid; gap: var(--space-l) clamp(2rem, 5vw, 4rem); align-items: center; }
@media (min-width: 900px) {
  .club__intro { grid-template-columns: minmax(0, 0.55fr) minmax(0, 1fr); }
}
/* Das Vereinslogo liegt als helle Grafik auf schwarzem Grund vor.
   Deshalb steht es auf einer dunklen Tafel statt auf dem hellen Papier. */
.club__mark {
  background: var(--color-dark);
  border-radius: var(--radius);
  padding: clamp(1.5rem, 4vw, 2.5rem);
  display: grid;
  gap: var(--space-m);
  justify-items: center;
  text-align: center;
}
/* Das <picture> ist der Grid-Eintrag, nicht das <img>. Mit justify-items:center
   wurde deshalb die Huelle zentriert, und das kleinere Bild darin rutschte an
   deren linken Rand. Gemeldet am 21.09.2026. Die Breite gehoert
   an die Huelle, dann sitzen Logo und Link auf derselben Mitte. */
.club__mark picture { display: block; width: min(100%, 20rem); }
.club__mark img { width: 100%; aspect-ratio: 1 / 1; object-fit: contain; }
.club__mark a { color: var(--color-accent-soft); font-size: var(--step--1); letter-spacing: 0.06em; }
.club__mark a:hover { color: var(--color-on-dark); }
/* Postanschrift des Vereins im dunklen Rahmen: dieselbe Groesse wie der Link,
   aber die ruhige Textfarbe des dunklen Grunds, damit sie nicht wie ein
   zweiter Link aussieht. */
.club__mark .club__contact { color: var(--color-on-dark-soft); font-size: var(--step--1); margin: 0; text-align: center; }

.club__figure { margin: var(--space-l) 0 0; }
.club__figure img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--radius-img);
  background: var(--color-line);
}
.club__figure figcaption { margin-top: var(--space-xs); font-size: var(--step--1); color: var(--color-text-faint); }

.club__grid { display: grid; gap: var(--space-l); margin-top: var(--space-xl); }
@media (min-width: 820px) { .club__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.club__col h3 { margin-bottom: var(--space-xs); }
.club__col p { color: var(--color-text-soft); margin: 0 0 var(--space-xs); }
.club__contact { font-size: var(--step--1); color: var(--color-text-faint); }

/* ---------- Ablauf ---------- */

.steps { position: relative; margin-top: var(--space-l); }
.steps__list { list-style: none; }
.steps__rail {
  position: absolute;
  left: 0.6rem;
  top: 0.4rem;
  bottom: 0.4rem;
  width: 1px;
  background: var(--color-line);
}
.steps__rail::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--color-accent);
  transform: scaleY(var(--progress, 0));
  transform-origin: top;
}
.step {
  position: relative;
  padding-left: 3rem;
  padding-block: var(--space-s);
}
.step::before {
  content: "";
  position: absolute;
  left: 0.25rem;
  top: 1.45rem;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 50%;
  background: var(--color-bg);
  border: 1px solid var(--color-line-strong);
}
.step__no {
  font-size: var(--step--1);
  color: var(--color-text-faint);
  letter-spacing: 0.1em;
  font-weight: 600;
}
.step h3 { margin-block: 0.15rem 0.3rem; }
.step p { margin: 0; color: var(--color-text-soft); }

/* ---------- Erwartungsrahmen ---------- */

.expect__list { display: grid; gap: var(--space-m); margin-top: var(--space-l); }
@media (min-width: 820px) { .expect__list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-l) var(--space-xl); } }
.expect__item h3 { margin-bottom: var(--space-2xs); }
.expect__item p { color: var(--color-text-soft); margin: 0; }
.section--dark .expect__item p { color: var(--color-on-dark-soft); }
.section--dark .expect__close { border-top-color: var(--color-line-dark); }
.expect__close {
  margin-top: var(--space-l);
  padding-top: var(--space-m);
  border-top: 1px solid var(--color-line);
  font-size: var(--step-1);
  max-width: 52ch;
}

/* ---------- Formular ---------- */

.form-shell {
  margin-top: var(--space-l);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius);
  padding: clamp(1.25rem, 4vw, 2.75rem);
}
.form-progress {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) var(--space-s);
  margin-bottom: var(--space-l);
  padding-bottom: var(--space-s);
  border-bottom: 1px solid var(--color-line);
  font-size: var(--step--1);
}
.form-progress span {
  color: var(--color-text-faint);
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.form-progress span[aria-current="step"] { color: var(--color-text); font-weight: 600; }
.form-progress span[data-done="true"] { color: var(--color-accent); }

.fieldset { border: 0; }
.fieldset[hidden] { display: none; }
.fieldset legend {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 500;
  margin-bottom: var(--space-s);
}
.field { margin-bottom: var(--space-m); }
.field > label, .field > .field__label {
  display: block;
  font-weight: 600;
  margin-bottom: var(--space-2xs);
}
.field__hint { font-size: var(--step--1); color: var(--color-text-faint); margin-bottom: var(--space-xs); }
/* Pflichtfeld-Sternchen (Formular, Schritt 4). Farbe wie der Akzent-Text,
   damit es ohne Erklärsatz als Markierung lesbar ist. */
.pflicht { color: var(--color-accent-ink); font-weight: 600; }
.field input[aria-invalid="true"] { border-color: oklch(0.52 0.16 30); box-shadow: 0 0 0 1px oklch(0.52 0.16 30); }
.field input[type="text"],
.field input[type="email"],
.field input[type="tel"],
.field textarea,
.field select {
  width: 100%;
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--color-line-strong);
  border-radius: var(--radius);
  background: var(--color-bg);
  color: var(--color-text);
}
.field textarea { min-height: 7rem; resize: vertical; }
.field-row { display: grid; gap: var(--space-s); }
@media (min-width: 700px) { .field-row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.choices { display: flex; flex-wrap: wrap; gap: var(--space-xs); }
.choice {
  position: relative;
  display: inline-flex;
}
.choice input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.choice span {
  display: inline-block;
  padding: 0.7rem 1.1rem;
  min-height: 2.75rem;
  border: 1px solid var(--color-line-strong);
  border-radius: var(--radius);
  cursor: pointer;
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.choice input:checked + span {
  border-color: var(--color-text);
  background: var(--color-accent-weak);
  font-weight: 600;
}
.choice input:focus-visible + span { outline: 2px solid var(--color-accent); outline-offset: 3px; }

.dropzone {
  display: block;
  padding: var(--space-m);
  border: 1px dashed var(--color-line-strong);
  border-radius: var(--radius);
  text-align: center;
  cursor: pointer;
  color: var(--color-text-soft);
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.dropzone:hover { border-color: var(--color-accent); background: var(--color-accent-weak); }
.dropzone input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.dropzone b { display: block; color: var(--color-text); font-size: var(--step-0); }
.dropzone small { font-size: var(--step--1); }
.filelist { margin-top: var(--space-xs); font-size: var(--step--1); color: var(--color-text-soft); }
.filelist li { list-style: none; padding: 0.3rem 0; border-bottom: 1px solid var(--color-line); }

.form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-s);
  align-items: center;
  margin-top: var(--space-l);
  padding-top: var(--space-m);
  border-top: 1px solid var(--color-line);
}
.form-note { font-size: var(--step--1); color: var(--color-text-faint); max-width: 52ch; margin-top: var(--space-m); }


[hidden] { display: none !important; }

/* ---------- Kontakt & Footer ---------- */

.contact__grid { display: grid; gap: var(--space-l); }
@media (min-width: 820px) { .contact__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.contact__block h2, .contact__block h3 { font-size: var(--step-0); text-transform: uppercase; letter-spacing: 0.12em; color: var(--color-accent-ink); margin-bottom: var(--space-xs); font-family: var(--font-body); }
.contact__block p, .contact__block a { color: var(--color-text-soft); line-height: 1.7; }
.contact__block a:hover { color: var(--color-text); }
.section--dark .contact__block h2, .section--dark .contact__block h3 { color: var(--color-accent-soft); }
.section--dark .contact__block p, .section--dark .contact__block a { color: var(--color-on-dark-soft); }
.section--dark .contact__block a:hover { color: var(--color-on-dark); }
/* Vier Blöcke statt drei: der Verein hat ein eigenes Postfach, und drei
   gleich große Kacheln sind genau der Rhythmus, an dem KI-Layout auffällt. */
@media (min-width: 820px) { .contact__grid:has(> :nth-child(4)) { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* Der Fuss war am 21.09.2026 gemessen 513px hoch auf 1440 und 902px auf 390 –
   auf dem Telefon also fast ein ganzer Bildschirm fuer Adresse und neun Links.
   Getragen haben das nicht die Schrift, sondern drei Polster von je 2rem und
   neun Linkzeilen mit 44px Mindesthoehe. Beides ist hier zurueckgenommen. */
.site-footer {
  background: var(--color-dark);
  color: var(--color-on-dark-soft);
  padding-block: var(--space-s) var(--space-m);
  font-size: var(--step--1);
}
.site-footer__inner {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs) var(--space-m);
  justify-content: space-between;
  align-items: center;
  padding-top: var(--space-s);
  border-top: 1px solid var(--color-line-dark);
}
.site-footer a:hover { color: var(--color-on-dark); }
.site-footer nav { display: flex; gap: var(--space-m); }
/* Auch die Rechtslinks sind auf Touch-Geräten ein Ziel, nicht nur Kleingedrucktes. */
.site-footer nav a { display: inline-flex; align-items: center; min-height: 44px; }

/* ---------- Reveal (JS setzt .is-in) ---------- */

.reveal { opacity: 0; transform: translateY(18px); }
.reveal.is-in { opacity: 1; transform: none; transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
.no-js .reveal, .reduced-motion .reveal { opacity: 1; transform: none; }

/* Screenreader-only */
.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-link {
  position: absolute; left: var(--space-s); top: -4rem;
  background: var(--color-dark); color: var(--color-on-dark);
  padding: 0.7rem 1rem; z-index: 100; border-radius: var(--radius);
  transition: top 0.2s var(--ease);
}
.skip-link:focus { top: var(--space-s); }

/* =========================================================================
   Unterseiten (P3)
   Ergänzungen, keine Umbauten. Die Unterseiten benutzen die Sektionsmuster
   der Startseite weiter; nur drei Dinge gibt es dort nicht: einen Seitenkopf
   ohne Hero-Bild, ein Bildraster für die Werkschau und einen Fuß mit
   Leistungsnavigation.
   ========================================================================= */

/* ---------- Seitenkopf ---------- */

/* Kein zweiter Hero. Eine Unterseite beginnt mit Überschrift und Vorspann,
   und der Vorspann steht neben der Überschrift statt darunter – sonst ist
   der obere Bildschirm eine schmale Säule in viel leerer Fläche. */
.pagehead {
  padding-block: clamp(3rem, 7vw, 6.5rem) var(--space-l);
  border-bottom: 1px solid var(--color-line);
}
.pagehead h1 {
  font-size: var(--step-3);
  max-width: 22ch;
  margin: 0;
}
.pagehead .lead { margin-top: var(--space-m); max-width: 62ch; }

@media (min-width: 900px) {
  .pagehead .container {
    display: grid;
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: clamp(2rem, 6vw, 6rem);
    align-items: end;
  }
  .pagehead .eyebrow { grid-column: 1 / -1; }
  .pagehead .lead { margin-top: 0; margin-bottom: 0.35rem; }
}

/* Auf Unterseiten trägt die Leistungsliste h2 statt h3, weil die h1 im
   Seitenkopf steht. Die Optik bleibt die der Startseite. */
.pagehead + .section .craft__item h2 { font-size: var(--step-2); margin: 0 0 var(--space-xs); }
.craft__item--lead h2 { font-size: var(--step-2); }

/* ---------- Bildraster der Werkschau ---------- */

/* Die Startseite zeigt die Werkschau als Bühne mit einem Stück nach dem
   anderen. Auf /galerie/ steht alles nebeneinander: Wer hierher navigiert,
   will vergleichen, nicht durchblättern. */
.gallery {
  display: grid;
  gap: var(--space-l) clamp(1.5rem, 4vw, 3.5rem);
}
@media (min-width: 700px) { .gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Auszug auf der Startseite: vier Stuecke in einer Reihe, sobald sie Platz
   haben. Als Zweispalter war die Sektion auf 1920 gemessen 2385px hoch, weil
   jedes Hochformat 750px breit wurde. Ein Band zeigt dieselben vier Bilder
   in weniger als der halben Hoehe. */
@media (min-width: 1100px) { .gallery--band { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-m) clamp(1rem, 2.5vw, 2rem); } }
.gallery--band .gallery__item figcaption h3 { font-size: var(--step-0); }
/* Zwei Hochformate neben zwei Querformaten: Ohne Ausrichtung sassen die
   Unterschriften auf vier Hoehen. Am unteren Rand ausgerichtet stehen die
   Bilder auf einer Linie, und der Text darunter beginnt auf einer. */
.gallery.gallery--band { align-items: end; }

/* ---------- Bilder, die ein Ziel haben ---------- */

/* Gemeldet am 22.09.2026: Ein Bild auf der Startseite sollte sich beim
   Ueberfahren ruehren, und bei den Leistungen soll der Klick darauf auf die
   Unterseite fuehren. Beides gehoert zusammen: Ein Zoom auf Hover ist ein
   Klickversprechen. Wo er steht, muss auch etwas passieren, sonst luegt der
   Effekt. Hover gehört auf alles Anklickbare, und nur dorthin.

   Leichtestes Werkzeug: natives CSS. Bewegt wird nur
   transform, der Rahmen bleibt stehen und schneidet ab. */
.bildlink {
  display: block;
  overflow: hidden;
  border-radius: var(--radius-img);
  background: var(--color-line);
}
.bildlink img {
  display: block;
  transition: transform 0.5s var(--ease);
}
.bildlink:hover img,
.bildlink:focus-visible img { transform: scale(1.045); }

/* Das Bild gehoert zur Ueberschrift daneben. Wer es ueberfaehrt, sieht auch
   dort, wohin der Klick fuehrt. :has() trifft nur das Bild, nicht den Text. */
.craft__item:has(.bildlink:hover) :is(h2, h3) .link-underline {
  border-color: var(--color-accent-ink);
  color: var(--color-accent-ink);
}

/* Ohne Bewegung bleibt das Versprechen sichtbar, nur ohne Zoom. */
@media (prefers-reduced-motion: reduce) {
  .bildlink img { transition: none; }
  .bildlink:hover img, .bildlink:focus-visible img { transform: none; }
  .bildlink:hover, .bildlink:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }
}
/* Auf der Startseite ist das Portraet ein Vertrauenssignal, nicht das Thema.
   Ungedeckelt wurde es auf 1920 gemessen 650px breit und die Sektion 1125px
   hoch; 30rem reichen fuer das Gesicht, und die Sektion wird "mittel". */
#werkstatt .person__figure { max-width: 27rem; }
/* Der Abschluss unter dem Zeitstrahl ist fuer Hauptweg plus Abzweig gebaut
   (/innenausbau-u-moebel/). Auf der Startseite gibt es nur den Hauptweg, das
   grosse Polster darueber traegt dort nichts. */
#ablauf .zeitstrahl__abschluss { margin-top: var(--space-l); padding-top: var(--space-m); }

.gallery__item { margin: 0; }
.gallery__item img {
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  background: var(--color-bg-tint);
}
.gallery__item figcaption { padding-top: var(--space-s); }
.gallery__item figcaption h2,
.gallery__item figcaption h3 {
  font-size: var(--step-1);
  margin: var(--space-2xs) 0 var(--space-xs);
}
.gallery__item figcaption p { color: var(--color-text-soft); margin: 0; }
.gallery__item figcaption .slide__meta { margin: 0; }

/* Jedes Stück behält sein eigenes Format. Ein fester 4:3-Rahmen mit
   object-fit: cover schnitt vom Büffettschrank oben und unten so viel ab,
   dass er als Möbel nicht mehr zu erkennen war - und genau das Erkennen ist
   der Zweck einer Werkschau. Die Spalten werden dadurch unterschiedlich
   hoch. Das ist erwünscht: ein gleichförmiges Kachelraster ist der Rhythmus,
   an dem man Baukastenseiten erkennt.

   Begrenzt wird nur nach oben, damit ein hohes Bild nicht den halben
   Bildschirm für sich nimmt und die Bildunterschrift aus dem Blick schiebt. */
.gallery { align-items: start; }
/* Volle Spaltenbreite, Höhe nach Format. max-height mit width:auto wäre der
   naheliegende Weg, bricht aber die Kantenflucht: Ein Hochformat stünde dann
   schmaler als seine Spalte, und die linke Kante der Bildunterschrift läge
   nicht mehr unter der linken Bildkante. */
.gallery__item img { width: 100%; height: auto; }

/* ---------- Fuß mit Navigation ---------- */

.site-footer__cols {
  display: grid;
  gap: var(--space-m) clamp(1.5rem, 5vw, 4rem);
  padding-block: var(--space-s) var(--space-m);
}
/* Unter 700px stand alles untereinander: Adressblock, fuenf Leistungen, vier
   Werkstattlinks. Die beiden Linkspalten passen nebeneinander, das spart rund
   ein Drittel der Fusshoehe auf dem Telefon. */
@media (max-width: 699px) {
  .site-footer__cols { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .site-footer__cols > :first-child { grid-column: 1 / -1; }
}
@media (min-width: 700px) {
  .site-footer__cols { grid-template-columns: minmax(0, 1.4fr) repeat(2, minmax(0, 1fr)); }
}
.site-footer__cols p { margin: 0 0 var(--space-2xs); }
.site-footer__name { color: var(--color-on-dark); font-weight: 600; }
.site-footer__head {
  color: var(--color-on-dark);
  font-weight: 600;
  letter-spacing: 0.06em;
  margin-bottom: var(--space-xs);
}
.site-footer__cols nav { display: flex; flex-direction: column; gap: 0; }
/* 44px je Zeile ist die AAA-Regel (WCAG 2.5.5) und gehoert an Schaltflaechen.
   Fuer eine Linkspalte im Fuss gilt WCAG 2.5.8 (AA): 24px, und mit Abstand
   dazwischen ist auch das erfuellt. Neun Zeilen mal 44px waren auf dem Telefon
   450px reine Navigation. 34px bleibt bequem treffbar und halbiert den Block. */
.site-footer__cols nav a {
  width: fit-content;
  min-height: 34px;
  display: inline-flex;
  align-items: center;
}

.site-footer__base {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2xs) var(--space-m);
  justify-content: space-between;
  align-items: center;
  padding-top: var(--space-s);
  border-top: 1px solid var(--color-line-dark);
}
.site-footer__base nav { display: flex; gap: var(--space-m); }

/* Agenturnennung. Sie steht bewusst auf der vorhandenen Fusszeile statt in
   einer eigenen: kein Logo, keine eigene Zeile, keine Auszeichnung, dieselbe
   Groesse und Farbe wie der Rest der Zeile. Ankertext ist nur der Markenname –
   ein Keyword-Anker wie "Webdesign Berlin" macht aus einem Credit den
   Fuss-Spamlink, den Googles Link-Richtlinie meint. */
/* Keine eigene Farbe: --color-text-faint ist ein Token fuer helle Gruende
   (oklch 0.505) und waere auf dem dunklen Fuss kaum lesbar. Die Zeile erbt,
   was sie ohnehin hat, und genau das ist die gewollte Zurueckhaltung. */
.site-footer__credit { margin: 0; }
.site-footer__credit a { color: inherit; }
.site-footer__credit a:hover,
.site-footer__credit a:focus-visible { color: var(--color-on-dark); }

/* Gemeldet am 22.09.2026: Die Agenturnennung hing ohne Trennung an
   der Werkstattzeile, und dem Markennamen sah man nicht an, dass er ein Link
   ist. Jetzt steht sie rechts hinter einer senkrechten Linie, getrennt von
   allem, was den Betrieb betrifft, und traegt dieselbe Unterstreichung wie
   jeder andere Textlink der Seite. */
.site-footer__base-rechts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-xs) var(--space-m);
}
@media (min-width: 760px) {
  .site-footer__base-rechts .site-footer__credit {
    border-left: 1px solid var(--color-line-dark);
    padding-left: var(--space-m);
  }
}
/* Auf dem Telefon stehen die drei Zeilen untereinander. Damit die Trennung
   auch dort sichtbar bleibt, wird aus der senkrechten Linie eine waagerechte. */
@media (max-width: 759px) {
  .site-footer__base-rechts { width: 100%; }
  .site-footer__base-rechts .site-footer__credit {
    width: 100%;
    border-top: 1px solid var(--color-line-dark);
    padding-top: var(--space-xs);
  }
}
.link-unterstrichen {
  border-bottom: 1px solid var(--color-line-dark);
  padding-bottom: 2px;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}
.link-unterstrichen:hover { border-color: var(--color-accent-soft); }

/* Die aktive Seite in der Kopfnavigation. Ohne Markierung weiß niemand,
   wo er steht, sobald es mehr als eine Seite gibt. */
.site-nav a[aria-current="page"] {
  color: var(--color-text);
  text-decoration: underline;
  text-underline-offset: 0.4em;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--color-accent);
}

/* ---------- Touch-Ziele auf dem Telefon ---------- */

/* Gemessen bei 360px: die Telefonnummer im Fuß war 20px hoch,
   die Menüpunkte 17px. Verlangt sind 44px (WCAG 2.5.5). Umgesetzt über
   vertikales Padding statt über display: Die Trefferfläche eines Inline-
   Elements schließt sein Padding ein, die Zeilenhöhe bleibt davon unberührt.
   Das Layout verschiebt sich also nicht, die Fläche wächst trotzdem. */
@media (max-width: 820px) {
  .site-nav a,
  .site-footer a,
  .contact__block a,
  .club__contact a,
  a[href^="tel:"],
  a[href^="mailto:"] {
    padding-block: 0.85rem;
    /* Ohne das überlappen die Trefferflächen untereinanderstehender Links. */
    margin-block: -0.45rem;
  }
  .site-nav { row-gap: 0; }
  /* Die Regel darueber gilt fuer einzelne Links im Fliesstext des Fusses.
     Die Linkspalten haben seit dem 21.09.2026 ihre eigene Mindesthoehe; kaeme
     das Polster dazu, waeren es wieder 50px je Zeile und der Fuss so hoch wie
     vorher. Auf dem Telefon 40px statt 34px, weil dort der Daumen zielt. */
  .site-footer__cols nav a { padding-block: 0; margin-block: 0; min-height: 36px; }
  /* Diese Regel stammt aus der Zeit vor dem Signet, als die Wortmarke nur
     aus zwei Textzeilen bestand, und stellte sie auf eine Spalte. Seit das
     Wappen daneben steht, schob genau das es auf dem Telefon in eine eigene
     Zeile darüber. Die 44px-Trefferfläche bleibt, die Richtung nicht. */
  .wordmark { min-height: 44px; }
  /* Zwei Links nebeneinander im Fließtext dürfen sich seitlich nicht
     berühren, sonst trifft der Daumen den falschen. */
  .expect__item a + a, .stance__item a + a, .craft__item a + a { margin-left: 0.35rem; }
}

/* Formularlabel: Ein Klick darauf fokussiert das Feld, also ist es ein
   Bedienziel und braucht dieselben 44px wie ein Link (gemessen: 26px). */
@media (max-width: 820px) {
  .field > label { display: block; padding-block: 0.8rem 0.45rem; margin-top: -0.8rem; }
}

/* Eine Kartenliste in einer schmalen Sektion lässt auf 1920px 460px je Seite
   ungenutzt. Sie darf deshalb über den Lesesatz hinausgehen:
   Der Fließtext bleibt schmal und lesbar, die Karten nutzen die Fläche. */
.container--narrow > .expect__list,
.container--narrow > .gallery {
  width: min(100vw - 2 * var(--space-m), 1600px);
  margin-inline: calc(50% - min(50vw - var(--space-m), 800px));
}

/* Eine Leistungsüberschrift, die auf ihre Unterseite verlinkt, ist ein
   Tap-Ziel wie jeder andere Link (gemessen: 32px). */
@media (max-width: 820px) {
  .craft__item h2 a, .craft__item h3 a { display: inline-block; padding-block: 0.65rem; }
  /* Eigenstaendig stehende Textlinks: der Hero-Zweitweg und die Vereins-
     adresse unter dem Logo (gemessen 25 bis 29px). */
  .hero__actions .link-underline,
  .club__mark a { display: inline-block; padding-block: 0.7rem; }
}

/* Die Anfrage-Sektion liess auf 1920px 460px je Seite ungenutzt. Das Formular
   soll schmal bleiben - ein Eingabefeld ueber 1400px ist unbrauchbar -, die
   Schale darum darf aber mitwachsen. */
@media (min-width: 1500px) {
  /* Die Schale bricht aus dem Lesesatz aus und traegt die Flaeche, das
     Formular darin bleibt bei 62ch - ein Eingabefeld ueber 1400px ist
     unbrauchbar. */
  .form-shell {
    width: min(100vw - 2 * var(--space-m), 1560px);
    margin-inline: calc(50% - min(50vw - var(--space-m), 780px));
    padding-inline: clamp(2rem, 5vw, 6rem);
  }
  .form-shell form { max-width: 68ch; margin-inline: auto; }
}

/* Lesesatz für die Rechtstexte: dort steht Fließtext ohne Sektionsmuster. */
.prose h2 { font-size: var(--step-1); margin-top: var(--space-m); margin-bottom: var(--space-xs); }
.prose h3 { font-size: var(--step-0); margin-top: var(--space-m); margin-bottom: var(--space-2xs); }
.prose p, .prose li { color: var(--color-text-soft); max-width: 68ch; }
.prose p + p { margin-top: var(--space-s); }
.prose ul, .prose ol { margin: var(--space-s) 0 var(--space-s) 1.25rem; }
.prose li + li { margin-top: var(--space-2xs); }
.prose code { font-size: 0.92em; padding: 0.05em 0.3em; background: var(--color-bg-tint); border-radius: var(--radius); }
.prose .rechtstext-stand { margin-top: var(--space-l); font-size: var(--step--1); color: var(--color-text-faint); }

/* ---------- Leistungs-Menü im Kopf ---------- */

/* Zwei getrennte Bedienelemente, mit Absicht: Der Link führt auf die
   Übersicht, der Knopf daneben klappt die einzelnen Leistungen auf. Ein
   Menüpunkt, der beides tut, kann nur eines davon ohne JavaScript – und ohne
   JavaScript soll „Leistungen" weiterhin auf /leistungen/ führen. */
.site-nav__group { position: relative; display: inline-flex; align-items: center; gap: 0.15rem; }

.site-nav__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  min-height: 1.5rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--color-text-faint);
  cursor: pointer;
  border-radius: var(--radius-s, 4px);
  transition: color 0.2s var(--ease), transform 0.2s var(--ease);
}
.site-nav__toggle:hover { color: var(--color-text); }
.site-nav__toggle[aria-expanded="true"] { color: var(--color-text); transform: rotate(180deg); }
/* Ohne JavaScript bleibt der Knopf weg: Er könnte dann nichts aufklappen. */
.no-js .site-nav__toggle { display: none; }

.site-nav__menu {
  position: absolute;
  top: calc(100% + 0.65rem);
  left: -0.9rem;
  z-index: 60;
  min-width: 17rem;
  margin: 0;
  padding: 0.5rem 0;
  list-style: none;
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius);
  box-shadow: 0 18px 40px -22px rgb(0 0 0 / 0.45), 0 2px 6px -2px rgb(0 0 0 / 0.12);
}
.site-nav__menu[hidden] { display: none; }
.site-nav__menu li { margin: 0; }
.site-nav__menu a {
  display: block;
  padding: 0.55rem 1.1rem;
  font-size: var(--step--1);
  color: var(--color-text-soft);
  white-space: nowrap;
}
.site-nav__menu a:hover,
.site-nav__menu a:focus-visible { background: var(--color-bg-tint); color: var(--color-text); }
.site-nav__menu a[aria-current="page"] {
  color: var(--color-text);
  box-shadow: inset 3px 0 0 var(--color-accent);
}
/* Die letzten beiden sind Möbelmontage und Trockenbau. Sie gehören zum
   Betrieb, aber nicht zum Schwerpunkt – abgesetzt statt gleichrangig. */
.site-nav__menu li:nth-last-child(2) { border-top: 1px solid var(--color-line); margin-top: 0.4rem; padding-top: 0.4rem; }

/* „Leistungen" bleibt markiert, solange man auf einer ihrer Unterseiten ist. */
.site-nav a[aria-current="true"] { color: var(--color-text); }

@media (max-width: 820px) {
  /* Kein schwebendes Menü auf dem Telefon: Es klappt in der Zeile auf und
     schiebt den Inhalt nach unten, statt über ihm zu liegen. */
  .site-nav__menu {
    position: static;
    min-width: 0;
    border: 0;
    box-shadow: none;
    background: none;
    padding: 0.25rem 0 0.5rem;
  }
  /* Die aufgeklappte Liste faellt unter die Zeile, Link und Pfeil bleiben
     nebeneinander. Vorher brach schon der Pfeil um. */
  .site-nav__group:has(.site-nav__menu:not([hidden])) { flex-wrap: wrap; }
  .site-nav__menu { flex: 1 0 100%; }
  .site-nav__menu a { padding-block: 0.7rem; padding-inline: 0 1rem; }
  .site-nav__toggle { min-height: 44px; width: 44px; }
}

/* =========================================================================
   Hero der Unterseiten
   Die erste Fassung war ein Seitenkopf: Eyebrow, Überschrift, Vorspann, aus.
   Wer auf einer Unterseite landete, sah eine Überschrift und musste raten,
   was darunter kommt. Jetzt beantwortet der Einstieg drei Fragen, bevor
   jemand dafür scrollt: worum es geht, was zu sehen ist, was weiter unten
   steht.
   ========================================================================= */

.seitenhero {
  position: relative;
  padding-block: clamp(2.5rem, 5vw, 4rem) clamp(3rem, 6vw, 5rem);
  border-bottom: 1px solid var(--color-line);
  overflow: hidden;
}

.seitenhero__grid { display: grid; gap: var(--space-m); }
@media (min-width: 900px) {
  .seitenhero__grid {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.72fr);
    gap: clamp(2rem, 5vw, 4.5rem);
    align-items: center;
  }
}

.seitenhero h1 {
  font-size: var(--step-3);
  max-width: 18ch;
  margin: 0 0 var(--space-m);
  text-wrap: balance;
}
.seitenhero .lead { max-width: 54ch; margin: 0; }
.seitenhero .hero__actions { margin-top: var(--space-m); }
/* Kleine Telefone (gemessen 27.10.2026 auf 375x667): Auf drei Unterseiten
   lag der Knopf bis 35px unter dem Falz. Zwei Ursachen: Der Vorspann stand
   in 19px statt in der Fliesstextgroesse, die der Startseiten-Hero auf dem
   Telefon schon hat, und Knopf, Abstand und Telefonnummer brauchten 344px
   bei 343px Platz - die Nummer brach wegen eines Pixels in eine eigene
   Zeile. Jetzt Vorspann wie .hero__text (gemeinsame Regel im Hero-Block fuer
   unter 900px), Knopf und Nummer nebeneinander. Nur der Abstand wird
   schmaler, die Knoepfe behalten ihre eigenen Innenabstaende. */
@media (max-width: 430px) {
  .seitenhero .hero__actions { column-gap: var(--space-s); }
}
/* Die Nummer bricht nie in sich um, nur als Ganzes in die naechste Zeile. */
.hero__actions .link-underline { white-space: nowrap; }

/* Das Bild bleibt beim Öffnen der Seite vollständig sichtbar. Ein Hochformat
   in voller Spaltenbreite wurde auf dem Desktop höher als der Bildschirm –
   dann sieht man ein Stück Holz und weiß nicht, wovon. */
.seitenhero__bild { margin: 0; }
/* Passepartout statt Beschnitt, wie in der Werkschau der Startseite. Mit
   object-fit: cover war der Büffettschrank unten abgeschnitten – dieselbe
   Sache, die in der Galerie schon falsch war. Ein Stück, das die Werkstatt
   zeigen soll, wird ganz gezeigt; der Rahmen gibt die Höhe vor, das Bild
   sitzt darin. */
.seitenhero__bild picture {
  display: flex;
  align-items: center;
  justify-content: center;
  height: min(62vh, 30rem);
  padding: clamp(0.75rem, 2vw, 1.4rem);
  background: var(--color-surface);
  border: 1px solid var(--color-line);
  border-radius: var(--radius);
}
.seitenhero__bild img {
  width: auto;
  height: 100%;
  max-width: 100%;
  object-fit: contain;
  border-radius: 2px;
  box-shadow: 0 12px 30px -18px rgb(0 0 0 / 0.5);
}
@media (max-width: 899px) {
  .seitenhero__bild picture { height: min(46vh, 22rem); }
}
/* Nur am breiten Schirm (seit 28.09.2026, zuerst „Über uns“, Hobelbank).
   Die erste <source> im Markup liefert unter 900px ein leeres GIF, damit das
   Telefon die Datei gar nicht erst lädt; die Regel hier nimmt den Rahmen weg. */
@media (max-width: 899px) {
  .seitenhero__bild--nur-breit { display: none; }
}
.seitenhero__bild figcaption {
  margin-top: var(--space-s);
  font-size: var(--step--1);
  line-height: 1.6;
  color: var(--color-text-faint);
  max-width: 46ch;
}

/* Inhaltsverzeichnis: sagt, was die Seite hergibt, und springt hin. */
.seitenhero__inhalt {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1.1rem;
  margin-top: var(--space-l);
  padding-top: var(--space-s);
  border-top: 1px solid var(--color-line);
}
.seitenhero__inhalt > span {
  font-size: var(--step--1);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-faint);
  font-weight: 600;
}
.seitenhero__inhalt a {
  font-size: var(--step--1);
  color: var(--color-text-soft);
  text-decoration: underline;
  text-decoration-color: var(--color-line-strong);
  text-underline-offset: 0.3em;
}
.seitenhero__inhalt a:hover { color: var(--color-text); text-decoration-color: var(--color-accent); }
@media (max-width: 820px) {
  /* Sprungmarken sind Tap-Ziele wie jeder Link (gemessen: 22px). */
  .seitenhero__inhalt a { display: inline-flex; align-items: center; min-height: 44px; }
  .seitenhero__inhalt { gap: 0 1rem; }
}

/* Der Hinweis nach unten. Er bewegt sich, weil Bewegung hier eine Aussage
   hat: Es geht weiter. Bei reduzierter Bewegung steht er still, bleibt aber
   sichtbar und anklickbar. */
.weiterunten {
  display: none;
  position: absolute;
  right: max(var(--space-m), calc(50vw - var(--maxw-narrow) / 2 - 1rem));
  bottom: var(--space-m);
  align-items: center;
  gap: 0.45rem;
  font-size: var(--step--1);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-text-faint);
}
@media (min-width: 900px) { .weiterunten { display: inline-flex; } }
.weiterunten:hover { color: var(--color-text); }
.weiterunten svg { animation: weiterunten 2.4s var(--ease) infinite; }
@keyframes weiterunten {
  0%, 100% { transform: translateY(0); opacity: 0.55; }
  50%      { transform: translateY(5px); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .weiterunten svg { animation: none; opacity: 1; }
}
.reduced-motion .weiterunten svg { animation: none; opacity: 1; }

/* Beim Öffnen setzen sich Text und Bild leicht. Der Startzustand ist
   sichtbar, nicht opacity 0: Wer ohne JavaScript oder mit reduzierter
   Bewegung kommt, sieht die fertige Seite, nicht eine leere. */
@media (prefers-reduced-motion: no-preference) {
  .js .seitenhero__body > *,
  .js .seitenhero__bild { animation: hereinsetzen 0.65s var(--ease) both; }
  .js .seitenhero__body > *:nth-child(2) { animation-delay: 0.06s; }
  .js .seitenhero__body > *:nth-child(3) { animation-delay: 0.12s; }
  .js .seitenhero__body > *:nth-child(4) { animation-delay: 0.18s; }
  .js .seitenhero__body > *:nth-child(5) { animation-delay: 0.24s; }
  .js .seitenhero__bild { animation-delay: 0.1s; animation-duration: 0.8s; }
}
@keyframes hereinsetzen {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}

/* Hier standen `.seitenhero__fakten` und `.seitenhero--ohne-bild`: ein
   Faktenfeld anstelle des Kopfbildes, für Fenster, Trockenbau und
   Möbelmontage, weil im Material keine Aufnahme davon lag. Seit der
   Bildlieferung vom 12.10.2026 liegt sie. Beide Klassen werden von keiner
   Seite mehr benutzt und sind deshalb entfernt — die Begründung bleibt hier
   stehen, falls eine Seite wieder ohne Foto auskommen muss. */

/* ---------- Bildkacheln ---------- */

/* Die Themen standen als Textliste da und lasen sich wie eine Aufzählung im
   Angebot. Als Bildfeld sieht jemand in einer Sekunde, worum es geht: Fünf
   Möbel, fünf Ausgangslagen. Fünf geht in keinem gleichmäßigen Raster auf,
   deshalb steht das erste breit und die vier übrigen paarweise darunter —
   das schließt die Fläche und gibt gleichzeitig eine Rangfolge. */
.feldkacheln {
  display: grid;
  gap: var(--space-s);
}
@media (min-width: 700px) {
  .feldkacheln { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-m); }
  .feldkachel--breit { grid-column: 1 / -1; }
}

.feldkachel {
  position: relative;
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--color-dark);
  min-height: 19rem;
  isolation: isolate;
}
.feldkachel--breit { min-height: 22rem; }
@media (min-width: 900px) { .feldkachel--breit { min-height: 26rem; } }

.feldkachel picture { position: absolute; inset: 0; }
.feldkachel img {
  width: 100%; height: 100%;
  object-fit: cover;
  /* Leicht abgedunkelt und entsättigt, damit die Schrift darauf steht und
     fünf verschiedene Fotos zusammen ruhig wirken. Beim Überfahren kommt
     die Farbe zurück — die Bewegung zeigt, dass das Feld gemeint ist. */
  filter: brightness(0.72) saturate(0.85);
  transform: scale(1.02);
  transition: filter 0.45s var(--ease), transform 0.65s var(--ease);
}
/* Verlauf von unten, sonst steht der Text auf einer hellen Bildstelle. */
.feldkachel::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(to top, oklch(0.18 0.02 55 / 0.92) 0%, oklch(0.18 0.02 55 / 0.55) 42%, oklch(0.18 0.02 55 / 0.1) 75%);
  z-index: 1;
  pointer-events: none;
}
.feldkachel:hover img,
.feldkachel:focus-within img { filter: brightness(0.82) saturate(1); transform: scale(1.06); }

.feldkachel__text {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  height: 100%;
  padding: clamp(1.2rem, 3vw, 2rem);
  color: var(--color-on-dark);
}
.feldkachel__nr {
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.14em;
  color: var(--color-accent-soft);
  margin-bottom: 0.4rem;
}
.feldkachel__text h3 {
  color: var(--color-on-dark);
  font-size: var(--step-2);
  margin: 0 0 0.5rem;
}
.feldkachel--breit .feldkachel__text h3 { font-size: var(--step-3); }
.feldkachel__text p {
  color: var(--color-on-dark-soft);
  margin: 0;
  max-width: 52ch;
  font-size: var(--step-0);
}
/* Kacheln ohne Foto (seit 23.10.2026, /trockenbau/). Vorher standen dort
   Bretterstapel und Bettpfosten unter "Wand", "Decke", "Dachgeschoss" -
   irrefuehrend, denn ein Bild, das nicht zeigt, was darunter steht, behauptet etwas Falsches.
   Also Text auf dunklem Grund, oben beginnend statt unten. Die Bewegung
   beim Ueberfahren bleibt, nur am Grund statt am Foto.
   Seit 26.10.2026 tragen auf /trockenbau/ wieder alle vier Kacheln ein
   Foto aus dem Rohbau-Auftrag. Die Variante bleibt fuer den Fall, dass
   eines davon wieder herausgenommen wird. */
/* Hohe Kacheln fuer /trockenbau/: Bei 19rem lag der Text ueber fast dem
   ganzen Foto, Staenderwerk und Tuerzarge waren nicht zu erkennen
   (gemessen 26.10.2026: 304 px Kachel, rund 200 px Text). */
.feldkacheln--hoch .feldkachel { min-height: 28rem; }
/* Der Schaden sitzt im oberen Drittel des Hochformats. */
.feldkachel img[src*="tuerzarge-aufgebrochen"] { object-position: 50% 30%; }
.feldkachel--ohne-bild {
  min-height: 0;
  background: var(--color-dark);
  border: 1px solid var(--color-line-dark);
  transition: background-color 0.35s var(--ease), border-color 0.35s var(--ease);
}
.feldkachel--ohne-bild::after { content: none; }
.feldkachel--ohne-bild .feldkachel__text { justify-content: flex-start; }
.feldkachel--ohne-bild:hover,
.feldkachel--ohne-bild:focus-within {
  background: var(--color-dark-tint);
  border-color: var(--color-accent);
}

@media (prefers-reduced-motion: reduce) {
  .feldkachel img { transition: none; transform: none; }
  .feldkachel:hover img, .feldkachel:focus-within img { transform: none; }
  .feldkachel--ohne-bild { transition: none; }
}

/* ---------- Werkbank: die Stationen einer Restaurierung ---------- */

/* Kein Kachelraster. Sechs Zeilen, die sich wie eine Reihenfolge lesen:
   Gewerk links, Arbeit rechts, durchnummeriert. Beim Überfahren wächst eine
   Messinglinie von links und die Zeile rückt ein Stück nach — genug, damit
   klar ist, wo man steht, ohne dass die Liste zappelt. */
.werkbank { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--color-line); }

.werkbank__station {
  position: relative;
  display: grid;
  gap: 0.35rem 1.5rem;
  padding: clamp(1.2rem, 2.5vw, 1.8rem) 0;
  border-bottom: 1px solid var(--color-line);
  transition: padding-left 0.35s var(--ease), background-color 0.35s var(--ease);
}
@media (min-width: 820px) {
  .werkbank__station {
    grid-template-columns: 3.5rem 12rem minmax(0, 1fr);
    align-items: baseline;
    gap: 0 clamp(1.5rem, 3vw, 3rem);
  }
}

/* Die Linie liegt schon da und ist nur null breit. Eine Breite zu animieren,
   die erst bei :hover entsteht, ruckelt beim ersten Mal. */
.werkbank__station::before {
  content: "";
  position: absolute;
  left: 0; top: -1px; bottom: -1px;
  width: 0;
  background: var(--color-accent);
  transition: width 0.35s var(--ease);
}
.werkbank__station:hover,
.werkbank__station:focus-within { background: var(--color-surface); padding-left: 1.2rem; }
.werkbank__station:hover::before,
.werkbank__station:focus-within::before { width: 3px; }

.werkbank__nr {
  font-size: var(--step--1);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-faint);
  letter-spacing: 0.1em;
}
.werkbank__gewerk {
  font-family: var(--font-display);
  font-variation-settings: "SOFT" 20;
  font-size: var(--step-1);
  color: var(--color-accent-ink);
  line-height: 1.2;
}
.werkbank__arbeit h3 { margin: 0 0 0.3rem; font-size: var(--step-1); }
.werkbank__arbeit p { margin: 0; color: var(--color-text-soft); max-width: 72ch; }

@media (max-width: 819px) {
  .werkbank__nr { display: none; }   /* auf dem Telefon ist die Zahl Ballast */
  .werkbank__gewerk { font-size: var(--step-0); }
}
@media (prefers-reduced-motion: reduce) {
  .werkbank__station, .werkbank__station::before { transition: none; }
}

/* ---------- Referenzen: drei Arbeiten, die von selbst wechseln ---------- */

.referenzen__grid { display: grid; gap: var(--space-m); align-items: center; }
@media (min-width: 820px) {
  .referenzen__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr); gap: clamp(2rem, 5vw, 4rem); }
}

/* Alle drei liegen übereinander in einer Grid-Zelle. Die Bühne hat deshalb
   eine feste Höhe, sonst springt die Seite bei jedem Wechsel. */
.referenzen__buehne {
  display: grid;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--color-bg-tint);
}
.referenz {
  grid-area: 1 / 1;
  margin: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.7s var(--ease), visibility 0.7s var(--ease);
}
.referenz.is-active { opacity: 1; visibility: visible; }
/* Ohne JavaScript stehen alle drei untereinander statt gar keine. */
.no-js .referenzen__buehne { display: block; }
.no-js .referenz { opacity: 1; visibility: visible; margin-bottom: var(--space-s); }

.referenz picture { display: block; aspect-ratio: 4 / 3; }
.referenz img { width: 100%; height: 100%; object-fit: cover; }
.referenz figcaption {
  position: absolute;
  inset: auto 0 0 0;
  padding: clamp(1rem, 2.5vw, 1.5rem);
  background: linear-gradient(to top, oklch(0.16 0.02 55 / 0.95) 0%, oklch(0.16 0.02 55 / 0.8) 45%, oklch(0.16 0.02 55 / 0) 100%);
  padding-top: clamp(2.5rem, 6vw, 4rem);
  color: var(--color-on-dark);
  font-size: var(--step--1);
}
.referenz { position: relative; }
.referenz figcaption b { display: block; font-size: var(--step-0); margin-bottom: 0.15rem; }
.referenz figcaption span { color: var(--color-on-dark-soft); }

.referenzen__punkte { display: flex; gap: 0.5rem; margin-top: var(--space-m); }
.referenzen__punkte button {
  width: 44px; height: 44px;           /* Trefferfläche, sichtbar ist der Punkt */
  padding: 0; border: 0; background: none; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.referenzen__punkte button::before {
  content: "";
  width: 2.2rem; height: 3px;
  background: var(--color-line-strong);
  transition: background-color 0.3s var(--ease);
}
.referenzen__punkte button:hover::before { background: var(--color-text-faint); }
.referenzen__punkte button[aria-current="true"]::before { background: var(--color-accent); }

@media (prefers-reduced-motion: reduce) { .referenz { transition: none; } }

/* ---------- Fragen und Antworten ---------- */

/* Die drei Punkte standen als "Es dauert", "Es gibt keine Pauschale",
   "Die Einschätzung kann ein Nein sein" nebeneinander und lasen sich wie
   Bedingungen. Als Frage und Antwort lesen sie sich wie ein Gespräch — und
   es sind genau die Fragen, die am Telefon als erstes kommen. */
/* Aufklappbar seit dem 18.09.2026. Vier ausformulierte Antworten
   untereinander waren auf /fenstersanierungen/ 1706px hoch und haben den
   Abschluss der Seite nach unten gedrueckt. Wer eine bestimmte Frage sucht,
   findet sie in einer Liste aus vier Zeilen schneller als in vier Absaetzen.

   <details> statt JavaScript: Es klappt ohne Skript, ist mit Tastatur
   bedienbar, und der Browser meldet den Zustand von sich aus vor. Der
   Antworttext steht im Quelltext und wird von Suchmaschinen gelesen, auch
   wenn er zugeklappt ist. */
.fragen { display: grid; gap: 0; border-top: 1px solid var(--color-line-strong); }
.frage {
  border-bottom: 1px solid var(--color-line-strong);
}
.frage summary {
  position: relative;
  display: block;
  padding-block: clamp(1rem, 2vw, 1.3rem);
  padding-right: 2.5rem;
  cursor: pointer;
  list-style: none;
  transition: color 0.25s var(--ease);
}
.frage summary::-webkit-details-marker { display: none; }
.frage summary:hover { color: var(--color-accent); }
.frage summary:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
  border-radius: 2px;
}
.frage h3 {
  font-family: var(--font-display);
  font-variation-settings: "SOFT" 20;
  font-size: var(--step-1);
  line-height: 1.25;
  margin: 0;
  max-width: 44ch;
  color: inherit;
}
/* Das Zeichen rechts: zwei Balken. Der senkrechte legt sich beim Aufklappen
   auf den waagerechten, aus dem Plus wird ein Minus. Zwei Elemente statt
   eines gedrehten Kreuzes, weil ein um 90 Grad gedrehtes Plus wieder ein Plus
   ist - der erste Versuch am 18.09.2026 sah im Screenshot deshalb in beiden
   Zustaenden gleich aus. Bewegt wird nur transform. */
.frage summary::before,
.frage summary::after {
  content: "";
  position: absolute;
  right: 0.2rem;
  top: calc(clamp(1rem, 2vw, 1.3rem) + 0.62em);
  width: 1.05rem;
  height: 1.5px;
  background: currentColor;
  opacity: 0.55;
  transition: transform 0.3s var(--ease), opacity 0.25s var(--ease);
}
.frage summary::after { transform: rotate(90deg); }
.frage[open] summary::after { transform: rotate(0deg); }
.frage[open] summary::before,
.frage[open] summary::after { opacity: 1; }
.frage[open] summary { color: var(--color-accent); }
.frage__antwort {
  padding-bottom: clamp(1.1rem, 2.4vw, 1.6rem);
  padding-right: 2rem;
}
.frage p { margin: 0; color: var(--color-text-soft); max-width: 68ch; }

/* Das Aufklappen selbst: nur da, wo der Browser die Hoehe interpolieren kann.
   Wo nicht, erscheint die Antwort ohne Uebergang - das ist kein Fehler,
   sondern der Normalfall vor calc-size(). */
@supports (interpolate-size: allow-keywords) {
  .frage { interpolate-size: allow-keywords; }
  .frage::details-content {
    block-size: 0;
    overflow: hidden;
    transition: block-size 0.35s var(--ease), content-visibility 0.35s allow-discrete;
  }
  .frage[open]::details-content { block-size: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .frage summary::before, .frage summary::after { transition: none; }
  .frage::details-content { transition: none; }
}
.fragen__rest { margin-top: var(--space-l); color: var(--color-text-faint); }

/* Unter den Fragen stand die Telefonnummer neben dem Verweis ins Formular,
   auf zwei Seiten kamen verwandte Seiten dazu. Drei Wege an einer Stelle sind
   keine Auswahl, sondern eine Entscheidung, die der Leser nicht treffen will.
   Jetzt ein Weg, und weil das Formular direkt darunter steht, zeigt der Pfeil
   dorthin. Die Telefonnummer steht weiter im Hero und im Fuss. */
.fragen__weiter { margin-top: var(--space-l); }
.btn__pfeil {
  flex: none;
  margin-left: 0.1em;
  transition: transform 0.3s var(--ease);
}
.btn:hover .btn__pfeil,
.btn:focus-visible .btn__pfeil { transform: translateY(3px); }
@media (prefers-reduced-motion: reduce) {
  .btn__pfeil, .btn:hover .btn__pfeil { transition: none; transform: none; }
}

/* ---------- Brotkrumenpfad ---------- */

/* Er steht an der Stelle, an der vorher die Eyebrow "Leistung · <Name>"
   stand. Die sagte dasselbe, nur ohne Weg zurueck: Gemessen am 18.09.2026
   hatte /leistungen/ null eingehende Links aus dem Fliesstext und war nur
   ueber das Menue erreichbar, und /fenstersanierungen/ war eine Sackgasse
   ohne einen einzigen ausgehenden Link. Beides loest der Pfad auf einmal.

   Optisch bleibt es die Eyebrow, damit der Hero seinen Aufbau behaelt. */
.brotkrumen { margin-bottom: var(--space-s); }
.brotkrumen ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.5rem;
  font-size: var(--step--1);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--color-text-faint);
}
.brotkrumen li { display: flex; align-items: baseline; gap: 0.5rem; }
/* Das Zeichen gehoert zur Darstellung, nicht zum Text - deshalb im CSS und
   nicht im Quelltext, wo ein Screenreader es mitlesen wuerde. */
.brotkrumen li + li::before {
  content: "\203A";
  color: var(--color-text-faint);
  opacity: 0.6;
}
.brotkrumen a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.25s var(--ease), border-color 0.25s var(--ease);
}
.brotkrumen a:hover,
.brotkrumen a:focus-visible {
  color: var(--color-accent);
  border-bottom-color: currentColor;
}
.brotkrumen [aria-current="page"] { color: var(--color-text-soft); }

/* Auf dem Telefon waren die beiden Links 23px hoch und damit unter dem
   Mindestmass von 44px - gemessen, bevor es jemand mit dem Daumen
   gemerkt haette. Die Flaeche waechst, die Schrift nicht; der
   negative Aussenabstand holt zurueck, was die Polsterung oben und unten
   zusaetzlich braucht. */
@media (max-width: 819px) {
  .brotkrumen { margin-block: -0.7rem var(--space-2xs); }
  .brotkrumen li { align-items: center; }
  .brotkrumen a,
  .brotkrumen [aria-current="page"] {
    display: inline-flex;
    align-items: center;
    /* 46 statt 44: Bei genau 44 landet der gerenderte Wert je nach
       Zeilenhoehe auf 43,99 und liegt knapp unter dem Mindestmass. */
    min-height: 46px;
  }
}

/* Nebeninformation unter einem Abschnitt: sie gehoert dazu, traegt ihn aber
   nicht. Deshalb kleiner und blasser als der Vorspann, an dessen Stelle sie
   auf /fenstersanierungen/ getreten ist. */
.randnotiz {
  margin-top: var(--space-l);
  max-width: 62ch;
  font-size: var(--step--1);
  color: var(--color-text-faint);
}
/* Derselbe Block auf dunklem Grund. */
.section--dark .fragen { border-top-color: var(--color-line-dark); }
.section--dark .frage { border-bottom-color: var(--color-line-dark); }
.section--dark .frage p { color: var(--color-on-dark-soft); }
.section--dark .fragen__rest { color: var(--color-on-dark-soft); }

/* ---------- Betonung in einer Überschrift ---------- */

/* Ein Wort in der H1 unterstreichen, ohne dass es nach Link aussieht: die
   Linie sitzt tiefer als eine Textdekoration und trägt die Akzentfarbe.
   text-decoration-skip-ink lässt Unterlängen frei. */
.betont {
  font-style: normal;
  text-decoration: underline;
  text-decoration-color: var(--color-accent);
  text-decoration-thickness: 0.06em;
  text-underline-offset: 0.14em;
  text-decoration-skip-ink: auto;
}

/* ---------- Zeitstrahl ---------- */

/* Der Ablauf stand als Werkbank-Liste da und las sich wie eine Aufzählung.
   Als Strahl sieht man auf einen Blick, dass es vier Schritte in einer festen
   Reihenfolge sind und wo die eigene Entscheidung dazwischen liegt.
   Auf dem Telefon läuft er senkrecht, ab 820px waagerecht. */
.zeitstrahl {
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
  display: grid;
  gap: var(--space-l);
}

/* Die graue Grundlinie und darüber die mitwachsende Akzentlinie. Beide sind
   eigene Elemente statt Rahmen, weil nur transform animiert werden darf. */
.zeitstrahl::before,
.zeitstrahl::after {
  content: "";
  position: absolute;
  background: var(--color-line-strong);
}
.zeitstrahl::after {
  background: var(--color-accent);
  transform-origin: top;
  transform: scaleY(var(--fortschritt, 0));
}

@media (max-width: 819px) {
  .zeitstrahl { padding-left: 2.2rem; }
  .zeitstrahl::before,
  .zeitstrahl::after { left: 0.45rem; top: 0.5rem; bottom: 0.5rem; width: 2px; }
}

@media (min-width: 820px) {
  /* Feste vier Spalten waren fuer /innenausbau-u-moebel/ gebaut. Die
     Startseite hat drei Stationen, die vierte Spalte blieb leer und die drei
     Texte quetschten sich in drei Viertel der Breite: auf 1440 gemessen 220px
     je Spalte, also sechs bis acht Woerter Zeilenlaenge. Automatische Spalten
     passen sich der Zahl der Stationen an, auf beiden Seiten. */
  .zeitstrahl {
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: var(--space-l);
    padding-top: 2.6rem;
  }
  .zeitstrahl__station p { max-width: 42ch; }
  /* Die Linie laeuft durch, ueber die ganze Breite der Sektion.

     Endet sie an der letzten Marke, wirkt sie abgebrochen, mitten unter dem
     Text der letzten Station. Der Strich ist eine Achse, keine Fortschritts-
     anzeige, die an der letzten Station halt macht. */
  .zeitstrahl::before,
  .zeitstrahl::after {
    top: 0.45rem; left: 0; right: 0; height: 2px;
    transform-origin: left;
  }
  .zeitstrahl::after { transform: scaleX(var(--fortschritt, 0)); }
}

.zeitstrahl__station { position: relative; }

/* Die Marke auf der Linie. Gefüllt, sobald die Station erreicht ist. */
.zeitstrahl__marke {
  position: absolute;
  width: 1rem; height: 1rem;
  border-radius: 50%;
  background: var(--color-bg);
  border: 2px solid var(--color-line-strong);
  transition: border-color 0.4s var(--ease), background-color 0.4s var(--ease);
}
@media (max-width: 819px) {
  .zeitstrahl__marke { left: -2.2rem; top: 0.1rem; }
}
@media (min-width: 820px) {
  .zeitstrahl__marke { left: 0; top: -2.6rem; }
}
.zeitstrahl__station.is-in .zeitstrahl__marke {
  border-color: var(--color-accent);
  background: var(--color-accent);
}

.zeitstrahl__nr {
  display: block;
  font-size: var(--step--1);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--color-text-faint);
  margin-bottom: 0.35rem;
  transition: color 0.4s var(--ease);
}
/* accent auf hellem Grund ergab 3.30:1 (gemessen 15.10.2026, Grenze 4.5).
   accent-ink ist dafuer da: 5.85:1 auf bg-tint. Betrifft auch
   /innenausbau-u-moebel/, wo der Strahl ebenfalls auf hellem Grund steht -
   dort fiel es nie auf, weil die Farbe erst beim Scrollen gesetzt wird. */
.zeitstrahl__station.is-in .zeitstrahl__nr { color: var(--color-accent-ink); }
/* Auf /danke/ ist die erste Station schon geschehen: Die Anfrage liegt vor,
   der Besucher hat sie gerade abgeschickt. Sie wird deshalb sofort gefuellt
   gezeigt, unabhaengig vom Scrollen - waehrend die uebrigen Stationen wie
   ueberall beim Durchscrollen anspringen. Das ist der Unterschied zwischen
   einer Ankuendigung (Startseite: "so wird es laufen") und einem Stand
   ("hier stehen Sie gerade"). */
.zeitstrahl__station--fertig .zeitstrahl__marke {
  border-color: var(--color-accent);
  background: var(--color-accent);
  display: grid;
  place-items: center;
  color: var(--color-bg);
}
.zeitstrahl__station--fertig .zeitstrahl__nr { color: var(--color-accent-ink); }

.zeitstrahl__station h3 { margin: 0 0 0.4rem; font-size: var(--step-1); }
.zeitstrahl__station p { margin: 0; color: var(--color-text-soft); }
/* Auf dunklem Grund (Startseite, #ablauf): dieselben Rollen, die Farben fuer
   dunkles Papier. Gemessen am 21.09.2026: text-faint auf dem Dunkel hatte
   2,84:1, text-soft 2,45:1. Beides unter 4,5. */
.section--dark .zeitstrahl__nr { color: var(--color-on-dark-soft); }
.section--dark .zeitstrahl__station.is-in .zeitstrahl__nr { color: var(--color-accent-soft); }
.section--dark .zeitstrahl__station p { color: var(--color-on-dark-soft); }
.section--dark .zeitstrahl::before { background: var(--color-line-dark); }
.section--dark .zeitstrahl__marke { background: var(--color-dark); border-color: var(--color-line-dark); }
.section--dark .zeitstrahl__station.is-in .zeitstrahl__marke { background: var(--color-accent); border-color: var(--color-accent); }
.section--dark .zeitstrahl__abschluss { border-top-color: var(--color-line-dark); }

/* Vor dem Eintreffen leicht versetzt. Ohne JS und bei reduzierter Bewegung
   steht alles sofort da - deshalb .js als Bedingung. */
.js .zeitstrahl__station {
  opacity: 0;
  transform: translateY(1rem);
  transition: opacity 0.5s var(--ease), transform 0.5s var(--ease);
}
.js .zeitstrahl__station.is-in { opacity: 1; transform: none; }

/* Waagerecht stehen alle vier Stationen gleichzeitig im Bild und kaemen
   deshalb gleichzeitig an. Ein kleiner Versatz laesst sie der Linie folgen,
   statt als Block aufzublitzen. Senkrecht braucht es das nicht, dort
   erreicht sie der Scroll ohnehin nacheinander. */
@media (min-width: 820px) {
  .js .zeitstrahl__station:nth-child(2) { transition-delay: 0.09s; }
  .js .zeitstrahl__station:nth-child(3) { transition-delay: 0.18s; }
  .js .zeitstrahl__station:nth-child(4) { transition-delay: 0.27s; }
}

@media (prefers-reduced-motion: reduce) {
  .js .zeitstrahl__station { opacity: 1; transform: none; transition: none; transition-delay: 0s; }
  .zeitstrahl::after { transform: none; }
  .zeitstrahl__marke, .zeitstrahl__nr { transition: none; }
}

/* Abschluss unter dem Strahl: ein Hauptweg, darunter der Abzweig für alle,
   die hier falsch sind. Der Abzweig ist bewusst schwächer gesetzt. */
.zeitstrahl__abschluss {
  margin-top: var(--space-xl);
  padding-top: var(--space-l);
  border-top: 1px solid var(--color-line);
  display: grid;
  justify-items: start;
  gap: var(--space-l);
}
/* Ab 900px stehen Hauptweg und Abzweig nebeneinander. Untereinander blieb
   die rechte Haelfte leer, und der Abzweig las sich wie ein zweiter
   Hauptweg statt wie eine Abzweigung. */
@media (min-width: 900px) {
  .zeitstrahl__abschluss {
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    column-gap: clamp(2rem, 6vw, 5rem);
  }
}
.zeitstrahl__abzweig {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-s);
  color: var(--color-text-soft);
  padding-left: var(--space-m);
  border-left: 2px solid var(--color-line-strong);
}
.zeitstrahl__abzweig .btn { flex: none; }

/* ---------- Einsatzgebiet ---------- */

/* Kein eingebetteter Kartendienst. Ein Google-Maps-iframe laedt beim
   Seitenaufruf von fremden Servern und braucht eine Einwilligung, also ein
   Consent-Banner auf der ganzen Seite - für eine Stecknadel, die weniger
   zeigt als die drei Ringe hier. Die Abstufung ist die Aussage: je groesser
   das Stueck, desto naeher muss der Kunde sein. */
.gebiet__grid { display: grid; gap: var(--space-l); align-items: center; }
@media (min-width: 900px) {
  .gebiet__grid { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); gap: clamp(2rem, 6vw, 5rem); }
}
.gebiet__karte { margin: 0; }
.gebiet__karte svg { width: 100%; height: auto; display: block; }

.gebiet__ring { fill: none; stroke: var(--color-line-strong); stroke-width: 1; }
.gebiet__ring--1 { fill: var(--color-surface); stroke: var(--color-accent); }
.gebiet__ring--2 { stroke-dasharray: 3 5; }
.gebiet__ring--3 { stroke-dasharray: 2 7; opacity: 0.7; }
.gebiet__punkt { fill: var(--color-accent); }

.gebiet__marke,
.gebiet__label {
  fill: var(--color-text-faint);
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-anchor: middle;
}
.gebiet__marke { fill: var(--color-text); font-weight: 600; letter-spacing: 0.06em; font-size: 12px; }

.gebiet__karte figcaption {
  margin-top: var(--space-s);
  font-size: var(--step--1);
  color: var(--color-text-faint);
  text-align: center;
}

/* Hier stand `.bild--oben` (object-position: center 26%), eine Korrektur für
   die Kachel "Verglasung und Kitt": Bei object-fit: cover schnitt der Browser
   mittig, und vom Rahmen blieben nur die Sägeböcke. Gemeldet am 21.09.2026
   mit Screenshot. Seit dem 12.10.2026 steht dort ein Sprossenfenster, bei dem
   die Mitte das Motiv ist. Die Klasse wird von keiner Seite mehr benutzt und
   ist entfernt. */

/* ---------- Angabenband ---------- */

/* Drei Angaben, die den Betrieb einordnen. Sie standen im Hero neben dem
   Text; seit dort ein Bild steht, haben sie einen eigenen schmalen Streifen
   darunter. Sie sind eine Einordnung, kein Hero-Inhalt, und ringen so nicht
   mit dem Bild um dieselbe Flaeche. */
.section--band { padding-block: var(--space-l); background: var(--color-surface); }
.angabenband {
  margin: 0;
  display: grid;
  gap: var(--space-m) var(--space-l);
}
@media (min-width: 760px) {
  .angabenband { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.angabenband dt {
  font-size: var(--step--1);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-text-faint);
  font-weight: 600;
  margin-bottom: 0.25rem;
}
/* Unter einem Sektionskopf statt als eigenes Band (/leistungen/, Trockenbau,
   26.10.2026): eine Haarlinie trennt die Ueberschrift von den drei
   Angaben, der Link folgt darunter. */
.angabenband--linie { border-top: 1px solid var(--color-line); padding-top: var(--space-m); }
.angabenband__mehr { margin-top: var(--space-l) !important; }
.angabenband dd {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--step-1);
  line-height: 1.25;
}

/* Der Ausweg neben dem Formular: eine Zeile, kein zweiter Knopf. Wer das
   Formular nicht ausfuellen will, entscheidet das vor dem ersten Feld und
   nicht vor dem Absenden - deshalb steht sie oben. Als Knopf waere sie ein
   zweiter Hauptweg, und genau die haben wir am 18.09. unter den Fragen
   abgeschafft. Die Nummer steht zusaetzlich im Kopf, der mitscrollt. */
.anfrage__ausweg {
  margin: calc(var(--space-l) * -1) 0 var(--space-l);
  color: var(--color-text-faint);
  font-size: var(--step--1);
}

/* ---------- Karte auf /kontakt/ ----------
   Google Maps als iframe, geladen erst nach Einwilligung (/js/einwilligung.js).
   Die Karte nimmt zwei Drittel ein, die Adresse das letzte: dasselbe
   Dreierraster wie die Kontaktbloecke darunter, damit die Kanten fluchten. */
.karte { display: grid; gap: var(--space-l); margin-bottom: var(--space-xl); }
@media (min-width: 820px) {
  .karte { grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: center; }
  .karte__rahmen { grid-column: span 2; }
}
.karte__rahmen {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--radius-img);
  border: 1px solid var(--color-line);
  /* Ein angedeutetes Strassenraster, damit die Flaeche vor dem Laden als
     Karte lesbar ist. Reine Dekoration: Es zeigt keine echten Strassen. */
  background:
    repeating-linear-gradient(28deg, transparent 0 46px, color-mix(in oklab, var(--color-line) 70%, transparent) 46px 48px),
    repeating-linear-gradient(-62deg, transparent 0 70px, color-mix(in oklab, var(--color-line) 70%, transparent) 70px 72px),
    var(--color-bg-tint);
}
@media (min-width: 820px) { .karte__rahmen { aspect-ratio: 16 / 9; } }
.karte__rahmen iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.karte__sperre {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--space-xs);
  padding: var(--space-m);
  text-align: center;
}
.karte__sperre[hidden] { display: none; }
.karte__sperre > * {
  max-width: 34rem;
  margin: 0;
}
.karte__sperre p { color: var(--color-text-soft); line-height: 1.6; }
/* Die Textzeilen stehen auf dem Raster: eine ruhige Flaeche dahinter haelt
   den Kontrast, ohne einen Kasten in den Kasten zu setzen. */
.karte__sperre::before {
  content: "";
  position: absolute;
  inset: 12% 8%;
  background: radial-gradient(closest-side, var(--color-bg-tint) 62%, transparent);
  z-index: -1;
}
.karte__sperre { z-index: 0; }
.karte__sperre .karte__sperre-titel {
  font-family: var(--font-display);
  font-size: var(--step-1);
  color: var(--color-text);
}
.karte__sperre-aktionen {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-xs);
  margin-top: var(--space-xs);
}
.karte__adresse { padding-bottom: var(--space-2xs); }
/* Auf dem Telefon passt der Hinweis nicht in ein 4:3-Feld. Solange die
   Sperre steht, waechst das Feld mit ihrem Text; ist die Karte geladen,
   gilt wieder das feste Seitenverhaeltnis. */
@media (max-width: 819px) {
  .karte__rahmen:has(> .karte__sperre:not([hidden])) { aspect-ratio: auto; }
  .karte__sperre { position: relative; inset: auto; padding-block: var(--space-l); }
}

/* ---------- Cookie-Einstellungen ----------
   Der Knopf im Fuss sieht aus wie die Links daneben: Er ist deren
   Geschwister, keine Aufforderung. Ohne JavaScript bleibt er versteckt,
   weil er ohne Skript nichts tun kann. */
.site-footer__einstellungen {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.site-footer__einstellungen:hover,
.site-footer__einstellungen:focus-visible { color: var(--color-on-dark); }
@media (max-width: 820px) { .site-footer__einstellungen { padding-block: 0.85rem; } }

.einwilligung {
  /* Das Reset am Dateianfang nimmt allen Elementen den Rand, auch dem
     Dialog; ohne margin: auto klebt er oben links statt in der Mitte. */
  margin: auto;
  width: min(34rem, calc(100vw - 2 * var(--space-m)));
  padding: var(--space-l);
  border: 0;
  border-radius: var(--radius);
  background: var(--color-surface);
  color: var(--color-text);
}
.einwilligung::backdrop { background: color-mix(in oklab, var(--color-dark) 55%, transparent); }
.einwilligung h2 { font-size: var(--step-2); margin-bottom: var(--space-s); }
.einwilligung p { color: var(--color-text-soft); line-height: 1.6; }
.einwilligung { max-height: calc(100dvh - 2 * var(--space-s)); overflow-y: auto; }
.einwilligung__kategorie {
  margin-block: var(--space-s);
  padding: var(--space-s);
  border: 1px solid var(--color-line);
  border-radius: var(--radius);
}
.einwilligung__kopf {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-s);
  align-items: start;
  color: var(--color-text-soft);
  line-height: 1.6;
  cursor: pointer;
}
.einwilligung__kopf:has(input:disabled) { cursor: default; }
.einwilligung__kopf input { width: 1.25rem; height: 1.25rem; margin-top: 0.2rem; accent-color: var(--color-accent-ink); }
.einwilligung__kopf strong { display: block; color: var(--color-text); }
.einwilligung__details { margin-top: var(--space-xs); padding-left: calc(1.25rem + var(--space-s)); font-size: var(--step--1); }
.einwilligung__details summary {
  display: inline-flex; align-items: center; min-height: 2.75rem;
  color: var(--color-accent-ink); font-weight: 600; cursor: pointer;
}
.einwilligung__details summary:hover { text-decoration: underline; }
.einwilligung__details dl { display: grid; grid-template-columns: max-content 1fr; gap: 0.35rem var(--space-s); color: var(--color-text-soft); line-height: 1.55; }
.einwilligung__details dt { color: var(--color-text); font-weight: 600; }
@media (max-width: 520px) {
  .einwilligung { padding: var(--space-m) var(--space-s); width: calc(100vw - 2 * var(--space-xs)); }
  .einwilligung__details { padding-left: 0; }
  .einwilligung__details dl { grid-template-columns: 1fr; }
  .einwilligung__details dd { margin-bottom: 0.4rem; }
}
/* Alle Wahl-Knöpfe gleich groß und gleich auffällig (CONSENT-BANNER A3):
   „Nur notwendige“ ist kein schwächerer Knopf als „Alle akzeptieren“. */
.einwilligung__wahl { background: var(--color-dark); color: var(--color-on-dark); flex: 1 1 11rem; }
.einwilligung__wahl:hover { background: var(--color-text); }

/* Banner, erste Ebene. Unten statt Vollbild: Die Seite, Impressum und
   Datenschutz bleiben lesbar und erreichbar (A10). */
.einwilligung-banner {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 90;
  padding: var(--space-s);
  pointer-events: none;
}
.einwilligung-banner__innen {
  pointer-events: auto;
  max-width: 60rem;
  margin-inline: auto;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-s) var(--space-m);
  align-items: end;
  padding: var(--space-m);
  background: var(--color-surface);
  color: var(--color-text);
  border: 1px solid var(--color-line-strong);
  border-radius: var(--radius);
  box-shadow: 0 18px 48px -20px oklch(0.2 0.02 55 / 0.45);
}
.einwilligung-banner h2 { font-size: var(--step-1); margin-bottom: var(--space-2xs); }
.einwilligung-banner p { color: var(--color-text-soft); line-height: 1.6; max-width: 62ch; }
.einwilligung-banner__links { display: flex; gap: var(--space-m); margin-top: -0.35rem; margin-bottom: -0.5rem; font-size: var(--step--1); }
/* Unterstrichen per text-decoration statt .link-underline: Die Trefferfläche
   wächst über padding, der Strich bleibt direkt unter dem Wort. */
.einwilligung-banner__links a {
  display: inline-block; padding-block: 0.7rem;
  color: var(--color-text-soft); text-decoration: underline; text-underline-offset: 0.2em;
  text-decoration-color: var(--color-line-strong);
}
.einwilligung-banner__links a:hover { color: var(--color-accent-ink); text-decoration-color: currentColor; }
.einwilligung-banner__aktionen { display: grid; gap: var(--space-xs); min-width: 15rem; }
.einwilligung-banner__aktionen .einwilligung__wahl { width: 100%; }
.einwilligung-banner__anpassen {
  min-height: 2.75rem;
  background: none; border: 0; padding: 0;
  font: inherit; font-weight: 600; color: var(--color-accent-ink);
  cursor: pointer; text-decoration: underline; text-underline-offset: 0.2em;
}
.einwilligung-banner__anpassen:hover { color: var(--color-text); }
@media (max-width: 760px) {
  .einwilligung-banner { padding: var(--space-xs); }
  .einwilligung-banner__innen { grid-template-columns: 1fr; padding: var(--space-s); gap: var(--space-xs); }
  .einwilligung-banner p { font-size: var(--step--1); }
  .einwilligung-banner__aktionen { grid-template-columns: 1fr 1fr; min-width: 0; }
  .einwilligung-banner__aktionen .einwilligung__wahl { padding-inline: 0.5rem; font-size: var(--step--1); }
  .einwilligung-banner__anpassen { grid-column: 1 / -1; }
}
@media (prefers-reduced-motion: no-preference) {
  .einwilligung-banner__innen { animation: einwilligung-rein 0.35s var(--ease) both; }
  @keyframes einwilligung-rein { from { opacity: 0; transform: translateY(0.75rem); } }
}
.einwilligung__aktionen { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--space-xs); margin-top: var(--space-m); }

/* ---------- Formularversand ----------
   Die Falle für Bots liegt außerhalb des sichtbaren Bereichs statt auf
   display:none: Manche Bots überspringen versteckte Felder gezielt. */
.form-falle { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.form-hinweis { margin-top: var(--space-m); font-size: var(--step--1); color: var(--color-text-soft); line-height: 1.6; }
.form-meldung {
  margin-top: var(--space-m);
  padding: var(--space-s) var(--space-m);
  border-left: 3px solid var(--color-accent-ink);
  background: var(--color-surface);
  color: var(--color-text);
  line-height: 1.5;
}
.form-meldung:focus { outline: none; }

/* ─────────── /danke/ ─────────── */

/* Umgekehrt zu /ueber-uns/: Dort stellt sich eine Person vor, das Bild fuehrt.
   Hier hat jemand gerade etwas abgeschickt und will zuerst lesen, dass es
   angekommen ist. Der Text steht deshalb im Markup voran - am breiten Schirm
   steht das Portrait trotzdem rechts daneben, nicht darunter. */
@media (min-width: 900px) {
  .person__grid--umgekehrt { grid-template-columns: minmax(0, 1fr) minmax(0, 0.72fr); }
}

/* person__body setzt Abstand nur zwischen zwei Absaetzen (p + p), nicht nach
   der Ueberschrift - auf /ueber-uns/ steht dafuer ein style-Attribut im
   Markup. Hier nicht, das gehoert ins Stylesheet. */
.person__grid--umgekehrt h1 + .lead { margin-top: var(--space-s); }

.danke__eilig {
  margin-top: var(--space-m);
  padding-top: var(--space-s);
  border-top: 1px solid var(--color-line);
  color: var(--color-text-soft);
  font-size: var(--step--1);
}

/* Der Nachtrag traegt zwei Dinge nebeneinander: den Weg fuer ein vergessenes
   Foto und den Ausgang zurueck in die Seite. Untereinander gestapelt sah der
   zweite wie ein Nachklapp aus. */
.danke__nachtrag { display: grid; gap: var(--space-l); align-items: end; }
@media (min-width: 900px) {
  .danke__nachtrag { grid-template-columns: minmax(0, 1fr) minmax(0, 0.42fr); }
}
.danke__ausgang {
  padding-top: var(--space-s);
  border-top: 1px solid rgb(255 255 255 / 0.18);
}
.danke__ausgang p {
  margin: 0 0 0.3rem;
  font-size: var(--step--1);
  /* text-faint auf dem Dunkel ergab 2.84:1. Derselbe Fehler stand schon
     einmal beim Zeitstrahl an, siehe Kommentar dort. */
  color: var(--color-on-dark-soft);
}

/* Der Link ist der einzige Ausgang aus dieser Seite und stand als blosse
   Textzeile da: 22px hoch, also die Haelfte des Touch-Ziels. */
.danke__ausgang a {
  display: inline-block;
  padding-block: 0.6rem;
}
