/* ============================================================
   Franklin & Partners — static site custom CSS.
   Only the handful of behaviours that the compiled Tailwind bundle
   (styles.css) doesn't already cover: the JS-driven chrome that used
   to be framer-motion (mobile nav, cookie banner, sticky CTA).
   Loaded AFTER styles.css so equal-specificity rules win.
   ============================================================ */

/* ---- Mobile nav dropdown (replaces framer height 0->auto) ---- */
.fp-mobile-menu {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows 0.25s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.2s ease;
}
.fp-mobile-menu > div { overflow: hidden; min-height: 0; }
.fp-mobile-menu.is-open { grid-template-rows: 1fr; opacity: 1; }

/* hamburger icon swap */
[data-nav-toggle] .fp-icon-close { display: none; }
[data-nav-toggle][aria-expanded="true"] .fp-icon-open { display: none; }
[data-nav-toggle][aria-expanded="true"] .fp-icon-close { display: inline; }

/* ---- Mobile menu backdrop (replaces framer opacity fade) ---- */
.fp-backdrop {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.fp-backdrop.is-open { opacity: 1; pointer-events: auto; }

/* ---- Sticky CTA bars (mobile-cta + page-level bars) ----
   markup ships with translate-y-full (hidden); JS adds .is-visible. */
/* translate-y-full ships via Tailwind v4's `translate` property (not `transform`),
   so the reveal must reset `translate` — overriding only `transform` was a no-op. */
.fp-sticky-cta { transition: translate 0.3s ease, transform 0.3s ease; }
.fp-sticky-cta.is-visible { translate: 0 0 !important; transform: translateY(0) !important; }

/* ---- Cookie banner (replaces framer spring + AnimatePresence) ---- */
.fp-cookie-root[hidden] { display: none !important; }
.fp-cookie-backdrop {
  opacity: 0;
  transition: opacity 0.25s ease;
}
.fp-cookie-root.is-open .fp-cookie-backdrop { opacity: 1; }
.fp-cookie-panel {
  transform: translateY(110%);
  transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
}
.fp-cookie-root.is-open .fp-cookie-panel { transform: translateY(0); }
.fp-cookie-details {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.3s ease;
}
.fp-cookie-details > div { overflow: hidden; min-height: 0; }
.fp-cookie-details.is-open { grid-template-rows: 1fr; }

@media (prefers-reduced-motion: reduce) {
  .fp-mobile-menu, .fp-backdrop, .fp-sticky-cta,
  .fp-cookie-backdrop, .fp-cookie-panel, .fp-cookie-details {
    transition: none !important;
  }
}

/* ── iOS Safari white-screen fix (mobile) ───────────────────────────────────
   Symptom: on a real iPhone the page paints WHITE and stays white as you scroll
   (worse in Low Power Mode), while it renders perfectly in every desktop / headless
   engine. Cause: the decorative ".mesh-orb" gradient glows use huge blurs
   (blur-[120px] on 300–700px elements) and are each forced into their own GPU
   compositing layer (will-change + translateZ(0) + contain). 8 per page × 117
   pages, on a ~19,000px-tall page, blows past iOS Safari's per-tab tile-memory
   budget, so WebKit drops tiles and paints white. The orbs are faint ambiance
   (opacity 10–30%), so on phones/tablets we drop the GPU cost entirely; desktop
   (which has the memory headroom and no reported issue) keeps the full design. */
@media (max-width: 1024px) {
  .mesh-orb { display: none !important; }                 /* kill the 120px-blur GPU layers */
  /* Decorative round "glow" orbs (rounded-full + blur-3xl / blur-[120px]) relied
     on a huge GPU blur for their soft edge — that's what whited out iOS Safari.
     Drop the blur but keep the SOFT look by feathering the edge with a radial
     mask instead: no offscreen blur buffer, color-agnostic, cheap. Same vibe as
     the hero's radial-gradient glows, none of the GPU cost. */
  [class*="rounded-full"][class*="blur"] {
    filter: none !important;
    -webkit-mask-image: radial-gradient(closest-side, #000 32%, transparent 80%) !important;
            mask-image: radial-gradient(closest-side, #000 32%, transparent 80%) !important;
  }
  /* Everything else blurred (backdrop-blur UI panels, glass-light) just loses the
     blur — those keep their own solid/translucent background. */
  [class*="blur"]:not([class*="rounded-full"]), .glass-light {
    filter: none !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
  }
}

/* ── Long-page render fix (mobile): paint sections on demand ─────────────────
   content-visibility:auto lets WebKit SKIP painting off-screen sections until
   they're scrolled near — so a ~19,000px page only ever holds ~2 screens in the
   compositor instead of all 25. That's what stops iOS Safari from exhausting its
   per-tab tile memory and painting white on the long home page (the orbs above
   were one cost; the page's painted HEIGHT is the other). All content stays — it
   just renders as you reach it.
     • first section (hero) excluded → above-the-fold paints instantly, no placeholder
     • contain-intrinsic-size 'auto' remembers each section's real height after its
       first render, so scrolling stays stable (the 800px is only the first guess)
     • footer included; mobile only — desktop has the headroom and is untouched. */
@media (max-width: 1024px) {
  main > section:not(:first-of-type),
  body > footer {
    content-visibility: auto;
    contain-intrinsic-size: auto 800px;
  }
}

/* ── Team-Hub (Über uns) ─────────────────────────────────────────────────────
   Führung + Schlüsselpersonen + Dozenten als EINE Section (#team).
   Eigenes CSS statt Tailwind, weil styles.css vorgebaut ist: neue Utilities
   würden dort fehlen und stillschweigend nichts tun.
   Gestaltungsprinzip: KEINE Karten. Die Führung behält ihr originales
   Zitat-Layout, alles darunter ist ein redaktionelles Register aus Haarlinien,
   laufenden Nummern und Spalten — nur der CTA ist bewusst ein Kasten.
   Ohne blur/backdrop-filter und ohne Einblend-Animation: das mobile Blur-Kill
   weiter oben und der ensureVisible-Transform in .eleventy.js hätten beides
   entfernt bzw. wären ein Risiko für unsichtbaren Inhalt. */
.tm { --tm-line: rgba(255,255,255,.09); --tm-acc: #3fa8f5; }

/* Tier-Überschrift: Label + auslaufende Haarlinie */
.tm-tier { display: flex; align-items: center; gap: .9rem; margin: 3.25rem 0 1.6rem; }
.tm-tier::after { content: ""; flex: 1; height: 1px;
  background: linear-gradient(90deg, var(--tm-line), transparent); }
.tm-tier-label { font-size: .72rem; font-weight: 600; letter-spacing: .18em;
  text-transform: uppercase; color: #94a3b8; white-space: nowrap; }

/* Portraits (geteilt). Alle Quellen sind 3:4 — in quadratischen Rahmen wird der
   Ausschnitt nach oben gezogen, sonst sitzt der Kopf am oberen Rand. */
.tm-photo { position: relative; overflow: hidden; border-radius: 14px;
  background: #1e293b; border: 1px solid rgba(255,255,255,.1); }
.tm-photo img { display: block; width: 100%; height: 100%; object-fit: cover;
  object-position: center 25%; transition: transform .5s ease; }

/* ── Tier 2: Schlüsselpersonen — zentriertes Trio ohne Trenner. Der Ansprech-
   partner (Tobias) steht größer in der Mitte, flankiert von den beiden anderen.
   Größenstaffel der Section: Führung 360px → Ansprechpartner 260px /
   Flanken 175px → Dozenten-Register 136px. */
.tm-people { display: flex; flex-direction: column; gap: 1.6rem; padding: .6rem 0 .4rem; }
.tm-person { display: flex; align-items: center; gap: 1.2rem; }
.tm-person .tm-photo { width: 104px; aspect-ratio: 3 / 4; height: auto; flex: none; }
/* Mobil (gestapelt) steht der Ansprechpartner zuerst */
.tm-person-lead { order: -1; }
.tm-person-lead .tm-photo { width: 136px;
  border-color: rgba(63,168,245,.4);
  box-shadow: 0 16px 40px rgba(63,168,245,.14); }
.tm-person-tag { display: inline-flex; align-items: center; gap: .45rem;
  font-size: .64rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase;
  color: #9fd0f7; background: rgba(63,168,245,.1); border: 1px solid rgba(63,168,245,.28);
  border-radius: 999px; padding: .3rem .7rem; margin-bottom: .55rem; }
.tm-person-tag::before { content: ""; width: 6px; height: 6px; border-radius: 50%;
  background: var(--tm-acc); flex: none; }
.tm-person-name { font-family: var(--font-heading); font-weight: 700; color: #fff; font-size: 1rem; }
.tm-person-role { color: var(--tm-acc); font-size: .8rem; margin-top: .3rem; line-height: 1.45; }
.tm-person-org { color: #94a3b8; font-size: .75rem; margin-top: .25rem; }
@media (min-width: 880px) {
  .tm-people { flex-direction: row; justify-content: center; align-items: flex-start;
    gap: clamp(2.25rem, 5vw, 4.75rem); padding: 1.4rem 0 .6rem; }
  /* padding-top = (Bildhöhe Lead 347px − Flanke 233px) / 2: die Bildmitten der
     Flanken liegen dadurch exakt auf der Bildmitte des Ansprechpartners,
     unabhängig davon, wie viele Zeilen die Rollenbezeichnung darunter braucht. */
  .tm-person { display: block; text-align: center; max-width: 215px; padding-top: 3.5rem; }
  .tm-person-lead { order: 0; max-width: 285px; padding-top: 0; }
  .tm-person .tm-photo { width: 175px; margin: 0 auto 1.05rem; }
  .tm-person-lead .tm-photo { width: 260px; }
  .tm-person-name { font-size: 1.05rem; }
  .tm-person-lead .tm-person-name { font-size: 1.25rem; }
}

/* ── Tier 3, Auftakt: überlappende Gesichter als Vorschau des Registers */
.tm-cluster { display: flex; align-items: center; gap: 1.15rem; flex-wrap: wrap; margin: 0 0 2.1rem; }
.tm-faces { display: flex; flex: none; }
.tm-face { width: 46px; height: 46px; border-radius: 50%; overflow: hidden; flex: none;
  position: relative; border: 2px solid #020617; margin-left: -13px; transition: transform .25s ease; }
.tm-face:first-child { margin-left: 0; }
.tm-face img { width: 100%; height: 100%; object-fit: cover; object-position: center 25%; display: block; }
@media (hover: hover) { .tm-face:hover { transform: translateY(-4px) scale(1.08); z-index: 2; } }
.tm-cluster-text { color: #94a3b8; font-size: .88rem; line-height: 1.6; max-width: 46rem; }
.tm-cluster-text b { color: #fff; font-weight: 600; }

/* ── Tier 3: Dozenten-Register — Zeilen statt Karten.
   Mobil sitzt nur der Kopf neben dem Portrait, der Fließtext bekommt die volle
   Breite; eine durchgehende Portraitspalte hätte ihn auf 5–6 Wörter je Zeile
   gequetscht. Ab 760px kommt der Nummern-Gutter dazu. */
/* Zweispaltiges Raster statt einer langen Liste. Trenner bleiben Haarlinien —
   keine Kästen: horizontal je Eintrag, vertikal über border-left der rechten
   Spalte. 7 Dozenten + CTA = 8 Zellen = 4 volle Reihen. */
.tm-roster { border-top: 1px solid var(--tm-line); display: grid; grid-template-columns: 1fr; }
@media (min-width: 900px) {
  .tm-roster { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* 40px Luft auf beiden Seiten der Trennlinie; ohne padding-right stieß der
     Text der linken Spalte direkt an die Linie (gemessen: 0px). */
  .tm-roster > .tm-row { padding-left: 1.25rem; }   /* Rinne für die Hover-Schiene */
  .tm-roster > :nth-child(odd) { padding-right: 2.5rem; }
  .tm-roster > :nth-child(even) { border-left: 1px solid var(--tm-line); padding-left: 2.5rem; }
  .tm-roster > :nth-child(even)::before { left: 1.25rem; }   /* Schiene neben, nicht auf der Linie */
  /* ungerade Anzahl: der letzte Eintrag nimmt beide Spalten, sonst klafft unten
     rechts eine leere Zelle und die Schlusslinie endet auf halber Breite */
  .tm-roster > .tm-row:last-child:nth-child(odd) { grid-column: 1 / -1; padding-right: 0; }
}
.tm-row { position: relative; display: grid; grid-template-columns: 68px minmax(0, 1fr);
  grid-template-areas: "photo head" "body body";
  gap: .85rem 1.1rem; padding: 1.9rem 0;
  border-bottom: 1px solid var(--tm-line);
  /* start, nicht stretch: die Zelle ist so hoch wie die höhere Nachbarzelle, und
     stretch verteilt diesen Überschuss auf die auto-Zeilen — dadurch wuchs die
     Kopfzeile und der Abstand Name→Zitat schwankte zwischen 14 und 51px. */
  align-content: start; }
/* Akzentschiene (::before) und Hintergrund-Wash (::after) animieren beide nur
   transform bzw. opacity — das läuft im Compositor, ohne Layout oder Repaint.
   Der Wash MUSS über ein Pseudoelement laufen: als background-image auf .tm-row
   wäre er nicht animierbar (Gradient von `none` aus interpoliert nicht) und
   würde hart anspringen. z-index:-1 hält ihn hinter dem Text.
   Kein will-change: die Layer entstehen nur während des Hovers, und auf
   Touch-Geräten greift der ganze Block wegen (hover:hover) ohnehin nicht. */
.tm-row::before, .tm-row::after { content: ""; position: absolute; pointer-events: none;
  transition: transform .35s ease, opacity .3s ease; }
.tm-row::before { left: 0; top: 0; bottom: 0; width: 2px;
  background: linear-gradient(180deg, var(--tm-acc), rgba(63,168,245,.2));
  transform: scaleY(0); transform-origin: top; }
.tm-row::after { inset: 0; z-index: -1; opacity: 0;
  background: linear-gradient(90deg, rgba(63,168,245,.055), transparent 55%); }
@media (hover: hover) {
  .tm-row:hover::before { transform: scaleY(1); }
  .tm-row:hover::after { opacity: 1; }
  .tm-row:hover .tm-photo img { transform: scale(1.05); }
}
.tm-row .tm-photo { grid-area: photo; align-self: start; width: 68px; height: 68px; }
.tm-row-head { grid-area: head; align-self: center; display: flex; flex-direction: column; gap: .25rem; }
.tm-row-body { grid-area: body; display: grid; gap: .85rem; align-content: start; }
.tm-row-main, .tm-row-side { display: grid; gap: .8rem; align-content: start; }
.tm-row-name { font-family: var(--font-heading); font-weight: 700; color: #fff; font-size: 1.15rem; }
.tm-title { color: var(--tm-acc); font-size: .72rem; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; line-height: 1.35; }
.tm-title-sub { color: #94a3b8; font-size: .74rem; }
.tm-cite { border-left: 2px solid rgba(63,168,245,.35); padding-left: .85rem;
  color: #cbd5e1; font-size: .84rem; font-style: italic; line-height: 1.55; }
.tm-cite cite { display: block; font-style: normal; color: #94a3b8; font-size: .72rem; margin-top: .3rem; }
.tm-bio { color: #94a3b8; font-size: .85rem; line-height: 1.65; max-width: 62ch; }
.tm-tags { display: flex; flex-wrap: wrap; gap: .4rem; list-style: none; padding: 0; margin: 0; }
.tm-tags li { font-size: .7rem; padding: .28rem .62rem; border-radius: 999px; color: #9fd0f7;
  background: rgba(63,168,245,.1); border: 1px solid rgba(63,168,245,.2); }

@media (min-width: 760px) {
  /* 136px = alte Nummernspalte (2.75rem) + Spalten-Gap + 92px-Portrait —
     die Textspalte behält dadurch exakt ihre Breite. */
  .tm-row { grid-template-columns: 136px minmax(0, 1fr);
    grid-template-areas: "photo head" "photo body"; gap: .9rem 1.4rem; }
  .tm-row .tm-photo { width: 136px; height: 136px; }
  /* oben verankert statt zentriert: das Portrait spannt beide Rasterzeilen, bei
     kürzerem Text dehnt sich sonst die Kopfzeile und der Name rutscht nach
     unten — dann stehen die Namen der beiden Spalten nicht auf einer Linie. */
  .tm-row-head { flex-direction: row; align-items: baseline; gap: .3rem .8rem;
    flex-wrap: wrap; align-self: start; }
}
/* Kein rechter Rail mehr: bei zwei Spalten ist die Zelle dafür zu schmal,
   die Schwerpunkte stehen unter dem Fließtext. */

/* Aufklappbare Vita — native <details>, kein JS */
.tm-more { border-top: 1px solid var(--tm-line); padding-top: .9rem; margin-top: .2rem; }
.tm-more summary { display: flex; align-items: center; gap: .55rem; cursor: pointer;
  list-style: none; color: #cbd5e1; font-size: .78rem; font-weight: 600;
  transition: color .2s ease; width: fit-content; }
.tm-more summary::-webkit-details-marker { display: none; }
.tm-more summary::after { content: ""; width: 7px; height: 7px; flex: none;
  border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg) translateY(-2px); transition: transform .25s ease; }
.tm-more[open] summary::after { transform: rotate(-135deg) translateY(-2px); }
.tm-more summary:hover, .tm-more summary:focus-visible { color: #fff; }
.tm-more-body { display: grid; gap: 1.15rem; margin-top: 1rem; }
.tm-blk h5 { font-size: .67rem; letter-spacing: .16em; text-transform: uppercase;
  color: #94a3b8; font-weight: 600; margin: 0 0 .6rem; }
.tm-steps, .tm-certs { list-style: none; padding: 0; margin: 0; display: grid; }
.tm-steps { gap: .6rem; }
.tm-certs { gap: .42rem; }
.tm-steps li, .tm-certs li { position: relative; padding-left: 1.05rem;
  font-size: .79rem; color: #94a3b8; line-height: 1.5; }
.tm-steps li::before { content: ""; position: absolute; left: 0; top: .5em; width: 5px;
  height: 5px; border-radius: 50%; background: rgba(63,168,245,.75); }
.tm-steps b { display: block; color: #e2e8f0; font-weight: 600; }
.tm-certs li::before { content: "✓"; position: absolute; left: 0; top: -.05em;
  color: rgba(63,168,245,.85); font-size: .74rem; }
/* Fließtext-Block (nur dort, wo das Deck keine Stationen/Zertifikate hergibt) */
.tm-prose p { color: #94a3b8; font-size: .82rem; line-height: 1.7; max-width: 72ch; }
.tm-prose p + p { margin-top: .7rem; }
@media (min-width: 700px) {
  .tm-more-body { grid-template-columns: 1fr 1fr; column-gap: 2.25rem; align-items: start; }
  /* ein einzelner Block würde sonst in der linken Spalte kleben */
  .tm-more-body.is-single { grid-template-columns: 1fr; }
}

/* Einziger Kasten der Section: der Handlungsaufruf */
.tm-cta { margin-top: 2.25rem; border: 1px solid rgba(63,168,245,.26); border-radius: 18px;
  align-self: start;
  padding: 1.6rem; display: flex; flex-direction: column; gap: 1.15rem;
  background: linear-gradient(135deg, rgba(32,102,174,.22), rgba(63,168,245,.07) 55%, rgba(255,255,255,.02)); }
.tm-role { display: inline-flex; align-items: center; gap: .55rem; font-size: .68rem;
  font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--tm-acc); }
.tm-role::before { content: ""; width: 20px; height: 1px; background: currentColor; }
.tm-cta-title { font-family: var(--font-heading); font-weight: 700; color: #fff;
  font-size: 1.15rem; line-height: 1.35; margin: .55rem 0 .5rem; }
.tm-cta-actions { display: flex; flex-wrap: wrap; gap: .6rem; flex: none; }
.tm-btn { display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
  border-radius: 12px; padding: .72rem 1.15rem; font-size: .82rem; font-weight: 600;
  text-decoration: none; white-space: nowrap; color: #e2e8f0;
  border: 1px solid rgba(255,255,255,.16);
  transition: background-color .25s ease, border-color .25s ease, color .25s ease; }
.tm-btn:hover, .tm-btn:focus-visible { border-color: var(--tm-acc); color: #fff;
  background: rgba(63,168,245,.1); }
.tm-btn.is-primary { background: #2066ae; border-color: #2066ae; color: #fff; }
.tm-btn.is-primary:hover, .tm-btn.is-primary:focus-visible { background: #185a8e; border-color: #185a8e; }
@media (min-width: 1000px) {
  .tm-cta { flex-direction: row; align-items: center; justify-content: space-between;
    gap: 2rem; padding: 1.85rem 2rem; }
  .tm-cta-actions { flex-direction: column; }
}

/* Die Section ist lang — bessere erste Höhenschätzung für das mobile
   content-visibility:auto weiter oben, damit das Scrollen nicht springt. */
@media (max-width: 1024px) { #team { contain-intrinsic-size: auto 4200px; } }

/* ============================================================
   KI-Kennzeichnung (Werberichtlinie 4.6)
   Das Label muss AM Bild sitzen — ein Sammelhinweis im Impressum
   oder in der Datenschutzerklärung genügt ausdrücklich nicht.
   Gekennzeichnet werden nur fotorealistische KI-Bilder und
   stockartige KI-Menschen. Illustrationen, Grafiken und Icons
   bekommen keins; Team- und Standortfotos müssen echt sein.

   Einsatz: als Geschwister direkt nach dem <img> in dessen
   position:relative-Wrapper.
     <span class="ki-label">KI-generiert</span>

   Zwei Wortlaute, bewusst nicht austauschbar:
     „KI-generiert"  — vollständig erzeugtes Bild, kein Foto zugrunde
                       (Heroes, Sektionsbilder, Infomaterial-Cover)
     „KI-bearbeitet" — echtes Ausgangsfoto einer echten Person, per KI
                       zum Porträt verarbeitet (nur Team, Über uns)
   Das ist keine Stilfrage: „bearbeitet" auf einem frei erzeugten Bild
   würde weniger behaupten, als tatsächlich der Fall ist.
   ============================================================ */
/* Bewusst dezent gehalten: klein, halbtransparent, ohne Rahmen. Es soll
   nicht ins Auge springen — aber lesbar bleiben, sonst ist es kein Label
   im Sinne von 4.6. Deshalb bleiben Textschatten und eine leicht dunkle
   Unterlage: nur so trägt der weiße Text auch über hellen Bildstellen. */
.ki-label {
  position: absolute;
  right: .375rem;
  bottom: .375rem;
  z-index: 10;              /* über den Gradient-Overlays der Bild-Wrapper */
  pointer-events: none;     /* darf klickbare Facades nicht blockieren */
  display: inline-block;
  padding: .1rem .3rem;
  border-radius: 4px;
  background: rgba(15, 23, 42, .38);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  color: rgba(255, 255, 255, .82);
  font-size: .5rem;
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: .03em;
  white-space: nowrap;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
}
@media (min-width: 768px) {
  .ki-label { font-size: .5625rem; right: .5rem; bottom: .5rem; }
}

/* Hero-Variante: bewusst ebenfalls unten rechts, damit die Kennzeichnung
   überall an derselben Stelle sitzt (Wunsch: einheitlich mit den
   Sektionsbildern). Der Hero ist vollflächig, deshalb etwas mehr Abstand
   zur Kante als bei den gerahmten Sektionsbildern. */
.ki-label.is-hero { top: auto; bottom: 1rem; right: 1rem; }
@media (min-width: 768px) {
  .ki-label.is-hero { bottom: 1.25rem; right: 1.5rem; }
}

/* Manche Heroes enden in einer hellen SVG-Welle (viewBox 0 0 1440 56,
   w-full h-auto → Höhe = Breite/1440*56 ≈ 3.9vw). Genau dort säße das
   Label sonst auf Weiß, und heller Text auf halbtransparentem Dunkel
   wird unlesbar. Abstand deshalb an dieselbe Skalierung hängen, dann
   bleibt es auf jeder Fensterbreite auf dem Bild. */
.ki-label.is-hero.is-above-wave { bottom: calc(3.9vw + .75rem); }

/* Bildunterschrift-Variante für Bilder, die zu klein für ein Overlay
   sind (z. B. das 104px-Cover der Infomaterial-LP). */
.ki-caption {
  display: block;
  margin-top: .35rem;
  color: #94a3b8;
  font-size: .5625rem;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: .02em;
}
.ki-caption.is-center { text-align: center; }

/* Porträt-Cluster (Über uns): die Avatare sind 32–136 px klein, ein Overlay
   wäre dort entweder unleserlich oder würde das Gesicht verdecken. Deshalb
   ein zurückhaltender Zusatz direkt an der jeweiligen Gruppe — nicht als
   Sammelhinweis, sondern beim Inhalt. Nur die großen 360-px-Porträts von
   CEO/CTO tragen das normale .ki-label. */
/* Erklärender Absatz einmal auf Über uns: dort fragt sich ein Besucher,
   wer diese Menschen sind. Beantwortet die naheliegende Sorge direkt —
   echte Kollegen, keine erfundenen Gesichter. */
.ki-note {
  margin: 1.15rem auto 0;
  max-width: none;
  color: #7c8ba1;
  font-size: .6875rem;
  line-height: 1.6;
}
/* Der Elternblock ist max-w-4xl (896px), der Container darum max-w-7xl mit
   lg:px-8. Für je 80px negativen Rand muss der Container also mindestens
   1056px breit sein → Viewport ≥ 1120px. Darunter NICHT anwenden: die
   Section hat overflow-hidden, der Text würde sonst beidseitig abge-
   schnitten statt umzubrechen. */
@media (min-width: 1120px) {
  .ki-note { margin-inline: -5rem; }
}

/* Kurzform an den kleinen Porträts (Footer, CTA-Flächen). Muss auf allen
   170 Seiten mitlaufen, deshalb bewusst eine Zeile und sehr leise. */
.ki-inline {
  margin-top: .3rem;
  color: #64748b;
  font-size: .625rem;
  font-weight: 500;
  line-height: 1.4;
}
/* Variante für Porträts, die auf dunklem Grund oder in einem
   Gradient-Overlay stehen (Footer, Webinar-Speakerkarte). */
.ki-inline.is-on-dark { color: rgba(255, 255, 255, .6); }

.tm-tier-note {
  font-size: .58rem;
  font-weight: 500;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: #64748b;
  white-space: nowrap;
}
