/* ==========================================================================
   Ackermann Architekten — Stylesheet
   Design: skandinavischer Minimalismus, Objektiv Mk1 (Adobe Typekit, wie alte Website),
   Albert Sans (selbst gehostet) als Fallback
   ========================================================================== */

@font-face {
  font-family: 'Albert Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/albert-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Albert Sans';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../fonts/albert-latinext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --bg: #FDFDFB;
  --ink: #111110;
  --muted: #6E6E68;
  --hair: #E4E4DE;
  --panel: #111110;
  --panel-ink: #F4F4EF;
  --panel-muted: #9A9A92;
  --panel-hair: #2C2C29;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: 'objektiv-mk1', 'Albert Sans', 'Segoe UI', system-ui, sans-serif;
  font-size: 19px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
/* Scroll-Lock (Menü offen, Logo-Intro läuft) — NUR auf html, nie auf body:
   body{overflow:hidden} macht body selbst zum Scroll-Container (Scrollstand 0),
   wodurch alle position:sticky-Bühnen an ihre Ausgangsposition zurückspringen
   (weißer Bildschirm bei geöffnetem Menü auf Zoom-Bühne / Leistungen / Team). */
html:has(body.locked) { overflow: hidden; }
html, body { overflow-x: clip; }

img { max-width: 100%; display: block; }

/* ---------- Typo-Skala ---------- */
.display-xl { font-size: clamp(2.8rem, 9.5vw, 8rem); font-weight: 500; letter-spacing: -0.05em; line-height: 0.98; margin: 0; text-wrap: balance; }
.display-l { font-size: clamp(2.2rem, 6vw, 4.8rem); font-weight: 500; letter-spacing: -0.045em; line-height: 1.05; margin: 0; text-wrap: balance; }
.display-m { font-size: clamp(1.6rem, 3.2vw, 2.5rem); font-weight: 450; letter-spacing: -0.03em; line-height: 1.25; margin: 0; text-wrap: balance; }
.label { font-size: 0.72rem; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }

/* ---------- Raster ---------- */
.wrap { padding-inline: clamp(1.2rem, 4vw, 4rem); }
/* Textspalten auf allen Seiten mittig zum Bildschirm */
.col { max-width: 660px; margin-inline: auto; }
/* Startseite: Titelbild bleibt beim Scrollen stehen, der Inhalt schiebt sich darüber (Curtain-Effekt).
   --hd (0–1, per JS): langsame Aufwärts-Drift; der nachrückende Inhalt deckt schneller ab,
   als das Bild driftet (16 % je Viewport), daher kein Scale-Überstand nötig. */
.home .hero { position: sticky; top: 0; z-index: 0; }
.home .hero .art img { transform: scale(1) translateY(calc(var(--hd, 0) * -16%)); }
/* Desktop-Hero (3:2-Foto): volle Breite, nur oben beschneiden – Unterkante bleibt komplett sichtbar */
@media (min-width: 769px) { .home .hero .art img { object-position: center bottom; } }
.home main > *:not(.hero) { position: relative; z-index: 1; background: var(--bg); }
/* Nahtstellen (alle Seiten mit stehendem Titelbild): Die Abschnitte liegen einzeln über
   dem Titelbild. Wo zwei aneinanderstoßen, bleibt je nach Bildschirmdichte ein Spalt von
   einem Bruchteil eines Pixels — dort schien das Titelbild als Haarlinie durch (am Handy
   und auf den dunklen Seiten sehr deutlich, meist an Ober-/Unterkante der Bildbänder).
   Eine durchgehende Fläche in Seitenfarbe deckt das Titelbild hinter allen Abschnitten
   lückenlos ab: Sie beginnt an seiner Unterkante, liegt über ihm (gleicher z-index,
   später im Baum) und unter den Abschnitten (z-index 1). */
.home main, .page-team main, .page-leistungen main, .page-kontakt main, .page-projekte main { position: relative; }
.home main::after, .page-team main::after, .page-leistungen main::after,
.page-kontakt main::after, .page-projekte main::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; z-index: 0;
  top: max(100svh, 560px); /* = Höhe von .hero / .t-hero */
  background: var(--bg); pointer-events: none;
}
.page-team main::after, .page-leistungen main::after, .page-kontakt main::after { background: #0D0D0C; }
/* Ist das Titelbild vollständig überdeckt, wird es gar nicht mehr gezeichnet
   (Klasse aus main.js) — spart am Handy eine bildschirmgroße Ebene */
.hero.is-covered, .t-hero.is-covered { visibility: hidden; }
section { padding-block: clamp(5rem, 11vw, 10.5rem); }
section.tight { padding-block: clamp(3rem, 6vw, 5.5rem); }

p { margin: 0 0 1.4em; }
p:last-child { margin-bottom: 0; }
.muted { color: var(--muted); }
a { color: inherit; }
strong { font-weight: 600; }

/* ---------- Masken-Reveal (Text) ---------- */
/* clip statt hidden: hidden-Boxen sind programmatisch scrollbar — der Fokus auf
   einen Menülink (Öffnen/Tab) scrollt sonst die Maske und legt die versteckte
   Roll-Kopie frei bzw. schneidet die sichtbare Zeile oben an */
.mask { overflow: hidden; overflow: clip; display: block; }
/* padding-block: Luft für Ober-/Unterlängen, sonst schneidet der Masken-Beschnitt die Schrift an */
.mask > .mi { display: block; padding-block: 0.08em; transform: translateY(112%); transition: transform 1.15s var(--ease); }
.mask.in > .mi { transform: none; }
/* Das .mi-Polster rechnet in der KLEINEN Basis-Schriftgröße (~1,5px) — bei den großen
   Display-Titeln (line-height 0.98) ragen Umlaut-Punkte und Unterlängen weiter hinaus.
   Deshalb Polster direkt auf der Überschrift: es skaliert mit deren em. Keine negativen
   Margins zum Ausgleich — die würden die Maske wieder schrumpfen und erneut beschneiden. */
.mask .display-xl, .mask .display-l { padding-block: 0.09em 0.06em; }

/* ---------- Fade-Reveal ---------- */
.reveal { opacity: 0; transform: translateY(36px); transition: opacity 0.9s var(--ease), transform 1.1s var(--ease); transition-delay: var(--d, 0s); }
.reveal.in { opacity: 1; transform: none; }

/* ---------- Bild-Reveal ---------- */
.img-reveal { clip-path: inset(0 0 100% 0); transition: clip-path 1.3s var(--ease); }
.img-reveal .zoom { transform: scale(1.12); transition: transform 1.9s var(--ease); }
.img-reveal.in { clip-path: inset(0); }
.img-reveal.in .zoom { transform: none; }

/* ---------- Custom Cursor (Punkt gleitet dem Zeiger hinterher, Position/Farbe per JS) ----------
   Wichtig: Position (transform) und Wachsen (scale) liegen auf getrennten Elementen —
   die scale-Eigenschaft greift VOR transform und würde sonst die Positionsverschiebung
   mitskalieren (Punkt springt beim Link-Hover an die doppelte Koordinate). */
.cursor-dot {
  position: fixed; left: 0; top: 0; z-index: 999; /* über dem Menü-Overlay (z-index 20) */
  pointer-events: none;
  opacity: 0; transition: opacity 0.3s ease;
}
.cursor-dot.visible { opacity: 1; }
.cursor-dot.off { opacity: 0; } /* z. B. über dem Logo: Punkt ausblenden */
.cursor-dot i {
  display: block; width: 20px; height: 20px; margin: -10px 0 0 -10px;
  border-radius: 50%;
  background: var(--ink); /* schwarz auf hellem Grund; .on-dark schaltet auf weiß */
  transition: scale 0.4s var(--ease), background 0.25s ease;
}
.cursor-dot.on-dark i { background: #fff; }
.cursor-dot.on-link i { scale: 2; }
/* Über den Projektkarten wird der Punkt zum Schriftzug „Projekt öffnen"
   (weiße Standardschrift ohne Hintergrund), eingefasst von vier
   Sucher-Winkeln in den Ecken wie bei einem Kamera-Rahmen */
.cursor-dot .cursor-label {
  position: absolute; left: 0; top: 0;
  transform: translate(-50%, -50%);
  display: block; white-space: nowrap;
  /* Farbe folgt der Hell/Dunkel-Erkennung des Punkts: schwarz auf hellem Grund
     (z. B. Kontakt-Karte), weiß auf Fotos (.on-dark); Winkel via currentColor */
  color: var(--ink); font-size: 1.35rem; letter-spacing: 0.01em;
  padding: 0.75em 1.05em;
  --l: 16px; --t: 2px; /* Winkel: Schenkellänge / Strichstärke */
  background-image:
    linear-gradient(currentColor, currentColor), linear-gradient(currentColor, currentColor),
    linear-gradient(currentColor, currentColor), linear-gradient(currentColor, currentColor),
    linear-gradient(currentColor, currentColor), linear-gradient(currentColor, currentColor),
    linear-gradient(currentColor, currentColor), linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-size:
    var(--l) var(--t), var(--t) var(--l),
    var(--l) var(--t), var(--t) var(--l),
    var(--l) var(--t), var(--t) var(--l),
    var(--l) var(--t), var(--t) var(--l);
  background-position:
    left top,      left top,
    right top,     right top,
    left bottom,   left bottom,
    right bottom,  right bottom;
  opacity: 0; scale: 0.6;
  transition: opacity 0.25s ease, scale 0.4s var(--ease);
}
.cursor-dot.on-dark .cursor-label { color: #fff; text-shadow: 0 1px 18px rgba(0, 0, 0, 0.4); }
.cursor-dot.on-project i { scale: 0; }
.cursor-dot.on-project .cursor-label { opacity: 1; scale: 1; }
/* Solange das Logo-Intro bzw. der Seitenwechsel-Vorhang die Seite noch verdeckt,
   bleibt das Etikett verborgen (der Zeiger steht dabei oft schon über dem
   Titelbild) — es blendet erst ein, wenn die Seite frei steht */
body:has(.intro:not(.s-done)) .cursor-dot.on-project .cursor-label,
html.pt-enter .cursor-dot.on-project .cursor-label { opacity: 0; scale: 0.6; }
@media (pointer: coarse) { .cursor-dot { display: none; } }

/* ---------- Partner-Raster ---------- */
.partners {
  display: grid; grid-template-columns: repeat(4, 1fr);
}
/* Intro-Text belegt 2×2 Zellen (= 4 Kacheln) rechts oben, die Logos füllen links auf */
.partners-intro {
  grid-column: 3 / span 2; grid-row: 1 / span 2;
  display: flex; flex-direction: column; justify-content: center;
  padding: clamp(1.2rem, 3vw, 2.4rem) 0 clamp(1.2rem, 3vw, 2.4rem) clamp(3rem, 10vw, 12rem);
}
.partner {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 8 / 5; padding: clamp(1.2rem, 3vw, 2.4rem);
  text-decoration: none;
}
.partner img {
  max-width: 100%; max-height: clamp(52px, 7vw, 78px); width: auto; height: auto;
  /* brightness+contrast drücken Grautöne nach Schwarz, Weiß bleibt Weiß;
     multiply blendet weiße Logo-Hintergründe (JPG/PNG ohne Alpha) in den Seitenhintergrund */
  filter: grayscale(1) brightness(0.7) contrast(8);
  mix-blend-mode: multiply;
  transition: filter 0.4s ease;
}
/* Diese Logos sind im Original hellgrau — brauchen eine stärkere Schwarz-Kurve */
.partner img[src*="paulus"], .partner img[src*="hl-kreuz"] {
  filter: grayscale(1) brightness(0.62) contrast(10);
}
/* Edhofer: schwarzer Schriftzug liegt auf rotem Pinselstrich — die harte Schwarz-Kurve
   würde beides verschmelzen; nur entsättigen, dann bleibt der Strich grau lesbar */
.partner img[src*="edhofer"] { filter: grayscale(1) brightness(1.3); }
.partner:hover img, .partner:focus-visible img { filter: none; }
.partner-text span {
  color: var(--ink); text-align: center; text-transform: uppercase;
  font-size: 0.82rem; font-weight: 700; letter-spacing: 0.14em; line-height: 1.5;
  transition: opacity 0.4s ease;
}
.partner-text span small {
  display: block; font-size: 0.6rem; font-weight: 400; letter-spacing: 0.2em; margin-top: 0.3em;
}
/* Original-Bildmarke ohne eigenen Schriftzug (Zahnärzte, Physio): Zeichen über dem Namen */
.partner-mark { flex-direction: column; gap: 0.8rem; }
.partner-mark img { max-height: clamp(26px, 3.4vw, 44px); }
@media (max-width: 560px) {
  .partner-mark { gap: 0.5rem; }
  .partner-mark span { font-size: 0.68rem; }
  .partner-mark span small { display: none; }
}
@media (max-width: 900px) {
  .partners { grid-template-columns: repeat(3, 1fr); }
  /* 3-spaltiges Raster: Intro auf den rechten zwei Spalten */
  .partners-intro { grid-column: 2 / span 2; }
}
@media (max-width: 560px) {
  .partners { grid-template-columns: repeat(2, 1fr); }
  /* Mobil: Intro als volle Breite über den Logos, keine 2×2-Zelle */
  .partners-intro { grid-column: 1 / -1; grid-row: auto; padding: 0 0 clamp(1.2rem, 3vw, 2.4rem); }
}

/* ---------- Projektablauf (Akkordeon) ---------- */
.process { margin-top: clamp(2.5rem, 6vw, 4.5rem); border-top: 1px solid var(--hair); }
.process details { border-bottom: 1px solid var(--hair); interpolate-size: allow-keywords; }
.process summary {
  display: grid; grid-template-columns: clamp(3rem, 8vw, 5.5rem) 1fr auto;
  align-items: center; gap: clamp(0.9rem, 2.5vw, 1.8rem);
  padding: clamp(1.5rem, 4vw, 2.6rem) 0;
  cursor: pointer; list-style: none;
}
.process summary::-webkit-details-marker { display: none; }
.process .p-no { font-size: 0.85rem; color: var(--muted); letter-spacing: 0.1em; }
.process .p-title {
  margin: 0; font-size: clamp(1.35rem, 3.6vw, 2.5rem);
  font-weight: 500; letter-spacing: -0.025em; line-height: 1.12;
  min-width: 0; hyphens: manual;
  transition: opacity 0.3s ease;
}
.process summary:hover .p-title { opacity: 0.6; }
.process .p-icon { position: relative; width: 1rem; height: 1rem; margin-inline: 0.2rem; }
.process .p-icon::before, .process .p-icon::after {
  content: ""; position: absolute; top: 50%; left: 0;
  width: 100%; height: 1.5px; background: var(--ink);
  transform: translateY(-50%); transition: transform 0.4s var(--ease);
}
.process .p-icon::after { transform: translateY(-50%) rotate(90deg); }
.process details[open] .p-icon::after { transform: translateY(-50%) rotate(0deg); }
.process ::details-content {
  block-size: 0; overflow: hidden;
  transition: block-size 0.5s var(--ease), content-visibility 0.5s allow-discrete;
}
.process details[open]::details-content { block-size: auto; }
.process .p-body {
  padding: 0 0 clamp(1.8rem, 4vw, 2.6rem);
  margin-left: calc(clamp(3rem, 8vw, 5.5rem) + clamp(0.9rem, 2.5vw, 1.8rem));
  max-width: 38rem;
}
.process .p-body p { margin: 0.9rem 0 0; color: var(--muted); line-height: 1.65; }
@media (max-width: 640px) {
  .process .p-body { margin-left: 0; }
}

/* ---------- Roll-Link (Hover) ---------- */
.roll { display: inline-block; overflow: hidden; vertical-align: top; }
.roll > span { display: block; position: relative; transition: transform 0.6s var(--ease); }
.roll > span::after { content: attr(data-t); position: absolute; top: 100%; left: 0; }
a:hover .roll > span, a:focus-visible .roll > span,
button:hover .roll > span, button:focus-visible .roll > span { transform: translateY(-100%); }

/* ---------- Staggered Letter Roll-up (Menü-, Footer- + Big-Links, Split per JS) ----------
   .lroll ist die Bühne im Link, .rl die sichtbare Zeile, .rl2 die Kopie darunter.
   Beim Hover über den Link rollt jeder Buchstabe versetzt nach oben, die Kopie
   rückt nach. padding-block wie bei .mask: Luft für Unterlängen (g, j, p) */
.lroll { position: relative; display: inline-block; overflow: hidden; overflow: clip; vertical-align: top; }
.lroll .rl { display: block; padding-block: 0.08em; }
.lroll .rl2 { position: absolute; inset: 0; }
/* Transition nur im Hover-Zustand: beim Verlassen springt der Text sofort
   zurück, statt nochmal rückwärts zu rollen */
.lroll .rc { display: inline-block; transition: none; }
a:hover .lroll .rc,
a:focus-visible .lroll .rc {
  transition: transform 0.6s var(--ease);
  transition-delay: calc(var(--i) * 0.022s);
}
/* 130% statt 105%: Oberlängen/i-Punkte der versteckten Kopie ragen über die
   Zeilenbox hinaus und würden sonst unten aus der Maske lugen (ab ~117% sicher) */
.lroll .rl2 .rc { transform: translateY(130%); }
a:hover .lroll .rl:not(.rl2) .rc,
a:focus-visible .lroll .rl:not(.rl2) .rc { transform: translateY(-130%); }
a:hover .lroll .rl2 .rc,
a:focus-visible .lroll .rl2 .rc { transform: none; }

/* ---------- Header ---------- */
header.site {
  position: fixed; inset: 0 0 auto 0; z-index: 10;
  display: flex; justify-content: space-between; align-items: center;
  padding: 1.3rem clamp(1.2rem, 4vw, 4rem);
  color: var(--ink);
  opacity: 0; transition: opacity 1s ease 0.7s, color 0.35s ease;
}
/* Auf Bildern und dunklem Grund: Logo/Menü weiß; auf weißem Grund: schwarz */
header.site .brand img { filter: invert(1); transition: filter 0.35s ease; }
header.site.on-media { color: #fff; }
header.site.on-media .brand img { filter: none; }
html.loaded header.site { opacity: 1; }
/* Schmale Bildschirme: Kopf fährt beim Abwärtsscrollen aus dem Bild (hdr-hide) und
   kommt beim Aufwärtsscrollen mit mattem Grund zurück (hdr-solid) — sonst liegt der
   Logo-Schriftzug quer über dem Fließtext. Klassen setzt main.js. Der Grund folgt
   der Schriftfarbe: hell unter schwarzem Logo, dunkel unter weißem. Ausgenommen sind
   die Stellen, an denen das Logo bewusst fehlt (Titelbild und Video der Startseite):
   dort schwebt nur das Menü-Icon, ein Balken wäre dort leer */
@media (max-width: 860px) {
  header.site {
    transition: opacity 1s ease 0.7s, color 0.35s ease, transform 0.45s var(--ease), background-color 0.3s ease;
  }
  header.site.hdr-hide { transform: translateY(-105%); }
  /* bewusst ohne Weichzeichner (backdrop-filter): der müsste beim Scrollen in jedem
     Frame neu gerechnet werden — auf Handys spürbar. Fast deckende Fläche genügt */
  header.site.hdr-solid { background: rgba(253,253,251,0.97); }
  header.site.hdr-solid.on-media,
  .page-dark header.site.hdr-solid { background: rgba(12,12,11,0.97); }
  .page-kontakt header.site.hdr-solid.on-light-hero { background: rgba(253,253,251,0.97); }
  header.site.hdr-solid.hide-brand,
  body.zs-cover header.site.hdr-solid { background: none; }
}
.brand {
  text-decoration: none;
  font-size: 1.02rem; font-weight: 600; letter-spacing: -0.01em;
  color: inherit; white-space: nowrap;
  transition: opacity 0.3s ease;
}
/* Zoom-Sektion (Leistungen): Header-Logo ab dem Video bis zum Seitenende
   ausblenden (inkl. Footer) — sonst überlagert es das große Zeichen */
body.zs-cover header.site .brand { opacity: 0; pointer-events: none; }
/* Startseite: solange die Hero oben steht, trägt sie selbst das Logo-Lockup —
   das Header-Icon wird ausgeblendet und erst ab der nächsten Section wieder gezeigt */
header.site.hide-brand .brand { opacity: 0; pointer-events: none; }
.brand .sep { font-weight: 300; opacity: 0.55; margin-inline: 0.12em; }
.brand .thin { font-weight: 400; opacity: 0.85; }
.brand img { height: clamp(28px, 3.5vw, 36px); width: auto; display: block; }
/* Logo als Intro-Lockup im Kleinformat: Icon-SVG + „ackermann"-Schriftzug in
   Maske + ARCHITEKTEN-Text — exakt die Struktur des Logo-Intros, damit der
   Hover dieselbe Choreografie spielen kann (Icon-Kontur, Schriftzug-Rise,
   ARCHITEKTEN-Spationierung; Ablauf in main.js). Proportionen wie im Intro,
   skaliert auf die Logohöhe --bh. Farben: Icon + ARCHITEKTEN über currentColor
   (Header schaltet on-media auf Weiß), der Schriftzug über die bestehenden
   invert-Regeln für .brand img. */
/* Beide Textzeilen sind pixelgenau aus der Original-Logodatei geschnitten
   (ackermann: x108–422/y4–36, ARCHITEKTEN: x108–316/y52–72 im 433×73-Lockup);
   alle Maße unten sind diese Messwerte ÷ 73 (Logohöhe). */
.brand { --bh: clamp(28px, 3.5vw, 36px); display: flex; align-items: center; gap: calc(var(--bh) * 0.4795); }
.brand .b-icon { width: var(--bh); height: var(--bh); display: block; flex: none; }
.brand .b-icon rect { fill: currentColor; transform-box: fill-box; transition: fill 0.35s ease; }
/* Wachstumsrichtungen der Kontur-Aufdeckung — identisch zum Intro:
   rechte Wand von unten ↑, Balken von rechts ←, linke Wand von oben ↓,
   Sockel von links →. Ohne diese Origins wachsen die Segmente aus der Mitte. */
.brand .b-icon .r-right { transform-origin: 50% 100%; }
.brand .b-icon .r-beam  { transform-origin: 100% 50%; }
.brand .b-icon .r-left  { transform-origin: 50% 0; }
.brand .b-icon .r-base  { transform-origin: 0 50%; }
.brand .b-words { position: relative; width: calc(var(--bh) * 4.3151); height: var(--bh); flex: none; }
.brand .b-mask {
  position: absolute; left: 0; top: calc(var(--bh) * 0.0548);
  width: 100%; height: calc(var(--bh) * 0.4521); overflow: hidden;
}
.brand .b-ack { display: block; width: 100%; height: 100%; }
.brand .b-arch {
  position: absolute; left: 0; top: calc(var(--bh) * 0.7123);
  width: calc(var(--bh) * 2.863); height: auto; display: block;
  transform-origin: 0 50%;
}
.menu-btn {
  appearance: none; background: none; border: 0; cursor: pointer;
  color: inherit; padding: 0.6rem; margin: -0.6rem;
}
.menu-btn .burger {
  display: block; position: relative;
  width: 26px; height: 2px; background: currentColor;
  transition: background 0.35s ease;
}
.menu-btn .burger::before, .menu-btn .burger::after {
  content: ""; position: absolute; left: 0;
  width: 100%; height: 2px; background: currentColor;
  transition: background 0.35s ease;
}
.menu-btn .burger::before { top: -8px; }
.menu-btn .burger::after { top: 8px; }

/* ---------- Menü-Panel (rechts) ---------- */
.scrim {
  position: fixed; inset: 0; z-index: 19;
  background: rgba(10, 10, 9, 0.45);
  opacity: 0; visibility: hidden;
  transition: opacity 0.9s ease, visibility 0s linear 0.9s;
}
.scrim.open { opacity: 1; visibility: visible; transition: opacity 0.9s ease; }
.overlay {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 20;
  width: min(540px, 92vw);
  background: var(--panel); color: var(--panel-ink);
  padding: clamp(1.2rem, 3vw, 2.6rem);
  display: flex; flex-direction: column; justify-content: space-between;
  /* Vorhang-Reveal: Das Panel (samt Schrift) steht fest an der Endposition,
     nur der Clip-Ausschnitt fährt auf und legt den Inhalt frei */
  visibility: hidden;
  clip-path: inset(0 0 0 100%);
  transition: clip-path 1.1s var(--ease), visibility 0s linear 1.1s;
}
.overlay.open { clip-path: inset(0 0 0 0); visibility: visible; transition: clip-path 1.1s var(--ease); }
@media (max-width: 640px) {
  .overlay { left: 0; width: 100%; }
}
/* Menü invers zum Seitenhintergrund: Standard ist das dunkle Panel (helle Seiten);
   auf dunklen Hintergründen dreht main.js beim Öffnen auf die helle Variante
   (Literalwerte, damit page-dark-Overrides der Basisvariablen nicht durchschlagen) */
.overlay.light { --panel: #FDFDFB; --panel-ink: #111110; --panel-muted: #6E6E68; --panel-hair: #E4E4DE; }
.overlay .top { display: flex; justify-content: flex-end; }
.close-btn {
  appearance: none; background: none; border: 0; cursor: pointer;
  color: var(--panel-ink); padding: 0.6rem; margin: -0.6rem;
  /* Beim Schließen sofort ausblenden statt vom Vorhang zugedeckt zu werden */
  opacity: 0; transition: opacity 0.15s ease;
}
.overlay.open .close-btn { opacity: 1; transition: opacity 0.4s ease 0.5s; }
.close-btn .x-icon { display: block; position: relative; width: 26px; height: 26px; }
.close-btn .x-icon::before, .close-btn .x-icon::after {
  content: ""; position: absolute; top: 50%; left: 0;
  width: 100%; height: 2px; background: currentColor;
}
.close-btn .x-icon::before { transform: rotate(45deg); }
.close-btn .x-icon::after { transform: rotate(-45deg); }
.close-btn:hover .x-icon, .close-btn:focus-visible .x-icon { opacity: 0.7; }
.overlay nav { display: grid; gap: 0.25em; margin-top: auto; padding-bottom: clamp(0.3rem, 1.5vh, 1.2rem); }
.overlay nav a {
  text-decoration: none;
  font-size: clamp(3rem, 12vw, 4.4rem);
  font-weight: 500; letter-spacing: -0.035em; line-height: 1.16;
  width: fit-content;
}
/* Kein Masken-Reveal im Menü: Die Links stehen fest im Panel und fahren
   einfach mit (wie beim Nord-Å-Vorbild) */
.overlay nav .mask > .mi { transform: none; transition: none; }

/* ---------- Hero (Startseite) ---------- */
.hero { position: relative; height: 100svh; min-height: 560px; padding: 0; overflow: hidden; }
.hero .art { position: absolute; inset: 0; transform: scale(1.07); transition: transform 2.4s var(--ease); }
html.loaded .hero .art { transform: scale(1); }
/* Bilder liegen gestapelt übereinander; sichtbar ist das mit .on. Beim Wechsel
   (main.js) blendet das neue Bild über dem alten ein — das alte bleibt als .prev
   voll deckend darunter stehen, sonst schiene mitten in der Überblendung der
   Hintergrund durch */
.hero .art img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover; object-position: center top;
  opacity: 0; transition: opacity 1.8s ease;
}
.hero .art img.prev { opacity: 1; }
.hero .art img.on { opacity: 1; z-index: 1; }
.hero .art::after {
  content: ""; position: absolute; inset: 0; z-index: 2;
  background: linear-gradient(0deg, rgba(12,12,11,0.52), rgba(12,12,11,0) 42%),
              linear-gradient(180deg, rgba(12,12,11,0.28), rgba(12,12,11,0) 30%);
}
/* Klickfläche über dem ganzen Titelbild (→ Projektübersicht); das Logo-Lockup
   liegt darüber und behält seinen eigenen Hover */
.hero .hero-link { position: absolute; inset: 0; z-index: 1; }
/* Kategorie-Pille zum jeweiligen Titelbild (Öffentlich / Privat / NGO): unten rechts
   auf Höhe der Lockup-Unterkante, rechte Kante in der Flucht des Menü-Icons. Wechselt
   im Takt der Bilder (main.js) — die alte blendet erst aus, dann die neue ein, damit
   sich die Texte nicht überlagern */
.hero .hero-pill {
  position: absolute; right: clamp(1.2rem, 4vw, 4rem); bottom: clamp(0.6rem, 1.8vw, 1.6rem);
  /* Innenabstand bewusst ungleich: Versalien sitzen in der Zeile zu hoch (unten bleibt Platz
     für Unterlängen, die es hier nicht gibt), und die Laufweite hängt hinter dem letzten
     Buchstaben an. Gemessen und ausgeglichen, damit die Schrift optisch mittig steht */
  padding: 0.66em 1.07em 0.34em 1.13em; border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.75);
  background: rgba(12,12,11,0.22);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  color: #fff; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; line-height: 1.4;
  opacity: 0; transition: opacity 0.5s ease;
}
.hero .hero-pill.on { opacity: 1; transition-delay: 0.7s; }
/* Handy: Pille oben links, auf Höhe des Menü-Icons und mit demselben Seitenrand — der Platz
   ist frei, weil das Kopf-Logo über dem Titelbild ausgeblendet ist. Unten reicht das Lockup
   fast über die ganze Breite, dort wirkte sie eingezwängt */
@media (max-width: 640px) {
  .hero .hero-pill {
    right: auto; bottom: auto;
    left: clamp(1.2rem, 4vw, 4rem); top: 1.25rem;
  }
}
.hero .markwrap { position: absolute; z-index: 2; left: clamp(0.4rem, 2vw, 2rem); bottom: -0.02em; overflow: hidden; }
/* Hero-Lockup: Vektor-Icon + vektorisierte Original-Wortmarke (aus dem Logo-Artwork
   getract, nicht Font) — gestochen scharf bei jeder Größe und einzeln animierbar.
   Proportionen relativ zur Icon-Höhe --hs, exakt dieselben Ratios wie der Header
   (aus dem 433×73-Logo-Lockup ÷73). */
.hero .mark.hl {
  --hs: clamp(56px, 11vw, 124px);
  display: inline-flex; align-items: center; gap: calc(var(--hs) * 0.4795);
  margin-bottom: clamp(0.6rem, 1.8vw, 1.6rem);
  color: #fff; font-size: 0;
}
.hero .hl-icon { width: var(--hs); height: var(--hs); flex: none; display: block; }
.hero .hl-icon rect { fill: #fff; transform-box: fill-box; }
.hero .hl-icon .r-right { transform-origin: 50% 100%; }
.hero .hl-icon .r-beam  { transform-origin: 100% 50%; }
.hero .hl-icon .r-left  { transform-origin: 50% 0; }
.hero .hl-icon .r-base  { transform-origin: 0 50%; }
.hero .hl-words { position: relative; flex: none; width: calc(var(--hs) * 4.3151); height: var(--hs); }
.hero .hl-mask {
  position: absolute; left: 0; top: calc(var(--hs) * 0.0548);
  width: 100%; height: calc(var(--hs) * 0.4521); overflow: hidden;
}
.hero .hl-ack { display: block; width: 100%; height: 100%; }
.hero .hl-arch {
  position: absolute; left: 0; top: calc(var(--hs) * 0.7123);
  width: calc(var(--hs) * 2.863); height: auto; display: block;
  transform-origin: 0 50%;
}
.hero .mark {
  margin: 0; color: #fff;
  font-size: clamp(3.2rem, 13.5vw, 12rem);
  font-weight: 400; letter-spacing: -0.02em; line-height: 1;
  display: block; transform: translateY(112%);
  transition: transform 1.4s var(--ease) 0.25s;
  will-change: transform;
}
html.loaded .hero .mark { transform: none; }
.hero .claim {
  position: absolute; z-index: 2;
  top: 6.2rem; right: clamp(1.2rem, 4vw, 4rem);
  max-width: 330px; color: #fff;
  font-size: 0.98rem; line-height: 1.55; text-align: right;
  text-shadow: 0 1px 26px rgba(0,0,0,0.35);
  opacity: 0; transform: translateY(18px);
  transition: opacity 1s ease 0.9s, transform 1.2s var(--ease) 0.9s;
}
html.loaded .hero .claim { opacity: 1; transform: none; }

/* ---------- Seitenkopf (Unterseiten) ---------- */
.page-head { padding-top: clamp(7rem, 16vw, 12rem); padding-bottom: clamp(2.5rem, 6vw, 5rem); }
.page-head .label { display: block; margin-bottom: 1.2rem; }

/* ---------- Intro: Text und Kennzahlen nebeneinander ---------- */
.intro-grid {
  max-width: 1200px; margin-inline: auto;
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(2.5rem, 6vw, 6rem);
  align-items: center;
}
.intro-grid .stats { margin-top: 0; }
@media (max-width: 900px) {
  .intro-grid { grid-template-columns: minmax(0, 1fr); max-width: 660px; }
  .intro-grid .stats { margin-top: clamp(3rem, 7vw, 6rem); }
}

/* ---------- Stats ---------- */
.stats {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(2.2rem, 5vw, 4.5rem) clamp(2rem, 6vw, 6rem);
  margin-top: clamp(3rem, 7vw, 6rem);
}
.stat { border-top: 1px solid var(--ink); padding-top: 1rem; }
/* Ziffern klappen unter der Linie hervor: Maske schneidet oben ab,
   die Zahl startet hinter der Linie und fährt nach unten heraus */
.stat .num-mask { display: block; overflow: hidden; }
.stat b {
  display: block;
  font-size: clamp(3.2rem, 7vw, 6rem);
  font-weight: 500; letter-spacing: -0.05em; line-height: 1.12;
  font-variant-numeric: tabular-nums;
  transform: translateY(-115%);
  transition: transform 0.65s var(--ease);
  transition-delay: var(--d, 0s);
}
.stat.in b { transform: none; }
.stat span { display: inline-block; margin-top: 0.9rem; }

/* ---------- Bildband / Bilder ---------- */
.band { padding-block: 0; }
.band .ph { height: clamp(320px, 68vh, 660px); }
/* Inset-Variante: Bild mit Seitenrand, hohes Format */
.band--inset { padding-inline: clamp(1.2rem, 4vw, 4rem); }
.band--inset .ph { height: clamp(440px, 88vh, 940px); }
@media (max-width: 640px) { .band--inset .ph { height: clamp(340px, 58vh, 560px); } }

/* ---------- Scroll-Zoom-Bühne (Fläche wächst zu Vollbild, Leistungen fahren ein) ---------- */
/* 260vh: Zoom + Leistungen auf den ersten ~3/4 der Strecke, kurzes Durchatmen,
   dann löst sich die Bühne und scrollt normal mit dem Folgeinhalt weg (kein Stehenbleiben) */
.zoomstage { position: relative; height: 260vh; padding-block: 0; } /* ohne Section-Padding: Sticky läuft bündig bis zum Footer */
/* Antialiasing-Naht zum Footer: Frame-Unterkante und Footer-Oberkante teilen sich eine
   Bruchteil-Pixelzeile — beim Mischen scheint der helle Seitenhintergrund als Haarlinie
   durch (DPR-abhängig). Dunkler Deckstreifen in Footer-Farbe macht den Bereich blickdicht. */
.zoomstage::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: var(--panel);
}
.zs-sticky { position: sticky; top: 0; height: 100svh; display: grid; place-items: center; overflow: hidden; }
/* Rahmen ist immer bildschirmgroß (Bezug für Logo, Leistungen und die Messungen in main.js) */
.zs-frame { position: relative; width: 100vw; height: 100svh; }
/* Der "Zoom" läuft rein über transform: das Fenster skaliert von 64vw × 72svh auf
   Vollbild und schneidet ab, das Video gleicht die Skalierung gegen. Kein Layout,
   kein Neuzeichnen pro Frame (clip-path über dem laufenden Video hat geruckelt) —
   der Compositor verschiebt nur fertige Ebenen */
.zs-clip {
  position: absolute; inset: 0; overflow: hidden;
  background: #0C0C0B; /* Fallback, solange das Video noch lädt */
  --zw: calc(1 - 0.36 * (1 - var(--zp, 0))); /* Breite: 64vw → 100vw */
  --zh: calc(1 - 0.28 * (1 - var(--zp, 0))); /* Höhe: 72svh → 100svh */
  transform: scale(var(--zw), var(--zh));
  will-change: transform;
}
.zs-img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  /* Zoom-Gefühl: Inhalt wächst mit dem Fenster mit und endet bei 1.0 —
     im Vollbild ist so viel Video sichtbar, wie object-fit: cover zulässt
     (keine Extra-Vergrößerung, keine Drift). Geteilt durch --zw/--zh hebt sich
     die Fenster-Skalierung auf: das Video bleibt unverzerrt */
  transform: scale(
    calc((0.893 + 0.107 * var(--zp, 0)) / var(--zw)),
    calc((0.893 + 0.107 * var(--zp, 0)) / var(--zh)));
  will-change: transform;
  /* NICHT entfernen: Chrome/Edge unter Windows geben ein deckendes Video an eine
     Hardware-Ebene (DirectComposition-Overlay) ab. Die kennt nur ganze Pixel und
     legt ihren Puffer bei jeder Größenänderung neu an — beim Scroll-Zoom also in
     fast jedem Frame, das Video wackelt sichtbar. Unter voller Deckkraft bleibt es
     im normalen Compositor und skaliert subpixelgenau. Gemessen: 0.999 reicht
     nicht (gilt noch als deckend), ab 0.9989999 greift es — 0.99 mit Reserve;
     über dem dunklen Grund und unter der Abdunklung unsichtbar */
  opacity: 0.99;
}
/* Grundabdunklung, immer aktiv: der Loop zeigt auch helle Motive (Putzfassade,
   weiße Innenräume) — ohne sie verliert das weiße Zeichen in der Zoom-Phase den Kontrast */
.zs-clip::before {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: rgba(12,12,11,0.28);
}
/* Der frühere dunkle Verlauf der Text-Phase (unten am stärksten) ist auf Wunsch entfernt —
   über dem Video liegt nur noch die Grundabdunklung oben */
.zs-logo {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: clamp(80px, 11vw, 150px); height: auto; z-index: 2;
  /* blendet synchron zum Zoom aus: bei Vollbild (--zp = 1) unsichtbar */
  opacity: calc(1 - var(--zp, 0));
}
/* Logo-Flug (Desktop, Klasse zs-fly aus main.js): statt auszublenden gleitet
   das Zeichen mit --zt vom Zentrum in Lage und Größe der A-Marke des
   Lettern-Panels (--fx/--fy/--fs gemessen in main.js). Die A-Marke selbst
   bleibt dann verborgen — das geflogene Zeichen ist das A; beim Hover der
   Zeilen 2/3 blendet es aus und G/C erscheinen wie gehabt */
.zoomstage.zs-fly .zs-logo {
  opacity: 1;
  transition: opacity 0.6s ease;
  transform: translate(-50%, -50%)
    translate3d(calc(var(--fx, 0px) * var(--zt, 0)), calc(var(--fy, 0px) * var(--zt, 0)), 0)
    scale(calc(1 + (var(--fs, 1) - 1) * var(--zt, 0)));
}
.zoomstage.zs-fly .zs-mark.mark-a { opacity: 0; }
.zoomstage.zs-fly:has(.svc-list li:nth-child(2) a:hover) .zs-logo,
.zoomstage.zs-fly:has(.svc-list li:nth-child(3) a:hover) .zs-logo,
.zoomstage.zs-fly:has(.svc-list li:nth-child(2) a:focus-visible) .zs-logo,
.zoomstage.zs-fly:has(.svc-list li:nth-child(3) a:focus-visible) .zs-logo { opacity: 0; }
/* Icon als SVG mit Kontur-Aufdeckung (einmalig beim Hereinscrollen, main.js) —
   gleiche Wachstumsrichtungen wie Intro und Header-Logo */
.zs-logo rect { fill: #fff; transform-box: fill-box; }
.zs-logo .r-right { transform-origin: 50% 100%; }
.zs-logo .r-beam  { transform-origin: 100% 50%; }
.zs-logo .r-left  { transform-origin: 50% 0; }
.zs-logo .r-base  { transform-origin: 0 50%; }
/* Leistungen über dem Vollbild-Video: fahren synchron zum früheren Text ein (--zt).
   pointer-events erst freigeben, wenn der Block sichtbar ist (Klasse zs-on, main.js) —
   sonst fängt der unsichtbare Overlay Klicks ab */
.zs-svc {
  position: absolute; z-index: 2;
  left: clamp(1.2rem, 4vw, 4rem); right: clamp(1.2rem, 4vw, 4rem);
  bottom: clamp(1.4rem, 4.5vh, 3rem);
  color: #fff;
  transform: translateY(calc(32px * (1 - var(--zt, 0))));
  opacity: var(--zt, 0);
  pointer-events: none;
}
.zoomstage.zs-on .zs-svc { pointer-events: auto; }
/* Einleitung über der Leistungsliste — genauso breit wie die Listen-Spalte
   darunter (1.15fr von 2fr = 0.575 der Breite abzüglich Spaltenabstand);
   eingerückt um Nummern-Spalte + Gap der Liste, damit der Text mit den
   Leistungs-Titeln (Architektur …) fluchtet */
.zs-head {
  margin-bottom: clamp(1.8rem, 5vh, 3.5rem);
  max-width: calc((100% - clamp(2rem, 5vw, 5rem)) * 0.575);
  padding-left: calc(clamp(3rem, 6vw, 4.5rem) + clamp(0.9rem, 2.5vw, 1.6rem));
}
.zs-head .label { color: var(--panel-muted); }
.zs-head .display-m { margin-top: 1.1rem; }
@media (max-width: 860px) { .zs-head { max-width: none; } }
.zs-svc-grid {
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  grid-template-rows: auto auto;
  column-gap: clamp(2rem, 5vw, 5rem); align-items: center;
}
.zs-svc .svc-list { grid-row: 1 / 3; --panel-hair: rgba(255,255,255,0.32); --panel-muted: rgba(255,255,255,0.78); }
/* Link mittig unter dem Lettern-Panel in der rechten Spalte */
.zs-svc .biglink { border-bottom-color: currentColor; margin-top: clamp(1.2rem, 3vh, 2rem); grid-column: 2; justify-self: center; }

/* Logo-Lettern-Panel: A ruht, G/C blenden beim Hover der Zeilen 2/3 um (reines CSS via :has()) */
.zs-marks { position: relative; align-self: center; height: clamp(180px, 26vh, 300px); }
.zs-mark {
  position: absolute; inset: 0; margin: auto;
  width: auto; height: 100%; aspect-ratio: 1;
  opacity: 0; transform: scale(0.92);
  transition: opacity 0.6s ease, transform 1.2s var(--ease);
}
/* Kontur-Aufdeckung wie Intro/Header/zs-logo — fill-box macht die Origins
   lokal zum Rect, deshalb funktioniert der Zug auch in den gedrehten/
   gespiegelten <g>-Wrappern von G und C (Trigger in main.js) */
.zs-mark rect { fill: #fff; transform-box: fill-box; }
.zs-mark .r-right { transform-origin: 50% 100%; }
.zs-mark .r-beam  { transform-origin: 100% 50%; }
.zs-mark .r-left  { transform-origin: 50% 0; }
.zs-mark .r-base  { transform-origin: 0 50%; }
.zs-mark.mark-a { opacity: 1; transform: none; }
.zs-svc-grid:has(.svc-list li:nth-child(2) a:hover) .mark-a,
.zs-svc-grid:has(.svc-list li:nth-child(3) a:hover) .mark-a,
.zs-svc-grid:has(.svc-list li:nth-child(2) a:focus-visible) .mark-a,
.zs-svc-grid:has(.svc-list li:nth-child(3) a:focus-visible) .mark-a { opacity: 0; transform: scale(0.92); }
.zs-svc-grid:has(.svc-list li:nth-child(2) a:hover) .mark-g,
.zs-svc-grid:has(.svc-list li:nth-child(2) a:focus-visible) .mark-g,
.zs-svc-grid:has(.svc-list li:nth-child(3) a:hover) .mark-c,
.zs-svc-grid:has(.svc-list li:nth-child(3) a:focus-visible) .mark-c { opacity: 1; transform: none; }

@media (max-width: 860px) {
  .zs-svc-grid { grid-template-columns: 1fr; }
  .zs-marks { display: none; } /* Hover existiert auf Touch nicht — Lettern-Panel entfällt */
  .zs-svc .svc-list { grid-row: auto; }
  .zs-svc .svc-list .s-sub { max-width: none; }
  .zs-svc .biglink { grid-column: auto; justify-self: start; }
}
@media (max-width: 640px) {
  /* Start-Ausschnitt mobil: 78vw breit */
  .zs-clip { --zw: calc(1 - 0.22 * (1 - var(--zp, 0))); }
  /* Weniger Text überm Video: Kurzbeschreibungen entfallen mobil — Einleitung,
     Titel und "Alle Leistungen" reichen, die Details stehen auf leistungen.html */
  .zs-svc .svc-list .s-sub { display: none; }
  /* Die Desktop-Einrückung (Flucht mit der Titel-Spalte) wirkt am Handy verloren —
     Label, Einleitung und "Alle Leistungen" teilen sich mobil eine linke Kante */
  .zs-head { padding-left: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .zoomstage { height: auto; margin-bottom: 0; }
  .zs-sticky { position: static; height: 100svh; }
  .zs-frame { width: 100%; height: 100%; }
  .zs-clip { transform: none; }
  .zs-svc { opacity: 1; }
  .zs-svc { transform: none; pointer-events: auto; }
  .zs-img { transform: none !important; }
}
.ph { position: relative; overflow: hidden; background: #D7D7D2; }
.ph img.zoom { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* ---------- Link groß ---------- */
.biglink {
  display: inline-block; margin-top: 2.4rem;
  font-size: clamp(1.7rem, 4vw, 3rem);
  font-weight: 500; letter-spacing: -0.04em;
  text-decoration: none;
  border-bottom: 2px solid var(--ink);
  padding-bottom: 0.12em;
}
.biglink .arr { display: inline-block; transition: transform 0.55s var(--ease); }
.biglink:hover .arr, .biglink:focus-visible .arr { transform: translateX(0.3em); }
/* Leistungen: „Projekt anfragen"-Link rechtsbündig — nur Desktop (mobil bleibt er linksbündig) */
@media (min-width: 861px) {
  #consulting .biglink { display: block; width: fit-content; margin-left: auto; }
}

/* ---------- Nummerierte Liste (Leistungen) ---------- */
.services { list-style: none; margin: clamp(2.5rem, 6vw, 5rem) 0 0; padding: 0; }
.services li {
  display: grid; grid-template-columns: 5rem 1fr;
  align-items: baseline; gap: 1rem;
  border-top: 1px solid var(--hair);
  padding: 1.5rem 0;
  transition: padding-left 0.8s var(--ease);
}
.services li:hover { padding-left: 0.9rem; }
.services li:last-child { border-bottom: 1px solid var(--hair); }
.services .no { font-size: 0.8rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.services h3 { margin: 0; font-size: clamp(1.3rem, 2.4vw, 1.9rem); font-weight: 450; letter-spacing: -0.02em; }
.services p { margin: 0.5rem 0 0; max-width: 52ch; color: var(--muted); font-size: 0.95rem; }

/* ---------- Projekt-Raster ---------- */
.projects {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: clamp(2.2rem, 5vw, 4rem) clamp(1.4rem, 3vw, 2.5rem);
  margin-top: clamp(2.5rem, 6vw, 5rem);
}
.projects.dense { grid-template-columns: repeat(3, 1fr); gap: clamp(1.8rem, 3.5vw, 3rem) clamp(1.2rem, 2.2vw, 1.8rem); }
.project { text-decoration: none; display: block; }
.project .ph { aspect-ratio: 4 / 3; }
.projects:not(.dense) .project .ph { aspect-ratio: 4 / 5; }
.project .ph .zoom { transition: transform 1.4s var(--ease); }
.project:hover .ph .zoom, .project:focus-visible .ph .zoom { transform: scale(1.045); }
.project h3 { margin: 1rem 0 0.15rem; font-size: 1.12rem; font-weight: 500; letter-spacing: -0.015em; line-height: 1.3; }
.project .meta { font-size: 0.83rem; color: var(--muted); }
.projects:not(.dense) .project:nth-child(even) { margin-top: clamp(1.5rem, 5vw, 4rem); }
div.project { cursor: default; }
@media (max-width: 900px) { .projects.dense { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px) {
  .projects, .projects.dense { grid-template-columns: 1fr; }
  .projects:not(.dense) .project:nth-child(even) { margin-top: 0; }
}

/* ---------- Projekt-Detailseite ---------- */
.meta-list { list-style: none; margin: 2rem 0 0; padding: 0; max-width: 420px; }
.meta-list li {
  display: grid; grid-template-columns: 8.5rem 1fr; gap: 1rem;
  border-top: 1px solid var(--hair); padding: 0.65rem 0;
  font-size: 0.95rem;
}
.meta-list li:last-child { border-bottom: 1px solid var(--hair); }
.meta-list .k { color: var(--muted); }
.gallery { display: grid; gap: clamp(1.4rem, 3vw, 2.5rem); margin-top: clamp(2.5rem, 6vw, 5rem); }
.gallery .ph { aspect-ratio: 3 / 2; }
.gallery .ph.tall { aspect-ratio: 4 / 5; max-width: 720px; }
.gallery .duo { display: grid; grid-template-columns: 1fr 1fr; gap: inherit; }
@media (max-width: 640px) { .gallery .duo { grid-template-columns: 1fr; } }
.backlink {
  display: inline-block; margin-top: 3rem;
  font-size: 0.9rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  text-decoration: none; border-bottom: 1.5px solid var(--ink); padding-bottom: 0.15em;
}

/* ---------- Projekt-Detailseite (Vorbild Nord-Å „Verve Tower") ----------
   Maße des Originals bei 1440px Viewport: Seitenrand 64 → Inhalt 1312;
   Textspalte beginnt bei 26.25 % und ist 47.6 % breit (408/624 px);
   Hero-Rahmen 1312×720, Galerie-Rahmen 624×720 im Abstand von 128 px.
   Die Hero liegt 300 px höher als ihr overflow-hidden-Rahmen und gleitet per
   Scroll-Parallax (main.js, .par); die Galerie-Bilder klappen stattdessen von
   links auf (img-reveal--left). Den Abschluss bildet das Projekt-Rad (unten). */
.pd-head { padding-top: clamp(7rem, 15vw, 11rem); padding-bottom: 0; }
.pd-herosec { padding-block: clamp(2rem, 4.4vw, 4rem) 0; }
.pd-metasec { padding-block: clamp(3.5rem, 8.9vw, 8rem) 0; }
.pd-textsec { padding-block: clamp(2.5rem, 4.4vw, 4rem) 0; }
.pd-gallerysec { padding-block: clamp(3.5rem, 8.9vw, 8rem) 0; }

.pd-col { margin-left: 26.25%; max-width: 47.6%; }
.pd-hero { aspect-ratio: 1312 / 720; }
.pd-gallery { display: grid; gap: clamp(3rem, 8.9vw, 8rem); }
/* Galerie-Rahmen nach Bildformat: Hochkant (Standard, wie Vorlage), quer, quadratisch —
   die Klasse steht im HTML passend zum natürlichen Format des Fotos */
.pd-gallery .ph { aspect-ratio: 624 / 720; }
.pd-gallery .ph.wide { aspect-ratio: 3 / 2; }
.pd-gallery .ph.square { aspect-ratio: 1 / 1; }
.pd-prose { margin-top: clamp(1.8rem, 3.3vw, 3rem); }

/* Frame-Player: Präsentations-Frames (identischer Ausschnitt) spielen im selben
   Rahmen nacheinander ab (main.js). Das aspect-ratio steht inline am Element,
   passend zum Pixelmaß der Frames — object-fit: contain hält die Zeichnungen
   deckungsgleich, weißer Grund passt zu den hellen Frames. */
.pd-frames { position: relative; }
.pd-frames .frames-stage { background: #fff; cursor: pointer; }
.frames-stage img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; opacity: 0; transition: opacity 0.45s ease;
}
.frames-stage img.on { opacity: 1; }
.frames-count {
  display: block; margin-top: 0.8rem; text-align: right;
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.14em;
  color: var(--muted); font-variant-numeric: tabular-nums;
}
@media (prefers-reduced-motion: reduce) { .frames-stage img { transition: none; } }

/* margin-block statt margin: 0 — das margin-left kommt von .pd-col (steht früher im Stylesheet) */
.pd-meta { list-style: none; margin-block: 0; padding: 0; display: grid; grid-template-columns: repeat(2, 1fr); gap: 2rem 1.5rem; }
.pd-meta .k { display: block; font-size: 0.8rem; color: var(--muted); margin-bottom: 0.3rem; }

/* Parallax-Bild: um --par höher als der Rahmen, die Verschiebung setzt main.js */
/* Parallax-Weg je Rahmen über --par (Standard 300 px) — main.js liest denselben Wert */
.ph > img.par, .ph > picture > img.par { position: absolute; left: 0; top: 0; width: 100%; height: calc(100% + var(--par, 300px)); object-fit: cover; will-change: transform; }
/* Unten verankert: der Beschnitt liegt oben (Himmel), Sockel und Vorplatz bleiben im Rahmen */
.pd-hero--bottom > img.par, .pd-hero--bottom > picture > img.par { object-position: center bottom; }
@media (prefers-reduced-motion: reduce) { .ph > img.par, .ph > picture > img.par { height: 100%; } }

/* ---------- Projekt-Rad „Weitere Projekte" (Ende jeder Projektseite) ----------
   Port der React/GSAP-Komponente „RadialScrollGallery" (ScrollTrigger pin +
   scrub) auf Vanilla-CSS/JS (main.js). Die Karten sitzen tangential auf einem
   Kreis (Radius 450 px Desktop / 320 px mobil), dessen untere Hälfte unter der
   Maske liegt (visiblePercentage 50). Die Bühne klebt eine Viewport-Höhe lang am
   Viewport, der Kreis dreht sich beim Scrollen (2000 px je 360°, Lerp-geglättet
   wie scrub: 1). Einzug der Karten mit back.out(1.2) + 50 ms Stagger; Hover/Fokus
   hebt die Karte (scale 1.25, −2 rem) und dämpft die übrigen (blur, grau, 40 %).
   Karten im Querformat: Titelbild 16:10 unverdeckt, Titelzeile darunter — passend
   zu den Architektur-Titelbildern (1200 × 732). Alle Maße (--rg-*) setzt main.js aus
   Radius, Kartengröße und Viewport-Höhe; --rg-s skaliert Rad und Karten gemeinsam,
   damit der Ausschnitt auch auf flachen Laptops in 100 svh passt. Die Karten
   erzeugt tools/build-wheel.js (beste Projekte derselben Bauherren-Kategorie). */
.pd-wheelsec { padding-block: clamp(5rem, 11vw, 10rem) 0; }
/* Überschrift als Nabe im freien Innenkreis: mittig zwischen Oberkarte und Horizont
   (--rg-hub/--rg-hub-w aus main.js), vor dem Ring, aber außerhalb der Verlaufsmaske.
   Keine Zeigerereignisse — eine angehobene Nachbarkarte darf darüberliegen */
.wheel-intro {
  position: absolute; left: 50%; top: var(--rg-hub, 60%);
  transform: translate(-50%, -50%);
  width: min(var(--rg-hub-w, 480px), calc(100vw - 2rem));
  display: flex; flex-direction: column; align-items: center;
  gap: 0.5rem; text-align: center;
  pointer-events: none;
}
.wheel-hint { display: block; font-size: 0.78rem; color: var(--muted); transition: opacity 0.9s var(--ease), transform 1.1s var(--ease); }
/* sobald gedreht wird, verschwindet der Scroll-Hinweis */
.radial-gallery.is-scrolled .wheel-hint { opacity: 0; }
/* Titel und Etikett skalieren mit dem Rad (--rg-s), damit sie in den Innenkreis passen */
.wheel-intro .display-l { font-size: min(calc(2.9rem * var(--rg-s, 1)), 10vw); }
.wheel-intro .label { font-size: calc(0.5rem + 0.22rem * var(--rg-s, 1)); }
.wheel-hint-b { display: inline-block; animation: wheel-bounce 1s infinite; }
@keyframes wheel-bounce {
  0%, 100% { transform: translateY(-25%); animation-timing-function: cubic-bezier(0.8, 0, 1, 1); }
  50% { transform: none; animation-timing-function: cubic-bezier(0, 0, 0.2, 1); }
}

.radial-gallery {
  --rg-s: 1;             /* Skalierung von Rad + Karten (main.js) */
  --rg-r: 450px;         /* Radius */
  --rg-hidden: 0.5;      /* verdeckter Anteil des Kreises */
  --rg-mask-h: 720px;    /* Höhe des sichtbaren Ausschnitts */
  --rg-dur: 2000px;      /* Scrollweg der Drehung (main.js: anteilig bei weniger als 6 Karten) */
  --rg-cw: calc(320px * var(--rg-s));   /* Kartenbreite; Höhe = Bild 16:10 + Titelzeile */
  /* Einzug: GSAP back.out(1.2) — Näherung per cubic-bezier, exakt per linear() (unten) */
  --rg-back-out: cubic-bezier(0.34, 1.45, 0.64, 1);
  --rg-back-in: cubic-bezier(0.36, 0, 0.66, -0.45);
  position: relative;
  /* Pin-Spacer: Bühnenhöhe + Scrollweg (wie ScrollTrigger pinSpacing) */
  height: calc(max(100svh, 480px) + var(--rg-dur));
}
@supports (animation-timing-function: linear(0, 1)) {
  .radial-gallery {
    --rg-back-out: linear(0, 0.1968, 0.3682, 0.5159, 0.6416, 0.7469, 0.8334, 0.9028, 0.9568, 0.997, 1.025, 1.0425, 1.0512, 1.0527, 1.0486, 1.0406, 1.0304, 1.0196, 1.0098, 1.0027, 1);
    --rg-back-in: linear(0, -0.0027, -0.0098, -0.0196, -0.0304, -0.0406, -0.0486, -0.0527, -0.0512, -0.0425, -0.025, 0.003, 0.0432, 0.0972, 0.1666, 0.2531, 0.3584, 0.4841, 0.6318, 0.8032, 1);
  }
}
@media (max-width: 767px) {
  .radial-gallery { --rg-cw: calc(224px * var(--rg-s)); }
}
.rg-stage {
  position: sticky; top: 0;
  height: max(100svh, 480px);
  /* Rad mittig; oben Luft für den fixierten Header */
  display: flex; align-items: center; justify-content: center;
  padding: 4.5rem 0 1rem;
  overflow: clip;
}
.rg-mask {
  position: relative; width: 100%; height: var(--rg-mask-h);
  overflow: clip;
}
/* Verlaufsmaske nur auf dem Ring — die Nabe (Überschrift) bleibt ungetrübt */
.rg-ringwrap {
  position: absolute; inset: 0;
  -webkit-mask-image: linear-gradient(to top, transparent 0%, #000 40%, #000 100%);
          mask-image: linear-gradient(to top, transparent 0%, #000 40%, #000 100%);
}
.rg-ring {
  position: absolute; margin: 0; padding: 0; list-style: none;
  left: calc(50% - var(--rg-r)); bottom: calc(var(--rg-r) * -2 * var(--rg-hidden));
  width: calc(var(--rg-r) * 2); height: calc(var(--rg-r) * 2);
  will-change: transform;
  opacity: 0; transition: opacity 0.5s ease-out;
}
.radial-gallery.is-ready .rg-ring { opacity: 1; }
.rg-item {
  position: absolute; top: 50%; left: 50%; z-index: 10;
  /* Position auf dem Kreis + Tangentialdrehung (--x/--y/--a aus main.js) */
  transform: translate(-50%, -50%) translate3d(var(--x, 0px), var(--y, 0px), 0) rotate(var(--a, 0deg));
  /* Einzug (fromTo scale 0 / autoAlpha 0 → 1, 1,2 s, Stagger 50 ms). Rückwärts
     („toggleActions: play none none reverse") läuft dieselbe Kurve gespiegelt
     (back.in) und der Stagger von hinten; scale als Einzel-Property, damit die
     Kreis-Transform unberührt bleibt */
  scale: 0; opacity: 0; visibility: hidden;
  --rg-delay: calc((var(--n, 1) - 1 - var(--i, 0)) * 50ms);
  transition-property: scale, opacity, visibility;
  transition-duration: 1.2s, 1.2s, 0s;
  transition-timing-function: var(--rg-back-in), var(--rg-back-in), linear;
  transition-delay: var(--rg-delay), var(--rg-delay), calc(var(--rg-delay) + 1.2s);
}
.radial-gallery.is-in .rg-item {
  scale: 1; opacity: 1; visibility: visible;
  --rg-delay: calc(var(--i, 0) * 50ms);
  transition-timing-function: var(--rg-back-out), var(--rg-back-out), linear;
  transition-delay: var(--rg-delay), var(--rg-delay), var(--rg-delay);
}

/* Karte: Titelbild 16:10 oben (unverdeckt), Titelzeile darunter */
.rg-card {
  position: relative; display: block; overflow: hidden;
  width: var(--rg-cw);
  border-radius: 12px; background: var(--bg); border: 1px solid var(--hair);
  box-shadow: 0 10px 15px -3px rgba(17, 17, 16, 0.1), 0 4px 6px -4px rgba(17, 17, 16, 0.1);
  color: var(--ink); text-decoration: none; text-align: left; cursor: pointer; outline: none;
  transition: transform 0.5s ease-out, filter 0.5s ease-out, opacity 0.5s ease-out, box-shadow 0.5s ease-out;
  will-change: transform;
}
.rg-card:focus-visible { box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--ink); }
.rg-item.is-hover .rg-card { transform: translateY(-2rem) scale(1.25); box-shadow: 0 24px 40px -16px rgba(17, 17, 16, 0.28), 0 6px 12px -6px rgba(17, 17, 16, 0.12); }
.rg-ring.has-hover .rg-item:not(.is-hover) .rg-card { filter: blur(2px) grayscale(1); opacity: 0.4; }
.rg-media { position: relative; display: block; overflow: hidden; aspect-ratio: 16 / 10; background: #D7D7D2; }
.rg-media img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  filter: grayscale(0.3);
  transition: transform 0.7s ease-out, filter 0.7s ease-out;
}
.rg-item.is-hover .rg-media img { transform: scale(1.1); filter: none; }
.rg-top {
  position: absolute; left: 0; right: 0; top: 0;
  display: flex; justify-content: space-between; align-items: flex-start;
  padding: 0.8rem;
}
.rg-badge {
  display: inline-flex; align-items: center;
  padding: 0 0.5rem; border-radius: 999px;
  font-size: 10px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; line-height: 1.7;
  color: var(--ink); background: rgba(253, 253, 251, 0.82);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
/* Handy: kein Weichzeichner auf den Karten des drehenden Rads (teuer in jedem Frame) */
@media (max-width: 860px) {
  .rg-badge { background: rgba(253, 253, 251, 0.92); -webkit-backdrop-filter: none; backdrop-filter: none; }
}
.rg-arrow {
  width: 1.5rem; height: 1.5rem; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--ink); color: var(--bg);
  opacity: 0; transform: rotate(-45deg);
  transition: opacity 0.5s ease, transform 0.5s ease;
}
.rg-arrow svg { display: block; }
.rg-item.is-hover .rg-arrow { opacity: 1; transform: none; }
/* Titelzeile: rückt beim Hover um 0,4 rem nach oben, Unterstrich wächst */
/* Schrift und Polster der Titelzeile wachsen mit der Kartenbreite (--rg-cw), damit auf
   kleinen Rädern (flache Laptops, 8/10 Plätze) keine Titel abgeschnitten werden */
.rg-cap { display: block; overflow: hidden; padding: calc(0.3rem + var(--rg-cw) * 0.016) calc(0.35rem + var(--rg-cw) * 0.017) calc(0.33rem + var(--rg-cw) * 0.017); }
.rg-cap-in { display: block; transform: translateY(0.4rem); transition: transform 0.5s ease; }
.rg-item.is-hover .rg-cap-in { transform: none; }
.rg-title { display: block; font-size: calc(0.5rem + var(--rg-cw) * 0.026); font-weight: 500; letter-spacing: -0.015em; line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rg-sub { display: block; margin-top: 0.15rem; font-size: calc(0.42rem + var(--rg-cw) * 0.0175); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.rg-bar { display: block; height: 2px; margin-top: 0.55rem; background: var(--ink); width: 0; opacity: 0; transition: width 0.5s ease, opacity 0.5s ease; }
.rg-item.is-hover .rg-bar { width: 100%; opacity: 1; }
@media (max-width: 767px) {
  .rg-top { padding: 0.6rem; }
  .rg-title { letter-spacing: -0.02em; }
  .rg-bar { margin-top: 0.4rem; }
}

/* Ohne JS (bzw. bevor main.js die Geometrie gesetzt hat): schlichte Kartenreihe */
.radial-gallery:not(.is-ready) { height: auto; }
.radial-gallery:not(.is-ready) .rg-stage { position: static; height: auto; min-height: 0; padding-block: 2rem; }
.radial-gallery:not(.is-ready) .rg-mask { height: auto; }
.radial-gallery:not(.is-ready) .rg-ringwrap { position: static; -webkit-mask-image: none; mask-image: none; }
.radial-gallery:not(.is-ready) .wheel-intro { position: static; transform: none; width: auto; margin-bottom: 1.5rem; pointer-events: auto; }
.radial-gallery:not(.is-ready) .rg-ring {
  position: static; width: auto; height: auto; opacity: 1;
  display: flex; flex-wrap: wrap; justify-content: center; gap: 1.5rem; padding-inline: clamp(1.2rem, 4vw, 4rem);
}
.radial-gallery:not(.is-ready) .rg-item { position: static; transform: none; scale: 1; opacity: 1; visibility: visible; transition: none; }

/* Reduzierte Bewegung: Rad steht still (kein Pin, keine Drehung, kein Einzug) */
@media (prefers-reduced-motion: reduce) {
  .radial-gallery { height: auto; }
  .rg-stage { position: static; height: auto; min-height: 0; padding-block: 2rem; }
  .rg-ring { opacity: 1; transition: none; }
  .rg-item { scale: 1; opacity: 1; visibility: visible; transition: none; }
  .rg-card, .rg-media img, .rg-arrow, .rg-cap-in, .rg-bar { transition: none; }
  .wheel-hint-b { animation: none; }
}

@media (max-width: 760px) {
  .pd-col, .pd-meta { margin-left: 0; max-width: none; }
  /* Quer-Titelbilder mobil in flachem Rahmen zeigen, damit das ganze Gebäude
     sichtbar bleibt. Der Parallax-Überhang (calc(100% + 300px)) macht den
     abgedeckten Bereich sonst viel höher als den Rahmen und schneidet das Bild
     zu einem schmalen Streifen — deshalb die Höhe mobil auf 100 % begrenzen
     (die Parallax-Verschiebung schaltet main.js auf Mobil ohnehin ab). */
  .pd-hero { aspect-ratio: 3 / 2; }
  .pd-hero--portrait { aspect-ratio: 3621 / 5429; } /* 1610: eigenes Hochkantfoto voll zeigen */
  .ph > img.par, .ph > picture > img.par { height: 100%; }
}

/* ---------- Team ---------- */
.team {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: clamp(2rem, 4vw, 3.5rem) clamp(1.2rem, 2.4vw, 2rem);
  margin-top: clamp(2.5rem, 6vw, 5rem);
}
.member .ph { aspect-ratio: 3 / 4; }
.member .ph img { filter: grayscale(0.15); }
.member h3 { margin: 1rem 0 0.1rem; font-size: 1.08rem; font-weight: 500; }
.member .role { font-size: 0.85rem; color: var(--muted); }
.member a { font-size: 0.85rem; text-decoration: none; border-bottom: 1px solid var(--hair); }
.member a:hover, .member a:focus-visible { border-color: var(--ink); }
@media (max-width: 860px) { .team { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .team { grid-template-columns: 1fr; } }

/* ---------- Marquee ---------- */
/* ---------- Prosa (Rechtsseiten, Projekttexte) ---------- */
.prose { max-width: 68ch; }
.prose h2 { font-size: clamp(1.5rem, 3vw, 2.1rem); font-weight: 500; letter-spacing: -0.025em; margin: 2.6em 0 0.7em; }
.prose h3 { font-size: 1.15rem; font-weight: 600; margin: 2em 0 0.5em; }
.prose ul { padding-left: 1.2em; }
.prose li { margin-bottom: 0.35em; }
.prose a { text-decoration: underline; text-underline-offset: 3px; overflow-wrap: anywhere; }
.todo-note {
  border: 1px dashed var(--muted); padding: 1rem 1.2rem; margin: 1.5rem 0;
  font-size: 0.9rem; color: var(--muted); background: rgba(0,0,0,0.02);
}

/* ---------- Testimonials (Laufband + Portrait + Zitat-Slider) ---------- */
/* Foto-Geometrie als Variablen: Foto und Laufband teilen sich dieselben Kanten */
.testi {
  --ph-top: clamp(2.5rem, 7vh, 4.5rem); --ph-w: clamp(200px, 22vw, 320px); --ph-x: 66%;
  --testi-pb: clamp(4rem, 9vw, 8rem);
  --t-base: clamp(2.2rem, 6vh, 4rem); /* gemeinsame Unterkante: Team-Link, Pfeile, Foto, Laufband */
  position: relative; overflow: hidden; min-height: min(92vh, 900px); padding: 0 0 var(--testi-pb);
}
/* Laufband senkrecht rechts neben dem Foto; oben/unten bündig mit dem Bild abgeschnitten */
.t-banner {
  position: absolute; z-index: 0;
  left: calc(var(--ph-x) + var(--ph-w) / 2 + 0.25rem);
  top: var(--ph-top); bottom: var(--t-base);
  overflow: hidden; writing-mode: vertical-rl; white-space: nowrap; pointer-events: none;
}
.t-banner .track {
  display: inline-block; animation: slide-y 38s linear infinite;
  font-size: clamp(2.6rem, 4.6vw, 5rem);
  font-weight: 500; letter-spacing: -0.05em; line-height: 1.1;
}
@keyframes slide-y { to { transform: translateY(-50%); } }
.t-slides { position: relative; z-index: 1; min-height: inherit; }
.t-slide {
  position: absolute; inset: 0;
  opacity: 0; visibility: hidden; transition: opacity 0.7s ease, visibility 0.7s;
}
.t-slide.active { opacity: 1; visibility: visible; }
.t-photo {
  position: absolute; left: var(--ph-x); top: var(--ph-top); transform: translateX(-50%);
  /* Foto reicht über die Slide-Unterkante hinaus bis auf die Grundlinie von Link und Pfeilen */
  width: var(--ph-w); height: calc(100% - var(--ph-top) + var(--testi-pb) - var(--t-base));
  overflow: hidden; background: #D7D7D2;
}
.t-photo img { width: 100%; height: 100%; object-fit: cover; }
.t-quote {
  position: absolute; left: clamp(1.2rem, 4vw, 4rem); bottom: clamp(5.5rem, 14vh, 8.5rem);
  margin: 0; max-width: min(44%, 42rem);
  font-size: clamp(1.15rem, 2.2vw, 1.9rem); font-weight: 500;
  letter-spacing: -0.015em; line-height: 1.4;
}
.t-author {
  position: absolute; left: clamp(1.2rem, 4vw, 4rem); bottom: clamp(2.2rem, 6vh, 4rem);
  margin: 0; color: var(--muted); font-size: 0.95rem;
}
/* Team-Link: gleiche Zeile wie die Slider-Pfeile — Link links, Pfeile rechts */
.t-more { position: absolute; z-index: 2; left: clamp(1.2rem, 4vw, 4rem); bottom: clamp(2.2rem, 6vh, 4rem); margin: 0; }
.t-nav { position: absolute; z-index: 2; right: clamp(1.2rem, 4vw, 4rem); bottom: clamp(2.2rem, 6vh, 4rem); display: flex; gap: 0.6rem; }
.t-nav button {
  appearance: none; border: 0; cursor: pointer;
  width: 3.2rem; height: 3.2rem;
  background: var(--panel); color: var(--panel-ink);
  font-size: 1.5rem; line-height: 1;
  transition: opacity 0.3s ease;
}
.t-nav button:hover, .t-nav button:focus-visible { opacity: 0.75; }
/* Schmale Desktop-Breiten: Foto weiter links, damit das Laufband nicht unter die Pfeile läuft */
@media (max-width: 1000px) { .testi { --ph-x: 62%; } }
@media (max-width: 760px) {
  .testi { min-height: 0; }
  .t-slides { min-height: 0; }
  .t-slide { position: relative; inset: auto; display: none; padding: 0 clamp(1.2rem, 4vw, 4rem) 1rem; }
  .t-slide.active { display: block; }
  /* Laufband rechts neben dem zentrierten Foto, gleiche Ober-/Unterkante */
  .t-banner { top: clamp(2rem, 6vh, 3rem); bottom: auto; height: 58vh;
    left: calc(50% + min(31vw, 160px) + 0.25rem); }
  .t-banner .track { font-size: clamp(2rem, 9vw, 3rem); }
  .t-photo { position: relative; left: auto; top: auto; transform: none;
    width: min(62vw, 320px); height: 58vh; margin: clamp(2rem, 6vh, 3rem) auto 0; }
  .t-quote { position: static; max-width: 34rem; margin-top: 5.6rem; }
  .t-author { position: static; margin-top: 1rem; }
  /* Pfeile mittig direkt unter dem Foto (Foto-Oberkante + Fotohöhe + Abstand);
     die Leiste ist so breit wie das Foto, beide Buttons füllen sie gleichmäßig */
  .t-nav { right: auto; bottom: auto; left: 50%; transform: translateX(-50%);
    top: calc(clamp(2rem, 6vh, 3rem) + 58vh + 0.9rem); margin: 0;
    width: min(62vw, 320px); }
  .t-nav button { flex: 1; width: auto; }
  .t-more { position: static; display: inline-block; margin: 1.6rem 0 0 clamp(1.2rem, 4vw, 4rem); }
}
@media (prefers-reduced-motion: reduce) {
  .t-banner .track { animation: none; }
  .t-slide { transition: none; }
}

/* ---------- Leistungs-Liste (Startseite, liegt über der Zoom-Bühne) ---------- */
.svc-list { list-style: none; margin: 0; padding: 0; align-self: center; }
.svc-list a {
  display: grid; grid-template-columns: clamp(3rem, 6vw, 4.5rem) 1fr auto;
  align-items: baseline; gap: clamp(0.9rem, 2.5vw, 1.6rem);
  padding: clamp(1rem, 2.6vh, 1.8rem) 0;
  border-top: 1px solid var(--panel-hair);
  text-decoration: none;
  transition: padding-left 0.8s var(--ease); /* wie a.pj-row:hover */
}
.svc-list li:last-child a { border-bottom: 1px solid var(--panel-hair); }
.svc-list a:hover, .svc-list a:focus-visible { padding-left: 0.9rem; }
.svc-list .s-no { font-size: 0.85rem; color: var(--panel-muted); letter-spacing: 0.1em; }
.svc-list .s-name {
  display: block; font-size: clamp(1.6rem, 3.6vw, 2.7rem);
  font-weight: 500; letter-spacing: -0.03em; line-height: 1.12;
}
.svc-list .s-sub { display: block; margin-top: 0.45rem; color: var(--panel-muted); font-size: 0.92rem; max-width: 30rem; }
.svc-list .arr { transition: transform 0.55s var(--ease); }
.svc-list a:hover .arr, .svc-list a:focus-visible .arr { transform: translateX(0.35em); }

/* ---------- Footer ---------- */
footer.site {
  position: relative; overflow: hidden;
  /* liegt über dem Leistungs-Overlay der Zoom-Bühne (z-index 2), wenn er darüberfährt */
  z-index: 3;
  background: var(--panel); color: var(--panel-ink);
  padding: clamp(4rem, 9vw, 7.5rem) clamp(1.2rem, 4vw, 4rem) 2rem;
}
.f-wm {
  position: absolute; z-index: 0; left: 50%; top: 50%;
  transform: translate(-50%, -50%) translateY(var(--fwm-y, 0px));
  opacity: var(--fwm-o, 1);
  width: min(96vw, 1700px);
  pointer-events: none; user-select: none;
  will-change: transform, opacity;
}
.f-wm img { display: block; width: 100%; height: auto; opacity: 0.045; }
/* Wasserzeichen (Logo + Schriftzug) nur in der Webansicht, auf Mobilgeräten aus */
@media (max-width: 767px) { .f-wm { display: none; } }
.f-inner { position: relative; z-index: 1; }
.f-contact, .f-map { max-width: 660px; margin-inline: auto; }
footer.site .label { color: var(--panel-muted); }
.f-contact .display-m { max-width: 18ch; margin: 1.4rem 0 0; }
.f-note { color: var(--panel-muted); max-width: 34rem; margin: 1.6rem 0 0; line-height: 1.65; }
.f-adr { list-style: none; margin: 1.8rem 0 0; padding: 0; display: grid; gap: 0.4rem; font-size: 0.96rem; }
.f-adr a { text-decoration: none; }
.f-adr a:hover, .f-adr a:focus-visible { text-decoration: underline; text-underline-offset: 4px; }
.f-mail {
  display: inline-block; margin-top: 1.6rem;
  font-size: clamp(1.05rem, 2vw, 1.35rem); font-weight: 500;
  text-decoration: none; border-bottom: 1.5px solid currentColor; padding-bottom: 0.1em;
}
.f-map { margin-top: clamp(3.5rem, 8vw, 6rem); }
.f-links {
  list-style: none; margin: 1.6rem 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(2rem, 6vw, 5rem); row-gap: 0.55rem;
  max-width: 640px;
}
/* Hover-Effekt: staggered letter roll-up (a.lroll, Split per JS) */
.f-links a {
  text-decoration: none;
  font-size: clamp(1.35rem, 2.8vw, 2rem); font-weight: 500;
  letter-spacing: -0.02em; line-height: 1.35;
}
.f-bottom {
  display: flex; flex-wrap: wrap; gap: 1rem 2rem; justify-content: space-between;
  border-top: 1px solid var(--panel-hair);
  margin-top: clamp(3.5rem, 8vw, 6rem);
  padding-top: 1.6rem;
  font-size: 0.78rem; color: var(--panel-muted);
}
.f-bottom a { text-decoration: none; }
.f-bottom a:hover, .f-bottom a:focus-visible { text-decoration: underline; text-underline-offset: 4px; }

/* ==========================================================================
   Kontakt — dunkle Seite
   ========================================================================== */
body.page-dark { background: #0D0D0C; color: var(--panel-ink); --hair: var(--panel-hair); --muted: var(--panel-muted); }
.page-dark header.site { color: #fff; }
.page-dark header.site .brand img { filter: none; }
.page-dark .label, .page-dark .muted { color: var(--panel-muted); }
.page-dark .ph { background: #1B1B19; }
/* Fotos auf der dunklen Seite: durchgehend professionelles Schwarzweiß */
.page-dark .ph img { filter: grayscale(1) contrast(1.06) brightness(0.92); }
.page-dark .process .p-icon::before, .page-dark .process .p-icon::after { background: var(--panel-ink); }
.page-dark .biglink { border-bottom-color: currentColor; }

/* ---------- Kontakt-Hero: Standard-Hero mit interaktiver Karte statt Bild ----------
   Google-Maps-Embed (Büro-Standort, wie auf der alten Website) füllt den ganzen
   Sticky-Hero. Die Karte ist anfangs nicht bedienbar (pointer-events: none), damit
   das Mausrad die Seite scrollt statt die Karte zu zoomen — „Karte aktivieren"
   schaltet sie frei; dabei weicht der große Schriftzug nach unten aus. */
/* Heller Hero: Papierton statt dunkel (doppelte Klasse schlägt das spätere .t-hero);
   auch maßgeblich für die Hell/Dunkel-Abtastung von Menü-Panel und Cursor-Punkt */
.t-hero.t-hero--map { background: #F2F0EB; }
.t-map {
  position: absolute; inset: 0; width: 100%; height: 100%; border: 0;
  background: #F2F0EB; /* Papierton der Karte, bis die Kacheln geladen sind */
  pointer-events: none;
}
.t-hero--map.map-on .t-map { pointer-events: auto; }
/* MapLibre-Beiwerk: Attribution unauffällig, Logo-Puffer unten links */
.t-map .maplibregl-ctrl-attrib { font-size: 0.7rem; }
/* Heller Hero: statt dunkler Vignette eine zarte Papier-Aufhellung oben/unten
   (doppelte Klasse schlägt das spätere .t-hero::after) */
.t-hero.t-hero--map::after {
  background: linear-gradient(0deg, rgba(242,240,235,0.75), rgba(242,240,235,0) 42%),
              linear-gradient(180deg, rgba(242,240,235,0.6), rgba(242,240,235,0) 26%);
}
/* Auf der hellen Karte: „Kontakt"-Schriftzug und Hinweise in Schwarz */
.page-kontakt .t-word { color: #111110; }
.page-kontakt .t-scroll { color: #111110; }
/* Logo + Burger dunkel, solange der helle Karten-Hero unterm Header liegt
   (Klasse setzt das Inline-Script in kontakt.html); gewinnt per Spezifität
   gegen .page-dark header.site (weiß) und header.site.on-media */
.page-kontakt header.site.on-light-hero { color: #111110; }
.page-kontakt header.site.on-light-hero .brand img { filter: invert(1); }
.t-hero--map::after { transition: opacity 0.6s ease; }
.t-hero--map.map-on::after { opacity: 0; }
.t-hero--map .t-wordwrap { pointer-events: none; }
.t-hero--map.map-on .t-word { transform: translateY(112%); transition-delay: 0s; }
.t-hero--map .t-scroll { transition: opacity 0.6s ease; }
.t-hero--map.map-on .t-scroll { opacity: 0; }
/* Gesperrte Karte: Zeiger als Hinweis, dass ein Klick sie aktiviert */
.t-hero--map:not(.map-on) { cursor: pointer; }
/* Routen-Link zu Google Maps: erscheint unten rechts, sobald die Karte aktiv ist
   (tauscht den Platz mit dem ausblendenden Scroll-Hinweis). Optik kommt von
   .k-maps (großer Unterstrich-Link wie im Standort-Abschnitt), hier nur
   Position, dunkle Farbe für die helle Karte und Ein-/Ausblenden. */
.t-map-route {
  position: absolute; z-index: 2;
  right: clamp(1.2rem, 4vw, 4rem); bottom: clamp(1.5rem, 4vh, 2.8rem);
  color: #111110;
  opacity: 0; visibility: hidden; transform: translateY(8px); pointer-events: none;
  transition: opacity 0.45s ease, transform 0.45s ease, visibility 0s linear 0.45s;
}
.t-hero--map.map-on .t-map-route {
  opacity: 1; visibility: visible; transform: none; pointer-events: auto;
  transition: opacity 0.45s ease 0.15s, transform 0.45s ease 0.15s;
}

/* ---------- Kontakt-Formular (nur Unterlinien, große Sendezeile) ---------- */
.k-form { margin-top: clamp(3rem, 7vw, 5rem); max-width: 560px; display: grid; gap: 2.4rem; }
.k-form input, .k-form textarea {
  display: block; width: 100%;
  background: transparent; border: 0; border-radius: 0;
  border-bottom: 1px solid #3A3A36;
  color: var(--panel-ink); font: inherit; font-size: 1.25rem;
  padding: 0.45rem 0 0.95rem;
  transition: border-color 0.35s ease;
}
.k-form ::placeholder { color: var(--panel-muted); opacity: 1; }
.k-form input:focus, .k-form textarea:focus { outline: none; border-bottom-color: var(--panel-ink); }
.k-form textarea { resize: vertical; min-height: 6.5rem; }
.k-note { margin: 0.2rem 0 0; color: var(--panel-muted); font-size: 0.9rem; }
.k-privacy { font-size: 0.8rem; }
.k-privacy a { color: inherit; text-underline-offset: 0.18em; }
.k-send {
  appearance: none; background: none; border: 0; padding: 0; margin-top: 0.4rem;
  cursor: pointer; color: inherit; width: fit-content;
  font: inherit; font-size: clamp(1.9rem, 4.5vw, 3.2rem);
  font-weight: 500; letter-spacing: -0.04em; line-height: 1.1;
  display: inline-flex; align-items: center; gap: 0.4em;
}
.k-send .arr { transition: transform 0.55s var(--ease); }
.k-send:hover .arr, .k-send:focus-visible .arr { transform: translateX(0.3em); }

/* ---------- Standort-Sektion (großes ALT/ÖTT/ING über dem Foto) ---------- */
.k-city { position: relative; }
.k-cityname {
  position: absolute; z-index: 2;
  top: clamp(2.5rem, 6vw, 5.5rem); right: clamp(2rem, 12vw, 12rem);
  margin: 0; color: #fff; text-transform: uppercase;
  font-size: clamp(3.6rem, 13vw, 13rem);
  font-weight: 500; letter-spacing: -0.03em; line-height: 0.92;
}
.k-cityname span { display: block; }
/* Foto mittig, Kontaktdaten links, Maps-Link rechts unten — das große Wort
   ragt oben rechts über die Foto-Ecke hinaus (wie im Vorbild) */
.k-city-grid {
  display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 36%) minmax(0, 0.85fr);
  gap: clamp(1.5rem, 4vw, 3.5rem); align-items: stretch;
}
.k-city-photo { margin: clamp(3.2rem, 8vw, 7.5rem) 0 0; height: clamp(520px, 92vh, 960px); }
.k-maps-col {
  display: flex; align-items: flex-end; justify-content: flex-end;
  padding-bottom: clamp(3rem, 12vh, 8rem);
}
.k-info { display: flex; flex-direction: column; justify-content: center; gap: clamp(2.6rem, 6vh, 4.5rem); }
.k-info .k-k { display: block; color: var(--panel-muted); font-size: 1.02rem; margin-bottom: 0.7rem; }
.k-big {
  display: block; color: var(--panel-ink); text-decoration: none; width: fit-content;
  font-size: clamp(1.6rem, 2.6vw, 2.6rem);
  font-weight: 500; letter-spacing: -0.035em; line-height: 1.15;
  white-space: nowrap;
}
a.k-big:hover, a.k-big:focus-visible { text-decoration: underline; text-underline-offset: 6px; text-decoration-thickness: 2px; }
.k-maps {
  font-size: clamp(1.5rem, 3vw, 2.4rem);
  font-weight: 500; letter-spacing: -0.035em;
  text-decoration: none; border-bottom: 2px solid currentColor; padding-bottom: 0.1em;
}
.k-maps .arr { display: inline-block; transition: transform 0.55s var(--ease); }
.k-maps:hover .arr, .k-maps:focus-visible .arr { transform: translateX(0.3em); }
@media (max-width: 860px) {
  /* Ortsname bleibt auch mobil auf dem Foto liegen (oben rechts über der Bild-Ecke),
     mit weichem Schatten für die Lesbarkeit auf dem helleren Bildinhalt */
  .k-cityname {
    /* Foto beginnt um das Section-padding-top tiefer als die Section — den Text
       um genau diesen Betrag (+ etwas Luft) nach unten setzen, damit er auf dem Bild liegt */
    top: calc(clamp(5rem, 11vw, 10.5rem) + clamp(1rem, 3vw, 1.6rem));
    right: clamp(1.2rem, 5vw, 2rem);
    font-size: clamp(3.2rem, 15vw, 6rem);
    text-shadow: 0 2px 22px rgba(0, 0, 0, 0.45);
  }
  .k-city-grid { grid-template-columns: 1fr; }
  .k-city-photo { order: -1; margin-top: 0; height: clamp(340px, 62vh, 560px); }
  .k-maps-col { padding-bottom: 0; margin-top: 1.5rem; }
}

/* ---------- Logo-Intro (Startseite) ----------
   Choreografie: das Icon deckt sich entlang seiner Kontur auf (rechte Wand ↑,
   Balken ←, linke Wand ↓, Sockel →; eine durchgehende Timeline in main.js),
   die Wortmarke steigt aus einer Maske, ARCHITEKTEN spationiert ein. Dann
   blendet das Lockup aus und der Vorhang hebt sich — `html.loaded` wird erst
   dabei gesetzt, damit die Hero-Animation hinter der Vorhangkante startet. */
.intro { position: fixed; inset: 0; z-index: 100; pointer-events: none; }
.intro .i-curtain {
  position: absolute; inset: 0; background: var(--bg);
  transition: transform 1.15s var(--ease);
}
.intro.s-lift .i-curtain { transform: translateY(-101%); }
.intro .i-lockup {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: clamp(16px, 2.6vw, 30px);
  transition: opacity 0.45s ease;
}
.intro.s-out .i-lockup { opacity: 0; }
.intro .i-icon { width: clamp(64px, 9vw, 104px); height: auto; display: block; }
.intro .i-icon rect { fill: #111110; transform-box: fill-box; }
/* Startzustand + Wachstumsrichtung der vier Konturabschnitte (Fortschritt setzt JS) */
.intro .i-icon .r-right { transform: scaleY(0); transform-origin: 50% 100%; }
.intro .i-icon .r-beam  { transform: scaleX(0); transform-origin: 100% 50%; }
.intro .i-icon .r-left  { transform: scaleY(0); transform-origin: 50% 0; }
.intro .i-icon .r-base  { transform: scaleX(0); transform-origin: 0 50%; }
.intro .i-words { display: flex; flex-direction: column; align-items: flex-start; }
.intro .i-mask { display: block; overflow: hidden; }
.intro .i-ack {
  display: block; width: clamp(230px, 34vw, 400px); height: auto;
  filter: invert(1); /* weiße Logodatei -> schwarz auf hellem Vorhang */
  transform: translateY(112%); transition: transform 0.9s var(--ease) 0.25s;
}
.intro.s-words .i-ack { transform: none; }
/* ARCHITEKTEN als Original-Schriftzug (aus der Logodatei geschnitten);
   Breite/Abstand im Original-Verhältnis zur ackermann-Zeile (209/315 bzw. 16/315).
   Statt Letterspacing zieht sich das Bild per scaleX zusammen. */
.intro .i-arch {
  display: block; width: calc(clamp(230px, 34vw, 400px) * 0.663); height: auto;
  margin-top: calc(clamp(230px, 34vw, 400px) * 0.051); margin-left: 2px;
  filter: invert(1); /* weiße Logodatei -> schwarz auf hellem Vorhang */
  opacity: 0; transform: scaleX(1.35); transform-origin: 0 50%;
  transition: opacity 0.7s ease 0.25s, transform 1s var(--ease) 0.25s;
}
.intro.s-words .i-arch { opacity: 1; transform: none; }
.intro.s-done { display: none; }

/* ---------- Seitenübergang (Vorhang) ----------
   Exit: beim Klick auf einen internen Link fährt ein Vorhang in Panel-Farbe
   von unten über die Seite, dann navigiert der Browser unsichtbar dahinter.
   Enter: die Zielseite lädt bereits verdeckt (Klasse pt-enter setzt ein
   Inline-Script im <head>, bevor der erste Paint passiert) und der Vorhang
   hebt sich weiter nach oben — eine durchgehende Aufwärtsbewegung, die
   loaded-Reveals steigen hinter der Kante auf. Choreografie in main.js. */
html.pt::after, html.pt-enter::after {
  content: ""; position: fixed; inset: 0; z-index: 90;
  background: var(--panel);
  pointer-events: none;
}
/* Kommt die Navigation aus dem HELLEN Menü-Panel (dunkle Seiten), fährt auch
   der Vorhang hell — Farbe wird per sessionStorage an die Zielseite gereicht */
html.pt-light::after { background: #FDFDFB; }
/* Der Exit-Vorhang läuft unter dem Scrim (Menü bleibt sichtbar) — der dunkle
   Schleier würde das Weiß aber abdunkeln, deshalb blendet er hier aus */
html.pt-light .scrim.open { opacity: 0; }
/* Exit-Vorhang unter Scrim (19) und Menü-Panel (20): das offene Menü bleibt
   bis zur Navigation unangetastet sichtbar, nur die Seite dahinter wird verdeckt */
html.pt::after { z-index: 15; transform: translateY(102%); transition: transform 0.6s var(--ease); }
html.pt.pt-exit::after { transform: none; }
html.pt-enter::after {
  transition: transform 1.15s var(--ease);
  /* Sicherheitsnetz: hebt den Vorhang notfalls auch ohne JS-Weiterlauf
     (analog zum Hard-Cap des Intros) */
  animation: pt-failsafe 1.15s var(--ease) 4s forwards;
}
html.pt-enter.pt-lift::after { transform: translateY(-101%); animation: none; }
@keyframes pt-failsafe { to { transform: translateY(-101%); } }
@media (prefers-reduced-motion: reduce) {
  html.pt::after, html.pt-enter::after { display: none !important; }
}

/* ---------- Barrierefreiheit / Motion ---------- */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: var(--bg); padding: 0.7rem 1.2rem;
  font-size: 0.9rem; text-decoration: none;
}
.skip:focus { left: 0; }
:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  #intro { display: none !important; }
  .reveal, .mask > .mi, .img-reveal, .img-reveal .zoom, .stat b,
  .hero .art, .hero .mark, .hero .claim, header.site {
    opacity: 1 !important; transform: none !important; clip-path: none !important; transition: none !important;
  }
  .home .hero .art img, .zs-img, .t-hero .t-bg { transform: none !important; }
  .hero .art img { transition: none; }
  .project .ph .zoom { transition: none; }
  .lroll .rc { transition: none !important; }
}

/* ==========================================================================
   Team — dunkle Seite im Editorial-Look (Vorbild: Nord-Å)
   ========================================================================== */

/* ---------- Hero: Vollbild-Foto bleibt stehen (sticky), Inhalt schiebt sich darüber ---------- */
.t-hero {
  position: sticky; top: 0; z-index: 0;
  height: 100svh; min-height: 560px;
  overflow: hidden; padding: 0; background: #0D0D0C;
}
.page-team main > *:not(.t-hero),
.page-leistungen main > *:not(.t-hero),
.page-kontakt main > *:not(.t-hero) { position: relative; z-index: 1; background: #0D0D0C; }
.t-hero .t-bg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; filter: grayscale(1) contrast(1.06) brightness(0.8);
  transform: scale(1.18) translateY(calc(var(--hd, 0) * -16%));
}
.t-hero::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(0deg, rgba(10,10,9,0.62), rgba(10,10,9,0) 45%),
              linear-gradient(180deg, rgba(10,10,9,0.45), rgba(10,10,9,0) 30%);
}
.t-intro {
  position: absolute; z-index: 2;
  right: clamp(1.5rem, 5vw, 5rem); top: 26%;
  margin: 0; width: min(80vw, 24rem);
  color: #fff; text-align: left; text-wrap: balance;
  font-size: clamp(1.1rem, 2vw, 1.55rem); font-weight: 500;
  line-height: 1.55; letter-spacing: -0.01em;
  opacity: 0; transition: opacity 1s ease 0.8s;
}
html.loaded .t-intro { opacity: 1; }
@media (max-width: 860px) {
  .t-intro {
    right: auto; left: 50%; top: 40%;
    transform: translate(-50%, -50%);
    width: min(88vw, 44rem); text-align: center;
  }
}
.t-wordwrap { position: absolute; z-index: 2; left: clamp(0.5rem, 2.2vw, 2.2rem); bottom: -0.03em; overflow: hidden; }
.t-word {
  margin: 0; display: block; color: #fff;
  font-size: clamp(4.4rem, 19vw, 21rem);
  font-weight: 500; letter-spacing: -0.055em; line-height: 1;
  transform: translateY(112%); transition: transform 1.2s var(--ease) 0.25s;
  will-change: transform;
}
html.loaded .t-word { transform: none; }
/* Längere Wörter („Leistungen") brauchen eine kleinere Schriftgröße, um in die Breite zu passen;
   padding-bottom gibt Unterlängen (g) Platz, die das overflow:hidden des Wrappers sonst abschneidet */
.t-word--long { font-size: clamp(3.2rem, 16vw, 18rem); padding-bottom: 0.18em; }
/* Hero-Bild auf der Leistungen-Seite: weiterer Ausschnitt, dezenterer Drift */
.page-leistungen .t-hero .t-bg { transform: scale(1.06) translateY(calc(var(--hd, 0) * -6%)); }
/* Hero-Bild auf der Team-Seite: weiter herausgezoomt, damit mehr vom Fest-Foto sichtbar ist */
.page-team .t-hero .t-bg { transform: scale(1.04) translateY(calc(var(--hd, 0) * -4%)); }
@media (max-width: 640px) {
  .page-leistungen .t-scroll { display: none; }
}
.t-scroll {
  position: absolute; z-index: 2;
  right: clamp(1.2rem, 4vw, 4rem); bottom: clamp(1.5rem, 4vh, 2.8rem);
  color: #fff; font-size: 0.82rem; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase;
  opacity: 0; transition: opacity 1s ease 1.2s;
}
html.loaded .t-scroll { opacity: 0.85; }
/* ---------- Großer Abschnitts-Link („Offene Stellen ↘") ---------- */
.t-biglink {
  display: inline-flex; align-items: baseline; gap: 0.3em;
  margin-top: clamp(2.8rem, 7vw, 5rem);
  color: inherit; text-decoration: none; width: fit-content;
  font-size: clamp(2.1rem, 5.5vw, 4rem);
  font-weight: 500; letter-spacing: -0.04em; line-height: 1.1;
  border-bottom: 2px solid currentColor; padding-bottom: 0.12em;
}
.t-biglink .arr { display: inline-block; transition: transform 0.55s var(--ease); }
.t-biglink:hover .arr, .t-biglink:focus-visible .arr { transform: translate(0.18em, 0.18em); }

/* ---------- Teamfoto-Band: 3:2-Format wie das Original, klappt sanft von links auf ---------- */
.img-reveal--left { clip-path: inset(0 100% 0 0); transition-duration: 1.6s; }
.t-badgeband .ph, .t-karriereband .ph { height: auto; aspect-ratio: 21 / 9; max-height: 92vh; margin-inline: auto; }

/* ---------- Rotierendes Kreis-Text-Badge auf dem Teamfoto ---------- */
.band.t-badgeband { position: relative; }
.t-badge {
  position: absolute; z-index: 3;
  right: clamp(1.5rem, 6vw, 5rem); bottom: clamp(1.5rem, 6vw, 5rem);
  width: clamp(7rem, 14vw, 11rem);
  pointer-events: none; user-select: none;
}
.t-badge svg {
  display: block; width: 100%; height: auto; overflow: visible;
  transform-origin: 50% 50%;
  animation: t-spin 24s linear infinite;
}
.t-badge text {
  fill: #fff; font-size: 10.5px; font-weight: 600;
  letter-spacing: 0.24em; text-transform: uppercase;
}
@keyframes t-spin { to { transform: rotate(360deg); } }

/* ---------- Team-Collage: Riesen-Headline sticky hinter den Porträts ---------- */
.t-meet { position: relative; height: 300vh; padding: 0; overflow: clip; }
.t-meet-sticky {
  position: sticky; top: 0; height: 100svh;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}
.t-meet-title {
  margin: 0; color: #fff; text-transform: uppercase; text-align: center;
  font-size: clamp(4rem, 17vw, 17rem);
  font-weight: 600; letter-spacing: -0.02em; line-height: 0.95;
}
.t-ports { list-style: none; margin: 0; padding: 0; position: absolute; inset: 0; }
.t-port {
  position: absolute; left: var(--x); top: var(--y);
  width: var(--w); z-index: var(--z, 1); margin: 0;
  will-change: transform;
  transform-origin: var(--o, left bottom); /* Porträts wachsen aus ihrer Ecke */
}
.t-port img {
  display: block; width: 100%; height: auto;
  filter: grayscale(1) contrast(1.06) brightness(0.92);
  transition: transform 0.5s ease;
}
.t-port:hover img { transform: scale(0.96); }
.t-cap {
  position: absolute; inset: 0; z-index: 1;
  display: flex; flex-direction: column; justify-content: flex-end; gap: 0.1rem;
  padding: 0.9rem;
  background: linear-gradient(180deg, rgba(13,13,12,0) 42%, rgba(13,13,12,0.85));
  opacity: 0; transition: opacity 0.4s ease;
  color: #fff;
}
.t-cap b { font-weight: 600; font-size: clamp(0.82rem, 1.1vw, 1rem); letter-spacing: -0.01em; }
.t-cap i { font-style: normal; font-size: clamp(0.7rem, 0.9vw, 0.82rem); color: var(--panel-muted); }
.t-port:hover .t-cap, .t-port:focus .t-cap, .t-port:focus-visible .t-cap { opacity: 1; }
.t-port:focus { outline: none; }
.t-port:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
/* Mobil: Collage wird zur einspaltigen Liste — jedes Porträt volle Breite,
   keine Überlappung, Namen immer sichtbar (kein Hover auf Touch).
   Scroll-Transform des JS per !important neutralisiert. */
@media (max-width: 640px) {
  .t-meet { height: auto; overflow: visible; }
  .t-meet-sticky { position: static; height: auto; padding: clamp(3rem, 10vw, 5rem) 0 2.2rem; }
  .t-ports {
    position: static; inset: auto;
    display: grid; grid-template-columns: 1fr;
    gap: 1.4rem;
    padding: 0 clamp(1.2rem, 4vw, 4rem) clamp(3rem, 10vw, 5rem);
  }
  .t-port { position: relative; left: auto; top: auto; width: auto; transform: none !important; will-change: auto; }
  .t-cap { opacity: 1; padding: 0.9rem; }
  .t-cap b { font-size: 1rem; }
  .t-cap i { font-size: 0.85rem; }
}

/* ---------- Karriere: Job-Zeilen mit Pfeil ---------- */
.t-jobs { list-style: none; margin: clamp(2.8rem, 7vw, 5rem) 0 0; padding: 0; max-width: 46rem; }
.t-jobs a {
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem;
  padding: clamp(1.3rem, 3vw, 2rem) 0;
  border-top: 1px solid var(--panel-hair);
  text-decoration: none;
  font-size: clamp(1.6rem, 3.8vw, 2.7rem);
  font-weight: 500; letter-spacing: -0.03em; line-height: 1.15;
}
.t-jobs li:last-child a { border-bottom: 1px solid var(--panel-hair); }
.t-jobs .arr { flex: none; transition: transform 0.55s var(--ease); }
.t-jobs a:hover .arr, .t-jobs a:focus-visible .arr { transform: translateX(0.35em); }
.t-jobs-note { margin: 1.8rem 0 0; color: var(--panel-muted); font-size: 0.9rem; max-width: 34rem; }

@media (prefers-reduced-motion: reduce) {
  .t-word, .t-intro, .t-scroll { opacity: 1 !important; transition: none !important; }
  .t-word { transform: none !important; }
  .t-badge svg { animation: none; }
  .t-port { transform: none !important; }
}

/* ==========================================================================
   Projekte — Showcase-Seite (Vorbild: Nord-Å)
   ========================================================================== */

/* Heller Seiteninhalt schiebt sich über den Sticky-Hero (Curtain wie Team-Seite) */
.page-projekte main > *:not(.t-hero) { position: relative; z-index: 1; background: var(--bg); }
/* Hero auf der Projektseite in Farbe statt Schwarzweiß; Intro braucht auf dem
   hellen Sommerbild einen Schatten, um lesbar zu bleiben */
.page-projekte .t-hero .t-bg { filter: none; }
.page-projekte .t-intro {
  text-shadow: 0 1px 26px rgba(0, 0, 0, 0.5);
  /* näher an den rechten Rand gerückt */
  right: clamp(1.2rem, 2vw, 2rem);
}

/* ---------- Projektfilter (Alle / Öffentlich / Privat / NGOs): gehört zur
   Archivliste „Alle Projekte" — der Kartenstapel bleibt unberührt ---------- */
.pj-filter { display: flex; flex-wrap: wrap; gap: clamp(1.4rem, 3.5vw, 2.6rem); margin-top: clamp(2.2rem, 5vw, 3.2rem); }
.pjf-btn {
  appearance: none; background: none; border: 0; padding: 0 0 0.35em; cursor: pointer;
  font: inherit; font-weight: 600; font-size: clamp(0.85rem, 1.3vw, 1rem);
  letter-spacing: 0.1em; text-transform: uppercase; line-height: 1.45;
  color: var(--muted);
  border-bottom: 2px solid transparent;
  transition: color 0.5s var(--ease), border-color 0.5s var(--ease);
}
.pjf-btn:hover, .pjf-btn:focus-visible { color: var(--ink); }
.pjf-btn.is-active { color: var(--ink); border-color: currentColor; }
/* Gefilterte Zeilen: [hidden] muss die eigene display-Regel schlagen */
.pj-archive li[hidden] { display: none; }

/* ---------- Gestapelte Projekt-Bühnen: jedes Bild bleibt am Viewport stehen,
   das nächste schiebt sich beim Scrollen darüber. Die Bilder sitzen wie im
   Vorbild kompakt mittig im Viewport. ---------- */
.pj-stack { padding: 0; }
.pj-item {
  position: sticky; top: 0;
  display: flex; align-items: center; justify-content: center;
  height: 100svh; min-height: 480px;
  --pj-vy: clamp(4.5rem, 9svh, 5.5rem);
  --pjr: 1.639; /* Seitenverhältnis der Titelbilder (1200 × 732) */
  padding: var(--pj-vy) clamp(2.5rem, 8vw, 9rem);
  text-decoration: none;
  /* Bewusst KEIN Hintergrund: die Bühne ist durchsichtig, damit beim
     Hochschieben kein weißer Balken vor dem Bild über die vorherige Karte
     fährt — man sieht stattdessen die schrumpfende Vorgängerkarte, bis das
     neue Bild sie überdeckt (Kartenstapel-Effekt) */
}
.pj-frame {
  position: relative; display: block;
  /* Rahmen im Seitenverhältnis des Fotos — das Bild ist dadurch immer komplett
     zu sehen; so groß wie möglich, ohne die Luft seitlich/oben/unten zu verlieren.
     Kein eigener Hintergrund: der würde bei der Scroll-Skalierung als dünne
     helle Kante (Rahmen) an den Bildrändern durchscheinen */
  aspect-ratio: var(--pjr);
  width: min(100%, calc((100svh - var(--pj-vy) * 2) * var(--pjr)));
  overflow: hidden;
  /* Nord-Å-Effekt: die gepinnte Bühne schrumpft (1 → 0.6), während die
     nächste Karte sie überdeckt — Wert liefert main.js. Ursprung mittig:
     die Karte schrumpft zur Viewport-Mitte und liegt dadurch immer komplett
     hinter der nachrückenden Karte in voller Größe */
  transform: scale(var(--pjs, 1));
  transform-origin: 50% 50%;
  will-change: transform;
}
.pj-frame > img {
  /* 1px Überstand ringsum: verhindert, dass beim Skalieren durch Subpixel-
     Rundung eine dünne helle Linie am Bildrand aufblitzt */
  position: absolute; inset: -1px; width: calc(100% + 2px); height: calc(100% + 2px);
  object-fit: cover;
  transition: transform 1.4s var(--ease);
}
.pj-item:hover .pj-frame > img, .pj-item:focus-visible .pj-frame > img { transform: scale(1.035); }
/* Abdunklung unten, damit die Infozeile auf hellen Bildern lesbar bleibt */
.pj-frame::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(0deg, rgba(12,12,11,0.4), rgba(12,12,11,0) 38%);
}
.pj-titlepos {
  position: absolute; inset: 0; z-index: 1;
  display: flex; align-items: center; justify-content: center;
  padding-inline: clamp(1rem, 3vw, 3rem); text-align: center;
}
/* „Projekt öffnen" mittig auf dem Bild gibt es nur mobil (siehe Media Query unten) */
.pj-open { display: none; }
.pj-info {
  position: absolute; z-index: 1;
  left: clamp(2.8rem, 5vw, 4rem); right: clamp(2.8rem, 5vw, 4rem);
  bottom: clamp(1rem, 2.4vw, 1.5rem);
  display: flex; justify-content: space-between; align-items: baseline; gap: 1.5rem;
  color: #fff; font-size: 0.9rem; letter-spacing: 0.02em;
}
.pj-info .pj-year { white-space: nowrap; font-variant-numeric: tabular-nums; }
@media (max-width: 640px) { .pj-info { font-size: 0.78rem; } }
/* Auslauf des Stapels: der Spacer hält die letzte Karte eine Viewport-Höhe lang
   gepinnt, das hochgezogene Archiv schiebt sich währenddessen darüber —
   exakt dieselbe Geometrie wie zwischen zwei Karten */
.pj-tail { height: 100svh; min-height: 480px; }
.page-projekte .pj-stack + .wrap { margin-top: -100svh; }
/* Ohne Schrumpf-Animation (reduced motion) deckt die Bühne selbst ab, sonst
   blitzen unterschiedlich hohe Vorgängerkarten hinter den Rändern hervor */
@media (prefers-reduced-motion: reduce) {
  .pj-item { background: var(--bg); }
}
/* Mobil: kein Sticky-Stapel — die Karten stehen einfach untereinander.
   Der Nord-Å-Schrumpfeffekt bleibt dem Desktop vorbehalten (main.js setzt
   --pjs zwar weiter, transform: none ignoriert das hier). */
@media (max-width: 768px) {
  .pj-stack { padding: clamp(2rem, 7vw, 3rem) 0; }
  .pj-item {
    position: static;
    height: auto; min-height: 0;
    padding: 0 clamp(1.2rem, 4vw, 2rem);
  }
  .pj-item + .pj-item { margin-top: clamp(1.8rem, 6vw, 3rem); }
  .pj-frame { transform: none; width: 100%; }
  /* Statt der Infozeile: „Projekt öffnen"-Link mittig auf dem Bild, im Stil
     der großen Text-Links (biglink) — Unterstreichung + Pfeil */
  .pj-info { display: none; }
  .pj-open {
    display: inline-block;
    color: #fff; font-size: 1rem;
    font-weight: 500; letter-spacing: -0.02em;
    border-bottom: 2px solid currentColor; padding-bottom: 0.12em;
    text-shadow: 0 1px 20px rgba(0, 0, 0, 0.35);
  }
  /* Stapel-Auslauf und Archiv-Überlappung nur für den Desktop-Effekt nötig */
  .pj-tail { display: none; }
  .page-projekte .pj-stack + .wrap { margin-top: 0; }
}

/* ---------- Archiv-Liste: Name | Beschreibung | / Jahr ---------- */
.pj-count { font-size: 0.24em; font-weight: 500; letter-spacing: 0; vertical-align: super; }
/* Abschlusslinie am UL statt an der letzten Zeile: bleibt auch dann korrekt,
   wenn der Projektfilter die letzte Zeile ausblendet */
.pj-archive { list-style: none; margin: clamp(2.8rem, 7vw, 5rem) 0 0; padding: 0; border-bottom: 1px solid var(--hair); }
.pj-row {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr) minmax(5.5rem, auto);
  gap: clamp(1rem, 3vw, 2.5rem); align-items: baseline;
  padding: clamp(1.3rem, 3.2vw, 2.2rem) 0;
  border-top: 1px solid var(--hair);
  color: inherit; text-decoration: none;
}
a.pj-row { transition: padding-left 0.8s var(--ease); }
a.pj-row:hover, a.pj-row:focus-visible { padding-left: 0.9rem; }
.pj-n { font-weight: 600; font-size: clamp(0.85rem, 1.3vw, 1rem); letter-spacing: 0.1em; text-transform: uppercase; line-height: 1.45; }
.pj-d { font-size: clamp(0.95rem, 1.5vw, 1.15rem); }
.pj-y { font-size: clamp(0.95rem, 1.5vw, 1.15rem); text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
@media (max-width: 700px) {
  .pj-row { grid-template-columns: minmax(0, 1fr) auto; }
  .pj-n { grid-row: 1; grid-column: 1; }
  .pj-y { grid-row: 1; grid-column: 2; justify-self: end; }
  .pj-d { grid-row: 2; grid-column: 1 / -1; margin-top: 0.15rem; color: var(--muted); font-size: 0.92rem; }
}
/* Hover-Vorschau: das Titelbild schwebt als Tooltip seitlich neben dem Zeiger über
   der Archivzeile (Element wird per JS erzeugt, nur bei echtem Zeiger) */
.pj-preview {
  position: fixed; left: 0; top: 0; z-index: 5;
  width: clamp(240px, 26vw, 420px); aspect-ratio: 3 / 2;
  overflow: hidden; pointer-events: none;
  opacity: 0; scale: 0.82;
  transition: opacity 0.4s var(--ease), scale 0.4s var(--ease);
  will-change: transform;
}
.pj-preview img { width: 100%; height: 100%; object-fit: cover; }
.pj-preview.visible { opacity: 1; scale: 1; }

@media (prefers-reduced-motion: reduce) {
  .pj-frame > img { transition: none; }
  .pj-preview { transition: opacity 0.2s linear; scale: 1; }
}
