/* ==========================================================================
   0. SCHRIFTEN (self-hosted, DSGVO)
   Frueher via <link> von fonts.googleapis.com geladen - damit ging bei
   jedem Seitenaufruf die IP des Besuchers an Google, ohne Einwilligung.
   Die Dateien liegen jetzt unter /fonts/ und werden von der eigenen Domain
   ausgeliefert.

   League Spartan und Montserrat sind Variable Fonts: eine Datei deckt den
   ganzen Gewichtsbereich ab, deshalb steht dort "font-weight: 400 700"
   statt vier einzelner Schnitte. Barlow Condensed liefert Google als zwei
   statische Dateien, die bleiben getrennt.

   Zwei Subsets je Familie: "latin" fuer den Normalfall, "latin-ext" fuer
   Zeichen ausserhalb davon. Der Browser laedt nur, was die Seite braucht.
   ========================================================================== */
@font-face {
  font-family: "League Spartan";
  font-style: normal;
  font-weight: 700 900;
  font-display: swap;
  src: url("/fonts/league-spartan-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: "League Spartan";
  font-style: normal;
  font-weight: 700 900;
  font-display: swap;
  src: url("/fonts/league-spartan-latin-ext.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;
}

@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/fonts/montserrat-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: "Montserrat";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/fonts/montserrat-latin-ext.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;
}

@font-face {
  font-family: "Barlow Condensed";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/barlow-condensed-500-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: "Barlow Condensed";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/fonts/barlow-condensed-500-latin-ext.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;
}

@font-face {
  font-family: "Barlow Condensed";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/fonts/barlow-condensed-600-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: "Barlow Condensed";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/fonts/barlow-condensed-600-latin-ext.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;
}

/* ==========================================================================
   That's it. Marketing - Recruiting-Landingpage
   style.css
   --------------------------------------------------------------------------
   PASS 1: Fundament + Header + Hero + Footer auf das echte Marken-
   Designsystem (--ti-* Tokens) umgestellt. Sektionen 2-9 bekommen hier nur
   einen neutralen Uebergangs-Style (Brand-Typo, alternierende Flaechen) -
   ihr Feinschliff folgt in Pass 2.

   Aufbau:
     1. Design-Tokens (:root, --ti-*)
     2. Reset / Basis
     3. Typografie
     4. Layout: Container / Sektionen
     5. Buttons / Badges
     6. Header (sticky) + Scroll-Progress
     7. Hero
     8. (entfallen: mobiler Floating-CTA, September 2026 - die Nummern
        der folgenden Abschnitte bleiben stehen, damit Verweise in
        CLAUDE.md und in den Kommentaren weiter stimmen)
     9. Inhalts-Sektionen (Sektionen 2-9, neutraler Uebergangs-Style)
    9a. Portfolio: zwei gegenlaeufige Creative-Baender (reines CSS)
    10. Footer
    11. Reveal-Animationen (Progressive Enhancement)
    12. Breakpoints (min-width: 480 / 768 / 1024 / 1280)
    13. prefers-reduced-motion
   Mobil-zuerst. BEM-artige Klassennamen.
   ========================================================================== */

/* ==========================================================================
   1. DESIGN-TOKENS
   Uebernommen aus dem offiziellen Branding Guide (--ti-* Namensraum).
   Fonts werden aktuell ueber Google Fonts geladen (siehe <head>-Kommentar-
   TODO: vor Go-Live self-hosten wegen DSGVO).
   ========================================================================== */
:root {
  /* -------- Brand Core -------- */
  --ti-black:     #0E0E0E;
  --ti-ink:       #1A1A1A;
  --ti-gold:      #DC9832;
  /* Gold-Variante fuer TEXT auf hellen Flaechen: das Brand-Gold erreicht auf
     Weiss nur 2,45:1 und faellt damit unter WCAG AA. Flaechen (Buttons,
     Quadrate, Linien) behalten --ti-gold, Textakzente nutzen --ti-gold-ink
     (5,4:1 auf Weiss, 4,8:1 auf --ti-bg-alt). */
  --ti-gold-ink:  #92600F;
  --ti-paper:     #FFFFFF;
  --ti-off-white: #FAFAF8;

  /* -------- Neutrals -------- */
  --ti-n-900: #0E0E0E;
  --ti-n-800: #1A1A1A;
  --ti-n-700: #2B2B2B;
  --ti-n-600: #4A4A4A;
  --ti-n-500: #6E6E6E;
  --ti-n-400: #9A9A9A;
  --ti-n-300: #C8C8C8;
  --ti-n-200: #E5E5E3;
  --ti-n-100: #F2F2EF;
  --ti-n-050: #FAFAF8;

  /* -------- Semantische Vordergrund-/Hintergrundfarben (hell) -------- */
  --ti-bg:       var(--ti-paper);
  --ti-bg-alt:   var(--ti-n-100);
  --ti-fg:       var(--ti-n-900);
  --ti-fg-2:     var(--ti-n-600);
  --ti-fg-3:     var(--ti-n-500);
  --ti-fg-muted: var(--ti-n-400);
  --ti-line:     var(--ti-n-200);
  --ti-accent:   var(--ti-gold);

  /* -------- Ergebnis-Gruen (Kennzahlen in den Case-Kacheln) --------
     Gold bleibt die Markenfarbe und signiert den Stempel; Gruen markiert
     ausschliesslich belegte Ergebniszahlen (besetzte Stellen, Kosten pro
     Bewerbung). Drei Varianten, weil eine Farbe nicht auf beiden Flaechen
     lesbar ist: --ti-green fuer Flaechen, --ti-green-ink fuer Text auf
     Hell (5,8:1), --ti-green-fg fuer Text auf Schwarz (8,7:1). */
  --ti-green:     #2F8F5F;
  --ti-green-ink: #20734C;
  --ti-green-fg:  #4CC38A;

  /* -------- Semantische Statusfarben -------- */
  --ti-success: #2F8F5F;
  --ti-warning: #DC9832;
  --ti-danger:  #C4382C;
  --ti-info:    #2B6CB0;

  /* -------- Type-Familien -------- */
  --ti-display: "League Spartan", "Helvetica Neue", Arial, sans-serif;
  --ti-sans:    "Montserrat", "Helvetica Neue", Arial, sans-serif;
  --ti-label:   "Barlow Condensed", "Montserrat", "Helvetica Neue", Arial, sans-serif;
  --ti-mono:    ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  /* -------- Type-Skala -------- */
  /* Hero. ACHTUNG bei Aenderungen: Der mittlere Wert muss beim Minimum
     ANSETZEN, sonst ist das Minimum unerreichbar. Vorher stand hier
     "4rem + 3vw" - das ergab schon bei 320px Viewport 73,6px, das Minimum
     von 2,5rem hat nie gegriffen und die Hero-Zeile lief auf dem Handy
     ueber sechs Zeilen. Jetzt linear 44px @375px -> 96px @1440px. */
  --ti-fs-display-xl: clamp(2.75rem, 1.6rem + 4.9vw, 6rem);
  --ti-fs-display-l:  clamp(2.75rem, 6vw, 5.5rem);
  /* Die Minima greifen nur auf dem Handy (display-m bis ca. 620px, h2 bis
     ca. 1000px). Dort liegen ALLE Sektions-Headlines auf einer Stufe:
     Hero 45px -> jede h2 26px -> h3 22px -> Fliesstext 16px. Vorher standen
     zwei h2-Stufen nebeneinander (36px und 28px) - zu dicht beieinander und
     beide zu gross, lange Headlines liefen ueber drei und mehr Zeilen.
     Die 26px sind das Maximum, bei dem "Bewerbungen generieren." im
     Portfolio bei 375px Viewport noch in eine Zeile passt (gemessen: 27px).
     Ab Tablet uebernehmen die vw-Werte und die Stufen laufen wieder
     auseinander. Ab ca. 1080px sind die Groessen identisch mit vorher,
     dazwischen (Tablet) sind die Headlines etwas kleiner als bisher. */
  --ti-fs-display-m:  clamp(1.625rem, 4.2vw, 4rem);
  --ti-fs-h1:         clamp(2rem, 3.4vw, 3rem);
  /* Seit 2026-10-26 dieselbe Formel wie --text-h2 der uebrigen Leistungsseiten
     (Kundenwunsch: alle Abschnittsheadlines gleich gross), vorher
     clamp(1.625rem, 2.6vw, 2.25rem). */
  --ti-fs-h2:         clamp(1.875rem, 3.1vw, 2.75rem);
  --ti-fs-h3:         1.375rem;
  /* Betonte h3 (z. B. Firmenname in einer Case-Akte). Liegt bewusst unter
     --ti-fs-h2 - eine h3 darf ihre eigene h2 nicht ueberragen. */
  --ti-fs-h3-display: clamp(1.5rem, 1.32rem + 0.75vw, 2rem);
  --ti-fs-h4:         1.125rem;
  --ti-fs-body-l:     1.125rem;
  --ti-fs-body:       1rem;
  --ti-fs-body-s:     0.875rem;
  --ti-fs-caption:    0.75rem;
  --ti-fs-label:      0.75rem;

  /* -------- Spacing (4px-Raster) -------- */
  --ti-s-1: 0.25rem;  /* 4px */
  --ti-s-2: 0.5rem;   /* 8px */
  --ti-s-3: 0.75rem;  /* 12px */
  --ti-s-4: 1rem;     /* 16px */
  --ti-s-5: 1.5rem;   /* 24px */
  --ti-s-6: 2rem;     /* 32px */
  --ti-s-7: 3rem;     /* 48px */
  --ti-s-8: 4rem;     /* 64px */
  --ti-s-9: 6rem;     /* 96px */
  --ti-s-10: 8rem;    /* 128px */

  /* -------- Radien (Marke ist scharf; das Logo-Quadrat ist ein Rechteck) -------- */
  --ti-r-0: 0px;
  --ti-r-1: 2px;
  --ti-r-2: 4px;
  --ti-r-3: 8px;
  --ti-r-pill: 999px;

  /* -------- Schatten -------- */
  --ti-shadow-1: 0 1px 2px rgba(14, 14, 14, .06), 0 1px 1px rgba(14, 14, 14, .04);
  --ti-shadow-2: 0 4px 12px rgba(14, 14, 14, .08), 0 1px 2px rgba(14, 14, 14, .06);
  --ti-shadow-3: 0 12px 32px rgba(14, 14, 14, .12), 0 2px 6px rgba(14, 14, 14, .06);
  --ti-shadow-gold: 0 6px 18px rgba(220, 152, 50, .32);

  /* -------- Motion -------- */
  --ti-ease-standard: cubic-bezier(.2, .7, .2, 1);
  --ti-ease-entrance: cubic-bezier(.16, .84, .3, 1);
  --ti-dur-fast: 120ms;
  --ti-dur-base: 200ms;
  --ti-dur-slow: 360ms;

  /* -------- Signatur-Winkel (Flag-Cuts) -------- */
  --ti-angle: 18deg;
  --ti-clip-flag-right: polygon(0 0, 100% 0, calc(100% - 72px) 100%, 0 100%);
  --ti-clip-flag-left:  polygon(72px 0, 100% 0, 100% 100%, 0 100%);

  /* -------- Layout (seitenspezifisch, kein Brand-Token) -------- */
  --container-max: 1200px;
  --section-py: clamp(3rem, 8vw, 6rem);

  /* -------- Header-Hoehen (Scroll-Offset / Verdichtung ohne Layout-Shift) -------- */
  --header-h: 4.75rem;
  --header-h-scrolled: 3.75rem;

  /* -------- Semantische z-index-Skala (statt 999/9999) -------- */
  --z-base: 0;
  --z-scene: 1;
  --z-content: 2;
  --z-header: 100;
  --z-progress: 110;
  /* Die Einwilligung liegt ueber allem: solange die Frage offen ist, darf
     sie nicht vom Sticky-Header verdeckt werden. */
  --z-consent: 120;
  --z-consent-modal: 130;
}

/* ==========================================================================
   2. RESET / BASIS
   ========================================================================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Verhindert, dass Anker-Ziele hinter dem Sticky-Header verschwinden. */
  scroll-padding-top: var(--header-h);
  overflow-x: hidden;
  overflow-x: clip;
}

body {
  margin: 0;
  font-family: var(--ti-sans);
  font-size: var(--ti-fs-body);
  line-height: 1.6;
  font-weight: 400;
  color: var(--ti-fg);
  background-color: var(--ti-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  /* Kein horizontales Scrollen durch dekorative Overflows. Seit 2026-10-28
     mit `clip` am Wurzelelement (siehe html oben) statt `hidden` am Body:
     `hidden` am Body macht ihn auf iOS zum Scrollcontainer, die klebende
     Kopfleiste scrollte dann einfach mit weg. */
}

img,
picture,
svg {
  max-width: 100%;
  height: auto;
  display: block;
}

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

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

/* Sichtbarer, konsistenter Fokus-Ring (Barrierefreiheit). */
:focus-visible {
  outline: 3px solid var(--ti-gold);
  outline-offset: 3px;
  border-radius: var(--ti-r-1);
}

:focus {
  outline-color: var(--ti-gold);
}

/* Skip-Link: liegt ausserhalb des Bildes, bis er Fokus bekommt. Bewusst
   NICHT per display/visibility versteckt - beides nimmt das Element aus der
   Tab-Reihenfolge und macht den Link damit wirkungslos. */
.skip-link {
  position: fixed;
  top: var(--ti-s-3);
  left: var(--ti-s-3);
  z-index: 200;
  padding: var(--ti-s-3) var(--ti-s-5);
  background-color: var(--ti-gold);
  color: var(--ti-ink);
  font-family: var(--ti-label);
  font-size: var(--ti-fs-body-s);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border-radius: var(--ti-r-2);
  transform: translateY(calc(-100% - var(--ti-s-4)));
  transition: transform var(--ti-dur-base) var(--ti-ease-standard);
}

.skip-link:focus-visible {
  transform: translateY(0);
}

/* ==========================================================================
   3. TYPOGRAFIE
   Globale Element-Regeln entsprechen dem Branding Guide 1:1 - dadurch
   erhalten auch die unveraenderten Sektionen 2-9 automatisch die richtige
   Marken-Typo, ohne dass ihr HTML angefasst werden muss.
   ========================================================================== */
h1, h2 {
  font-family: var(--ti-display);
  font-weight: 900;
  margin: 0 0 var(--ti-s-4);
  color: var(--ti-fg);
  text-wrap: balance;
}

h1 {
  font-size: var(--ti-fs-h1);
  line-height: 1.04;
  letter-spacing: -0.015em;
}

h2 {
  font-size: var(--ti-fs-h2);
  line-height: 1.08;
  letter-spacing: -0.01em;
}

h3, h4 {
  font-family: var(--ti-sans);
  font-weight: 700;
  margin: 0 0 var(--ti-s-3);
  color: var(--ti-fg);
  text-wrap: balance;
}

h3 {
  font-size: var(--ti-fs-h3);
  line-height: 1.25;
}

h4 {
  font-size: var(--ti-fs-h4);
  line-height: 1.3;
}

p {
  margin: 0 0 var(--ti-s-4);
  max-width: 65ch;
  text-wrap: pretty;
}

strong {
  font-weight: 700;
  color: var(--ti-fg);
}

small,
.text-small {
  font-size: var(--ti-fs-body-s);
}

/* Textakzent auf hellem Grund: --ti-gold erreicht dort nur 2,45:1 und
   verfehlt WCAG AA. --ti-gold-ink sieht bei gleicher Groesse fast identisch
   aus und liegt bei 5,8:1. Auf Schwarz (Hero, #cases, Abschluss) bleibt das
   helle Gold, dort stimmt der Kontrast. */
.u-gold {
  color: var(--ti-gold-ink);
}

/* Tracked Label/Eyebrow-Stil (sparsam einsetzen, siehe Impeccable-Regeln). */
.ti-label {
  font-family: var(--ti-label);
  font-weight: 500;
  font-size: var(--ti-fs-label);
  letter-spacing: 0.3em;
  text-transform: uppercase;
}

/* Der orangene quadratische Punkt: Markensignatur. Schliesst die Wortmarke,
   signiert Ueberschriften, akzentuiert CTAs. CSS-Quadrat, kein Zeichen.

   Groesse in em, damit der Punkt in jeder Schriftgroesse dasselbe Verhaeltnis
   zum Text haelt. Der leere Inline-Block hat seine Baseline an der unteren
   Rand-Kante: mit vertical-align: baseline und ohne Versatz sitzt die
   Unterkante des Quadrats exakt auf der Textgrundlinie. */
.dot-mark {
  display: inline-block;
  width: 0.2em;
  height: 0.2em;
  background: var(--ti-gold);
  margin-left: 0.1em;
  vertical-align: baseline;
  transform-origin: bottom center;
  flex: 0 0 auto;
}

/* ==========================================================================
   4. LAYOUT: CONTAINER / SEKTIONEN
   ========================================================================== */
.container {
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--ti-s-5);
  width: 100%;
}

.section {
  padding-block: var(--section-py);
  background-color: var(--ti-bg);
}

/* Der Punkt der Wortmarke "That's it." wird als Marken-Quadrat gezeichnet.
   Das Zeichen selbst bleibt im Text stehen und wird nur nicht dargestellt:
   der von Suchmaschinen extrahierte Text lautet damit weiterhin
   "That's it." - waere der Punkt aus dem Markup entfernt, hiesse die Marke
   im Index "That's it", und das ist eine der haeufigsten englischen
   Floskeln.
   Bewusst NICHT .visually-hidden: das ist position:absolute und macht aus
   der Zeile im gerenderten Text "That's it\n.\nMarketing". inline-block mit
   Breite 0 bleibt dagegen im Textfluss und nimmt trotzdem keinen Platz. */
.brand-dot {
  display: inline-block;
  width: 0;
  overflow: hidden;
  color: transparent;
}

.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ==========================================================================
   5. BUTTONS / BADGES
   Label-Stil (Barlow Condensed, gesperrt, uppercase), scharfe Ecken.
   Primaerer CTA: Gold-Flaeche + Gold-Glow. Der Quadrat-Punkt schiebt sich
   als Mikro-Interaktion beim Hover in den Button.
   ========================================================================== */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* KEIN gap: der Quadrat-Punkt ist im Ruhezustand 0px breit, ein gap
     wuerde trotzdem zaehlen und das Label um die halbe Luecke nach links
     schieben. Der Abstand haengt deshalb als margin-left am Punkt selbst
     und faehrt beim Hover mit aus. */
  gap: 0;
  /* min-height 44px: mit dem reinen Innenabstand kam der Button je nach
     Schriftgroesse auf 39-41px und lag damit unter der Mindestgroesse fuer
     Zeigeflaechen (WCAG 2.5.8). Die Optik aendert sich dadurch kaum, weil
     die meisten Buttons ohnehin nahe an 44px lagen. */
  min-height: 44px;
  padding: var(--ti-s-3) var(--ti-s-5);
  /* Buttons laufen in der Fliesstext-Schrift, nur in Versalien
     (Kundenwunsch September 2026) - vorher Barlow Condensed wie die
     Overlines und Badges. Die Groesse bleibt bei 0.8125rem.

     Die Sperrung geht dabei von 0.22em auf 0.14em zurueck: 0.22em war auf
     eine SCHMALE Schrift gerechnet. Montserrat ist normal breit, dieselbe
     Sperrung liesse das Label auseinanderfallen - und sie kostet auf dem
     Handy Platz, den das laengste Label ohnehin nicht hat. */
  font-family: var(--ti-sans);
  font-weight: 600;
  font-size: 0.8125rem;
  --btn-track: 0.14em;
  letter-spacing: var(--btn-track);
  /* 1.2 statt 1: das laengste Label ("Kostenloses Erstgespraech sichern")
     passt in Montserrat auf 375 px nicht mehr in eine Zeile - bei
     line-height 1 klebten die zwei Zeilen aufeinander. Einzeilige Buttons
     aendern sich dadurch nicht, deren Hoehe kommt aus min-height. */
  line-height: 1.2;
  text-transform: uppercase;
  text-align: center;
  border: 2px solid transparent;
  border-radius: var(--ti-r-1);
  cursor: pointer;
  transition:
    transform var(--ti-dur-base) var(--ti-ease-standard),
    box-shadow var(--ti-dur-base) var(--ti-ease-standard),
    background-color var(--ti-dur-base) var(--ti-ease-standard);
}

/* Der kleine Quadrat-Punkt innerhalb des Buttons: unsichtbar/breite 0 im
   Ruhezustand, schiebt sich bei Hover/Fokus sichtbar ein. */
.btn__dot {
  display: inline-block;
  width: 0;
  height: 0.55em;
  margin-left: 0;
  background: currentColor;
  opacity: 0;
  flex: 0 0 auto;
  transition:
    width var(--ti-dur-base) var(--ti-ease-standard),
    margin-left var(--ti-dur-base) var(--ti-ease-standard),
    opacity var(--ti-dur-base) var(--ti-ease-standard);
}

/* Letter-spacing haengt auch hinter dem LETZTEN Zeichen. Ohne den
   Ausgleich sitzt die Schrift um genau diesen Betrag links aus der Mitte -
   sichtbar vor allem im kompakten Header-Button. */
/* Unter 600 px eine Stufe kleiner und enger gesperrt. Das ist keine
   Kosmetik, sondern die einzige Moeglichkeit, das laengste Label
   ("Kostenloses Erstgespraech sichern") dort in EINE Zeile zu bekommen: in
   Montserrat braucht es bei 13px/0.14em 332 px, im engsten Button der Seite
   (dem CTA in einer FAQ-Antwort) stehen auf einem 360-px-Handy aber nur
   274 px zur Verfuegung. 11px/0.09em kommt auf 264 px und passt ab 360 px
   ueberall.

   Das Seitenpolster geht aus demselben Grund von 2 x 24 px auf 2 x 16 px
   zurueck. Die Mindesthoehe von 44 px bleibt unangetastet - sie ist die
   Zeigeflaeche, nicht die Optik. */
@media (max-width: 599px) {
  .btn {
    font-size: 0.75rem;
    --btn-track: 0.10em;
    padding-inline: var(--ti-s-4);
  }
}

/* Zwei Fassungen desselben Labels, umgeschaltet bei 600 px. Immer nur EINE
   steht im Render (display: none, nicht Sichtbarkeit), damit Screenreader
   den CTA nicht doppelt vorlesen - dasselbe Muster wie im Header. */
.btn__label--lang {
  display: none;
}

@media (min-width: 600px) {
  .btn__label--kurz {
    display: none;
  }

  .btn__label--lang {
    display: inline;
  }
}

.btn__label {
  margin-right: calc(-1 * var(--btn-track));
}

/* Primaerer CTA: dunkler Text auf Gold-Flaeche. Gold NIE als Fliesstext. */
.btn--cta {
  background-color: var(--ti-gold);
  color: var(--ti-black);
  box-shadow: var(--ti-shadow-gold);
}

.btn--cta .btn__dot {
  background-color: var(--ti-black);
}

.btn--cta:hover,
.btn--cta:focus-visible {
  transform: translateY(-2px) scale(1.015);
  box-shadow: 0 10px 28px rgba(220, 152, 50, .42);
}

.btn--cta:hover .btn__dot,
.btn--cta:focus-visible .btn__dot {
  width: 0.55em;
  margin-left: var(--ti-s-2);
  opacity: 1;
}

.btn--cta:active {
  transform: translateY(0) scale(1);
}

/* Fokus-Ring auf Gold-Flaeche: Standard-Gold-Outline waere unsichtbar,
   daher ein zweifarbiger Ring (Papier + Schwarz), der auf jedem
   Hintergrund (hell oder dunkel/Hero) sichtbar bleibt. */
.btn--cta:focus-visible {
  outline: none;
  box-shadow:
    0 0 0 3px var(--ti-paper),
    0 0 0 6px var(--ti-black),
    var(--ti-shadow-gold);
}

/* Ghost-Button: transparente Flaeche, dunkle Kontur. Fuer sekundaere
   Aktionen auf hellem Grund. */
.btn--ghost {
  background-color: transparent;
  color: var(--ti-fg);
  border-color: var(--ti-fg);
}

.btn--ghost:hover,
.btn--ghost:focus-visible {
  background-color: var(--ti-fg);
  color: var(--ti-paper);
}

/* Dunkler Button: Schwarze Flaeche, weisser Text. Fuer Kontexte auf Papier. */
.btn--dark {
  background-color: var(--ti-black);
  color: var(--ti-paper);
}

.btn--dark:hover,
.btn--dark:focus-visible {
  background-color: var(--ti-n-800);
}

/* Badge/Pill (kleine Statuslabels) - Pillenform ist ausschliesslich hierfuer
   reserviert, niemals fuer Buttons. */
.badge {
  display: inline-flex;
  align-items: center;
  padding: var(--ti-s-1) var(--ti-s-3);
  font-family: var(--ti-label);
  font-weight: 500;
  font-size: 0.6875rem;
  letter-spacing: 0.25em;
  text-transform: uppercase;
  border-radius: var(--ti-r-pill);
  background-color: var(--ti-n-100);
  color: var(--ti-fg);
}

/* ==========================================================================
   5b. ANKUENDIGUNGSLEISTE (kuenstliche Verknappung, ueber dem Header)
   Schwarze Leiste ganz oben, scrollt weg - der sticky Header bleibt.
   Der Satz steht in Weiss; GOLD und pulsend ist nur die Verknappung selbst
   ("2 Plaetze") plus der Marken-Quadrat-Punkt davor. Vorher lag die ganze
   Zeile in Gold - dadurch hatte die Zahl keine Hervorhebung mehr.
   ========================================================================== */
/* Block statt Flex: der Quadrat-Punkt laeuft dadurch INLINE vor dem Text mit.
   Als Flex-Geschwister klebte er auf dem Handy am linken Rand, sobald die
   Zeile umbrach, und stand dann weit weg von der Schrift. */
.announce {
  display: block;
  padding: var(--ti-s-2) var(--ti-s-5);
  background-color: var(--ti-black);
  color: rgba(255, 255, 255, 0.82);
  text-align: center;
  font-family: var(--ti-label);
  font-size: var(--ti-fs-body-s);
  letter-spacing: 0.02em;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  transition: color var(--ti-dur-base) var(--ti-ease-standard);
}

/* Der Marken-Quadrat-Punkt als Verknappungs-Indikator (pulsend). */
.announce__dot {
  display: inline-block;
  vertical-align: middle;
  margin-right: 0.5em;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 1px;
  background-color: var(--ti-gold);
  animation: tiAnnouncePulse 1.8s var(--ti-ease-standard) infinite;
}

.announce__text {
  min-width: 0;
}

.announce__accent {
  color: var(--ti-paper);
  font-weight: 600;
}

/* Die Verknappung selbst: als einziges Wortpaar in Gold und im selben Takt
   wie der Quadrat-Punkt davor - aber nur ueber die Deckkraft. Der Punkt
   skaliert zusaetzlich (tiAnnouncePulse); bei einem WORT mitten im Satz
   liest sich das Groesserwerden als Wackeln, nicht als Puls. */
.announce__pulse {
  color: var(--ti-gold);
  animation: tiTextPulse 1.8s var(--ti-ease-standard) infinite;
}

@keyframes tiTextPulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.5; }
}

@keyframes tiAnnouncePulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.55; transform: scale(0.82); }
}

/* ==========================================================================
   6. HEADER (sticky, verdichtet bei Scroll ohne Layout-Shift)
   ========================================================================== */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background-color: rgba(255, 255, 255, 0.88);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: 1px solid transparent;
  transition:
    background-color var(--ti-dur-base) var(--ti-ease-standard),
    border-color var(--ti-dur-base) var(--ti-ease-standard),
    box-shadow var(--ti-dur-base) var(--ti-ease-standard);
}

.site-header.is-scrolled {
  background-color: rgba(255, 255, 255, 0.97);
  border-bottom-color: var(--ti-line);
  box-shadow: var(--ti-shadow-1);
}

/* Duenne goldene Scroll-Fortschrittsleiste am oberen Rand. */
.scroll-progress {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background-color: transparent;
  z-index: var(--z-progress);
  pointer-events: none;
}

.scroll-progress__fill {
  height: 100%;
  width: 0%;
  background-color: var(--ti-gold);
  transform-origin: left;
}

/* Ohne JS bleibt die Leiste unsichtbar (0 Breite) statt fehlerhaft zu wirken. */

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ti-s-4);
  min-height: var(--header-h);
  padding-block: var(--ti-s-3);
  /* Bewusst min-height/padding statt transform: der Header soll beim
     Scrollen wirklich flacher werden und Platz freigeben - ein transform
     wuerde ihn nur optisch stauchen und den Platz weiter belegen. Der
     Layout-Durchlauf faellt einmal beim Ueberschreiten der Schwelle an,
     nicht in jedem Frame; das ist die Ausnahme wert. */
  transition: min-height var(--ti-dur-base) var(--ti-ease-standard), padding-block var(--ti-dur-base) var(--ti-ease-standard);
}

.site-header.is-scrolled .site-header__inner {
  min-height: var(--header-h-scrolled);
  padding-block: var(--ti-s-2);
}

/* Original-Wortmarke als Bild. Die Hoehe steuert die Groesse, die Breite
   ergibt sich aus dem Seitenverhaeltnis (592x177). */
/* Das Logo ist ein Link zum Seitenanfang und braucht deshalb dieselbe
   Mindest-Trefferflaeche wie jeder andere Link. Der negative Rand haelt
   die Bildmarke optisch an ihrer Stelle. */
.site-header__logo {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: var(--ti-s-2);
  margin-inline: calc(-1 * var(--ti-s-2));
}

.site-header__logo img {
  height: clamp(1.6rem, 3.4vw, 2.1rem);
  width: auto;
}

.site-header__logo-word {
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: clamp(1.05rem, 2.2vw, 1.35rem);
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--ti-fg);
}

.site-header__logo-sub {
  font-family: var(--ti-label);
  font-weight: 500;
  font-size: 0.6875rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--ti-fg-2);
}

.site-header__nav {
  display: flex;
  align-items: center;
}

/* Der Header-CTA steht auf JEDER Breite - mobil mit dem kurzen Label
   ("Termin sichern"), damit er neben dem Logo auch auf 375px passt. Enger
   gesetzt und etwas kleiner als der lange Button, sonst draengt er das Logo
   aus der Zeile. */
.site-header__cta {
  display: inline-flex;
  flex: 0 1 auto;
  min-width: 0;
  /* Bewusst der leiseste Button der Seite (Kundenwunsch September 2026):
     neben dem Logo sass er vorher als breiter Gold-Block und war praesenter
     als die Wortmarke selbst. Kleinere Schrift, engere Sperrung, weniger
     Seitenpolster - und das kurze Label "Termin sichern" statt
     "Erstgespraech vereinbaren".

     Die Mindesthoehe von 44 px bleibt: sie ist die Zeigeflaeche nach
     WCAG 2.5.8 und keine Frage der Optik. Kleiner wird der Knopf ueber die
     Breite, nicht ueber die Hoehe. --btn-track zieht den Ausgleich an
     .btn__label automatisch mit. */
  padding: var(--ti-s-2) var(--ti-s-4);
  font-size: 0.625rem;
  --btn-track: 0.06em;
  white-space: nowrap;
}

.site-header__cta-long {
  display: none;
}

/* ==========================================================================
   7. HERO
   Showpiece: durchgehend schwarzer Grund, gestaffelte Headline-Animation
   beim First Load, dezentes Parallax-Punktfeld.
   ========================================================================== */
.hero {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  background-color: var(--ti-black);
  color: var(--ti-paper);
  /* Kopfabstand knapp gehalten: Headline, Subheadline, Beleg und CTA
     muessen zusammen ueber die Falz passen. Auf einem 375x667-Display
     (iPhone SE) ist das die Grenze. */
  padding-block: clamp(3rem, 9vw, 8rem) 0;
  /* Gemeinsame Maximalbreite fuer Pitch und Kennzahlen, damit beide auf
     einer linken Blockkante fluchten. */
  --hero-media-w: min(100%, 44rem);
}

/* --- Dekorative Markenszene (Punktfeld + Flag-Cut) --- */
.hero__scene {
  position: absolute;
  inset: 0;
  z-index: var(--z-scene);
  pointer-events: none;
  overflow: hidden;
}

/* .hero__flag ist entfallen (Kundenwunsch August 2026): die goldene
   Flag-Cut-Flaeche lag ueber der rechten Haelfte und liess den Hero wie
   mittig zweigeteilt aussehen - links Schwarz, rechts warm getoent. Der
   Hero-Grund ist jetzt durchgehend --ti-black. */
/* Seit dem 2026-10-21 wie `components/ui/Markenquadrate.astro` der anderen
   Seiten (Kundenwunsch: Quadrate am rechten Rand waren viel zu gross):
   einzelne Kaesten mit fester Kantenlaenge, Lage in Prozent der Flaeche,
   etwas ueber die Flaeche hinaus, damit beim Mitwandern keine Luecke
   entsteht. Vorher ein SVG mit preserveAspectRatio="slice", das die
   Zeichnung mit der Hoehe des Hero hochskalierte. */
.hero__dots {
  position: absolute;
  inset: -32px;
  opacity: 0.85;
  will-change: transform;
}

.hero__dots span {
  position: absolute;
  inset-inline-start: var(--x);
  inset-block-start: var(--y);
  inline-size: var(--kante);
  block-size: var(--kante);
  background: var(--ti-gold);
  opacity: var(--deckkraft);
}

@media (max-width: 900px) {
  .hero__dots { opacity: 0.4; }
}

.hero__inner {
  position: relative;
  z-index: var(--z-content);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
}

/* Seit dem 2026-09-29 (Kundenwunsch) so gross wie die Headlines der anderen
   Leistungsseiten: dieselbe Formel wie Webdesign und Fotos & Videos
   (`components/sektionen/Hero.astro`), bis 620 Pixel deren Handyformel.
   Vorher `--ti-fs-display-xl` (44 Pixel auf 390, 66 auf 1440). */
.hero__title {
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: clamp(2rem, calc(3.77vw - 2px), 3.3rem);
  line-height: 0.96;
  letter-spacing: -0.02em;
  text-wrap: balance;
  max-width: 15ch;
  margin: 0 0 var(--ti-s-5);
  color: var(--ti-paper);
}

@media (max-width: 620px) {
  .hero__title { font-size: clamp(1.5rem, calc(10.6vw - 5px), 2.6rem); }
}

/* Wort-fuer-Wort-Stagger beim First Load. Ohne JS oder bei reduzierter
   Bewegung bleiben die Woerter direkt sichtbar (kein Verstecken hinter
   einer JS-Klasse), siehe js/main.js und Abschnitt 13. */
.hero__word {
  display: inline-block;
}

html.js .hero--animate-in .hero__word {
  opacity: 0;
  transform: translateY(18px);
}

html.js .hero--animate-in.hero--animated .hero__word {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--ti-dur-slow) var(--ti-ease-entrance),
    transform var(--ti-dur-slow) var(--ti-ease-entrance);
}

html.js .hero--animate-in.hero--animated .hero__word:nth-child(1) { transition-delay: 0ms; }
html.js .hero--animate-in.hero--animated .hero__word:nth-child(2) { transition-delay: 70ms; }
html.js .hero--animate-in.hero--animated .hero__word:nth-child(3) { transition-delay: 140ms; }
html.js .hero--animate-in.hero--animated .hero__word:nth-child(4) { transition-delay: 210ms; }
html.js .hero--animate-in.hero--animated .hero__word:nth-child(5) { transition-delay: 280ms; }

/* Der Quadrat-Punkt pulst einmalig, sobald die Headline eingeblendet ist. */
html.js .hero--animate-in.hero--animated .hero__word:last-child .dot-mark {
  animation: tiDotPulse 640ms var(--ti-ease-entrance) 620ms both;
}

@keyframes tiDotPulse {
  0%   { transform: scale(1); }
  45%  { transform: scale(1.65); box-shadow: 0 0 0 6px rgba(220, 152, 50, .28); }
  100% { transform: scale(1); box-shadow: none; }
}

/* Highlight der ersten beiden Woerter ("Planbare Bewerber") in Gold. Gold auf
   Schwarz erreicht klaren Kontrast - die Ausnahme-Regel gegen Gold-Text gilt
   nur auf hellem Grund. */
.hero__word--accent {
  color: var(--ti-gold);
}

/* --- Above-the-fold-Block: VSL-Fenster + Pitch ---
   Mobil untereinander (Fenster zuerst), ab 1024px nebeneinander. Der Pitch
   dreht seine Kinder mobil per `order` um: erst CTA, dann Bewertung, dann
   Subheadline. Im Markup steht die Lesereihenfolge (Subheadline zuerst),
   damit Screenreader und die Ansicht ohne CSS sinnvoll bleiben.

   Der Grund fuer die Drehung ist die Falz: unter Headline und 16:9-Fenster
   bleibt auf einem 375x667-Display kein Platz mehr fuer vier Zeilen
   Fliesstext VOR dem Button. Ohne das Fenster (August bis September 2026)
   war die Drehung ueberfluessig und deshalb entfernt - sie kommt mit dem
   Fenster zurueck. */
.hero__main {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--ti-s-6);
  width: 100%;
  max-width: var(--hero-media-w);
  margin-bottom: var(--ti-s-7);
}

.hero__media {
  min-width: 0;
}

.hero__pitch {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--ti-s-5);
  min-width: 0;
}

/* Die Bewertung bleibt in JEDER Reihenfolge direkt unter dem Button - der
   Beleg sitzt dort, wo geklickt wird (dieselbe Anordnung wie im
   Abschluss-CTA). Gedreht wird nur, wo die Subheadline steht. */
.hero__pitch > .hero__actions  { order: 1; }
.hero__pitch > .rating         { order: 2; }
.hero__pitch > .hero__subtitle { order: 3; }

/* Button und Microcopy stehen IMMER untereinander - auch ab 480px, wo
   .hero__actions sonst in eine Zeile kippt. Die Zeile daneben waere die
   Kleingedruckte neben dem Hauptversprechen der Seite. */
.hero__pitch > .hero__actions {
  flex-direction: column;
  align-items: flex-start;
  gap: var(--ti-s-3);
}

.hero__subtitle {
  color: rgba(255, 255, 255, 0.78);
  font-size: var(--ti-fs-body-l);
  max-width: 55ch;
  margin: 0;
}

/* --- Google-Bewertung ---
   Generische Komponente: steht im Hero-Pitch UND im Abschluss-CTA. Beide
   Flaechen sind schwarz, deshalb ist die Chrome hell auf transparent. --- */
.rating {
  /* Seit 2026-10-22 (Kundenwunsch) im Look von `ui/Siegel.astro` der anderen
     Leistungsseiten: feine Kante ohne Flaeche, kleine Ecken, Sterne in Gold,
     Text weiss in 14 Pixeln. */
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0;
  padding: 0.75rem 1rem;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 4px;
  background-color: transparent;
}

.rating__google {
  display: inline-flex;
}

.rating__google svg {
  display: block;
  width: 20px;
  height: 20px;
}

.rating__stars {
  display: inline-flex;
  gap: 0.15rem;
  color: var(--ti-gold);
}

.rating__stars svg {
  display: block;
  width: 0.85rem;
  height: 0.85rem;
  fill: currentColor;
}

.rating__text {
  font-family: 'Montserrat', 'Helvetica Neue', Arial, sans-serif;
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.2;
  color: #fff;
}

/* --- VSL-Platzhalter (16:9) ---
   Der Rahmen haelt das Seitenverhaeltnis selbst (aspect-ratio), damit beim
   Einsetzen des echten Videos nichts springt: das Embed erbt die Flaeche,
   die der Platzhalter schon belegt. --- */
.hero__vsl {
  width: 100%;
  max-width: var(--hero-media-w);
  margin: 0;
}

.hero__vsl-frame {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--ti-s-3);
  aspect-ratio: 16 / 9;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--ti-r-3);
  background:
    radial-gradient(120% 120% at 50% 0%, rgba(220, 152, 50, 0.12), transparent 62%),
    rgba(255, 255, 255, 0.03);
  overflow: hidden;
}

/* Bewusst rund und nicht das Marken-Quadrat: das hier ist ein
   Wiedergabe-Zeichen und kein Marken-Akzent. Der orangene Punkt bleibt der
   Wortmarke und den Headlines vorbehalten. */
.hero__vsl-play {
  position: relative;
  width: clamp(3.25rem, 8vw, 4.5rem);
  aspect-ratio: 1;
  border-radius: 50%;
  background-color: var(--ti-gold);
}

.hero__vsl-play::before {
  content: "";
  position: absolute;
  top: 50%;
  /* 54 % statt 50 %: ein Dreieck sitzt optisch links von seiner Mitte. */
  left: 54%;
  transform: translate(-50%, -50%);
  border-style: solid;
  border-width: 0.55rem 0 0.55rem 0.95rem;
  border-color: transparent transparent transparent var(--ti-black);
}

.hero__vsl-label {
  font-family: var(--ti-label);
  font-size: var(--ti-fs-label);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72);
}

/* --- VSL im Hero: Zwei-Klick-Einbettung im 16:9-Rahmen (2026-10-08) ---
   Ohne Poster (kein Bild von YouTube vor der Einwilligung): der Rahmen
   behaelt Rand und goldenen Schimmer, der Schleier liegt mittig statt als
   Verlauf von unten. Der Knopf zieht per ::after die ganze Flaeche auf sich,
   damit ein Klick irgendwo im Fenster den Player startet. Der Iframe, der
   den Block ersetzt, erbt Breite und Hoehe vom Rahmen. --- */
.hero__vsl-frame > .video-consent { flex: 1 1 auto; }

.hero__vsl-frame > .case__video--embed {
  position: absolute;
  inset: 0;
}

.video-consent--vsl .video-consent__veil {
  justify-content: center;
  background: none;
}

.video-consent--vsl .video-consent__btn--vsl {
  flex-direction: column;
  gap: var(--ti-s-3);
  min-height: 0;
  padding: 0;
  background: none;
  color: rgba(255, 255, 255, 0.92);
}

.video-consent--vsl .video-consent__btn--vsl::after {
  content: "";
  position: absolute;
  inset: 0;
}

.video-consent--vsl .video-consent__btn--vsl:hover,
.video-consent--vsl .video-consent__btn--vsl:focus-visible {
  transform: none;
  box-shadow: none;
}

.video-consent--vsl .video-consent__btn--vsl .hero__vsl-play {
  transition: transform var(--ti-dur-base) var(--ti-ease-standard),
    box-shadow var(--ti-dur-base) var(--ti-ease-standard);
}

.video-consent--vsl .video-consent__btn--vsl:hover .hero__vsl-play,
.video-consent--vsl .video-consent__btn--vsl:focus-visible .hero__vsl-play {
  transform: scale(1.06);
  box-shadow: 0 10px 28px rgba(220, 152, 50, 0.42);
}

.video-consent--vsl .video-consent__btn--vsl:focus-visible {
  outline: 2px solid var(--ti-gold);
  outline-offset: -6px;
}

/* --- Kennzahlen-Band unter dem Above-the-fold-Block (dunkle Variante von
   .stat-grid). Ab 1024px laeuft es ueber die volle Containerbreite unter
   dem Pitch. --- */
.hero__stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  width: 100%;
  max-width: var(--hero-media-w);
  margin: 0;
  border-top: 2px solid rgba(255, 255, 255, 0.2);
}

.hero__stat {
  padding: var(--ti-s-4) var(--ti-s-3) 0 0;
}

.hero__stat + .hero__stat {
  padding-left: var(--ti-s-3);
  border-left: 1px solid rgba(255, 255, 255, 0.12);
}

.hero__stat-value {
  font-family: var(--ti-display);
  font-size: clamp(1.5rem, 6vw, 2.75rem);
  font-weight: 900;
  line-height: 0.95;
  letter-spacing: -0.02em;
  color: var(--ti-gold);
  margin: 0 0 var(--ti-s-2);
  font-variant-numeric: tabular-nums;
}

.hero__stat-label {
  margin: 0;
  font-weight: 600;
  font-size: 0.8125rem;
  line-height: 1.3;
  color: var(--ti-paper);
}

.hero__stat-note {
  margin: var(--ti-s-2) 0 0;
  font-size: 0.75rem;
  line-height: 1.35;
  color: rgba(255, 255, 255, 0.58);
  /* Auf dem Handy stehen nur Wert + Label (wie in der Vorlage); die Notiz
     wuerde in drei schmalen Spalten mehrzeilig brechen. Ab Tablet sichtbar. */
  display: none;
}

.hero__actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--ti-s-3);
  margin-bottom: 0;
}

.hero__cta {
  width: 100%;
  cursor: pointer;
}

.hero__cta-note {
  margin: 0;
  font-size: var(--ti-fs-body-s);
  color: rgba(255, 255, 255, 0.6);
}

/* --- Full-Width-Kundenlogo-Slider (zwei gegenlaeufige Zeilen) ---
   Nutzt dieselbe Marquee-Mechanik wie die Portfolio-Baender. Je Zeile stehen
   12 Logos in einer Gruppe, dahinter die aria-hidden Kopie. Gruppenbreite =
   12 * (--logo-w + --logo-gap); mobil 12 * (156px + 32px) = 2256px, ab 768px
   12 * (176px + 64px) = 2880px. **Seit 2026-09-28 einheitlich mit allen
   Logo-Slidern der Website** (siehe `src/components/ui/Logoslider.astro`):
   mobil 156px breit im Format 3:1, also 52px hoch wie auf der Webdesign-Seite
   (vorher 128px, 42,7px hoch), ab 768px unveraendert 176px, also 58,67px. Die Dauer ist so gesetzt, dass beide Stufen
   rund 49px/s laufen - dasselbe Tempo wie die Creatives. Wer --logo-w oder
   --logo-gap aendert, muss die Dauer mitziehen (Dauer = Gruppenbreite / 49).
   --reel-speed-1 treibt die linke Zeile, --reel-speed-2 (via .marquee--right)
   die rechte; beide gleich schnell, nur gegenlaeufig. */
.hero__logos {
  --reel-speed-1: 46s;
  --reel-speed-2: 46s;
  --logo-w: 9.75rem;
  --logo-gap: 2rem;
  /* Der Streifen liegt als HELLE Flaeche im schwarzen Hero (Kundenwunsch
     September 2026). Vorher liefen die Logos als weisse Silhouette direkt
     auf Schwarz - das war zwar einheitlich, nahm ihnen aber die Farbe.
     Auf Weiss duerfen sie ihre eigene behalten.

     z-index ist hier kein Feinschliff, sondern eine Fehlerbehebung: das
     goldene Punktfeld .hero__dots ist absolut positioniert (rechte 68 % des
     Hero) und lag damit VOR den Logos - die Marken-Quadrate schnitten
     sichtbar in die rechten Logos. Ein positionierter Kasten mit z-index
     legt den Streifen wieder darueber. */
  position: relative;
  z-index: var(--z-content);
  display: grid;
  gap: var(--ti-s-4);
  width: 100%;
  margin-top: clamp(2.5rem, 6vw, 4rem);
  padding-top: clamp(2rem, 4vw, 3rem);
  padding-bottom: clamp(2rem, 4vw, 3rem);
  background-color: var(--ti-paper);
}

.hero__logos .marquee__group {
  gap: var(--logo-gap);
  padding-right: var(--logo-gap);
  align-items: center;
}

.hero__logo {
  flex: 0 0 auto;
  width: var(--logo-w);
}

/* Keine Kachel, kein Filter, keine gedaempfte Deckkraft: die Logos stehen
   in ihrer eigenen Farbe auf der weissen Flaeche. Volle Deckkraft ist hier
   Absicht - jede Abschwaechung geht auf einem hellen Grund direkt vom
   Kontrast der ohnehin hellen Logos ab.

   Damit das aufgeht, muessen die Dateien "dunkel auf hell" sein. Vier
   Logos waren es nicht (12, 22, 23, 24: weisse Schrift bzw. helle Linien
   auf weisser Flaeche) und sind beim Import umgerechnet worden - siehe
   CLAUDE.md, Abschnitt "Kundenlogo-Slider". */
.hero__logo img {
  display: block;
  width: 100%;
  height: auto;
}

/* ==========================================================================
   9. INHALTS-SEKTIONEN (Sektionen 2-9)
   Neutraler Uebergangs-Style: alternierende Papier-/Off-White-Flaechen,
   Brand-Typo, zurueckhaltende Karten ohne Farbverlauf oder Seitenkanten-
   Akzent. Der inhaltliche Feinschliff folgt in Pass 2 - hier geht es nur
   darum, dass die Seite zwischen Hero und Footer nicht bricht.
   ========================================================================== */
.section--alt {
  background-color: var(--ti-bg-alt);
  border-block: 1px solid var(--ti-line);
}

/* Sektion auf Schwarz - dieselbe Flaeche wie Hero, Funnel-Showcase und
   Abschluss-CTA. Kundenwunsch September 2026 fuer #warum-wir und
   #so-funktioniert-es.

   Die Klasse setzt nur Flaeche und Textfarben. Alles, was innen eine eigene
   helle Flaeche hat (Karten, Icon-Quadrate, die Linie im Ablauf), wird bei
   der jeweiligen Komponente umgestellt - sonst stuende hier eine Liste
   fremder Selektoren, die beim naechsten Umbau niemand mitzieht.

   Kein border-block wie bei --alt: auf Schwarz trennt schon die Flaeche. */
.section--dark {
  background-color: var(--ti-black);
  color: var(--ti-paper);
}

.section--dark h2,
.section--dark h3 {
  color: var(--ti-paper);
}

/* Auf Schwarz traegt das Brand-Gold selbst: #DC9832 auf #0E0E0E sind 7,6:1.
   --ti-gold-ink ist die Variante fuer HELLE Flaechen und kaeme hier auf
   2,7:1 - also genau verkehrt herum. */
.section--dark .section__overline {
  color: var(--ti-gold);
}

/* Dieselbe Textfarbe wie im Abschluss-CTA, damit die drei schwarzen
   Flaechen der Seite gleich klingen. */
.section--dark .section__intro {
  color: rgba(255, 255, 255, 0.75);
}

/* Dunkle Sektion mit Foto darunter (Kundenwunsch September 2026 fuer #team:
   ein Bild aus dem eigenen Buero statt einer leeren Flaeche).

   Das Foto liegt NICHT allein da: darueber steht ein schwarzer Verlauf von
   82 % auf 90 % Deckung. Bei 82 % kommt die hellste textgrosse Stelle des
   Bildes (195, 152, 105) auf einen Grund von etwa (47, 39, 30) - weisse
   Schrift steht dort bei 14,9:1, der Fliesstext auf rgba(255,255,255,.75)
   bei rund 9:1. Die Lesbarkeit haengt damit nicht am Bildausschnitt, und
   ein spaeterer Fototausch kann sie nicht kippen, solange der Verlauf
   bleibt.

   background-attachment bleibt bewusst auf scroll: fixed ruckelt auf iOS
   und wird dort ohnehin ignoriert. */
.section--photo {
  background-color: var(--ti-black);
  background-image:
    linear-gradient(rgba(14, 14, 14, 0.82), rgba(14, 14, 14, 0.9)),
    var(--section-photo);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}

.section__head {
  max-width: 65ch;
  margin-bottom: var(--ti-s-8);
}

.section__intro {
  color: var(--ti-fg-2);
  margin-bottom: 0;
}

/* Overline ueber der Sektions-Headline (Label-Schrift wie die Buttons).
   Auf hellem Grund NIE --ti-gold: das Brand-Gold erreicht dort nur 2,45:1.
   --ti-gold-ink liegt bei 5,4:1 auf Weiss und 4,8:1 auf --ti-bg-alt. */
.section__overline {
  font-family: var(--ti-label);
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  font-size: var(--ti-fs-label);
  color: var(--ti-gold-ink);
  /* Ohne das begrenzt die globale p-Regel (65ch) den Kasten auf rund 325px -
     in einem zentrierten Kopf steht die Overline dann sichtbar links neben
     der Mitte. */
  max-width: none;
  margin: 0 0 var(--ti-s-3);
}

/* ==========================================================================
   9a. PORTFOLIO / CREATIVES: zwei gegenlaeufige Endlos-Baender
   --------------------------------------------------------------------------
   Reines CSS, kein JS: die Baender laufen ab dem ersten Frame, auch wenn
   main.js nie geladen wird.

   Schleifen-Mechanik: .marquee__track enthaelt ZWEI identische Gruppen
   (die zweite ist im Markup aria-hidden). Animiert wird um genau -50% der
   Track-Breite - dann steht Kachel 1 der Kopie exakt dort, wo Kachel 1 des
   Originals startete, und der Sprung ist unsichtbar.

   Damit die -50% aufgehen, darf der Abstand NICHT als gap am Track liegen
   (sonst fehlt an der Nahtstelle genau eine Luecke). Stattdessen traegt jede
   Gruppe ihren eigenen gap plus ein padding-right in derselben Groesse -
   so ist jede Gruppe exakt 29 * (Kachel + Abstand) breit.

   Rundung: --ti-r-3 (8px) ist das Maximum der Marke. Bewusst nicht die
   weichen Ecken aus der Vorlage - die Marke ist scharf.
   ========================================================================== */
.portfolio {
  overflow: hidden;
  /* Hoehe statt Breite steuert die Kachel (siehe .reel weiter unten).
     14rem = 224px: ein 4:5-Creative ist damit 179px breit statt der
     frueheren 120px. Bei 120px war auf dem Handy keine Headline lesbar,
     und der Abschnitt behauptete mit "Creatives, die Bewerbungen
     generieren" etwas, das er selbst nicht zeigte. */
  --reel-h: 14rem;
  --reel-gap: var(--ti-s-3);
  /* Das Tempo ist auf beiden Breiten gleich, die Rundenzeit ist es nicht:
     mobil sind die Kacheln kleiner, eine Runde ist damit kuerzer.
     224px * 25.2 (Summe der Seitenverhaeltnisse) + 29 * 12 = 5993px
     Gruppenbreite / 120s = 50px/s, derselbe Wert wie ab 768px.
     Wer Kacheln ergaenzt oder entfernt, muss hier neu rechnen -
     tools/creatives-import.sh gibt den passenden Wert nach jedem Lauf aus. */
  --reel-speed-1: 120s;
  --reel-speed-2: 26s;
}

/* Kopf und Fuss der Sektion stehen auf jeder Breite mittig - als einzige
   Sektion der Seite. Die beiden Baender sind symmetrisch, eine linksbuendige
   Headline haette daneben schief gewirkt. */
.portfolio__head {
  margin-bottom: var(--ti-s-6);
  margin-inline: auto;
  text-align: center;
}

.portfolio__head .section__intro {
  margin-inline: auto;
}

/* 24ch beziehen sich auf die Display-Schrift der h2 selbst. Der Wert
   entscheidet ueber die Zeilenzahl - nicht die Schriftgroesse, denn ch
   skaliert mit ihr mit. Bei 20ch brach die Headline auch auf dem Handy
   noch dreizeilig um. */
.portfolio__title {
  font-size: var(--ti-fs-display-m);
  line-height: 1.06;
  /* Etwas enger als die h2-Grundeinstellung (-0.01em). Grosse Display-Zeilen
     vertragen das - und "Bewerbungen generieren." passt damit auch bei 360px
     Viewport noch in eine Zeile (ohne blieb genau ein Pixel zu wenig). */
  letter-spacing: -0.02em;
  max-width: 24ch;
  margin-inline: auto;
}

.portfolio__rails {
  display: grid;
  /* minmax(0, 1fr) statt des impliziten `auto`: die untere Zeile ist ein
     Scroll-Container, und ein auto-Track waechst auf die Mindestbreite
     seines Inhalts - also auf alle sieben Videokacheln nebeneinander. Die
     Zeile ragte dadurch aus dem Abschnitt heraus (von overflow:hidden an
     .portfolio nur verdeckt), scrollWidth und clientWidth waren gleich, und
     die Pfeile hielten sich fuer am Ende angekommen. Dasselbe Muster wie
     bei .proof__list in #einblicke. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--reel-gap);
}

/* Die Baender liegen in der Container-Breite (nicht full-bleed). An beiden
   Kanten blendet eine Maske die Kacheln aus, damit sie nicht hart abreissen,
   sondern in die Flaeche laufen. */
.marquee {
  overflow: hidden;
  -webkit-mask-image: linear-gradient(
    90deg, transparent 0, #000 8%, #000 92%, transparent 100%
  );
  mask-image: linear-gradient(
    90deg, transparent 0, #000 8%, #000 92%, transparent 100%
  );
}

.marquee__track {
  display: flex;
  width: max-content;
  animation: tiMarqueeLeft var(--reel-speed-1) linear infinite;
  will-change: transform;
}

.marquee--right .marquee__track {
  animation-name: tiMarqueeRight;
  animation-duration: var(--reel-speed-2);
}

/* Anhalten, solange jemand hinschaut oder sich per Tastatur darin bewegt.

   Der :hover-Zweig gilt bewusst NUR fuer echte Zeigegeraete. Auf dem Handy
   haelt der Browser den Hover-Zustand nach einem Tap auf der getippten Kachel
   fest, bis irgendwo anders hingetippt wird - das Band blieb dadurch stehen
   und lief beim Weiterscrollen nicht wieder an. Auf Touch pausiert es
   stattdessen nur, solange der Finger liegt (:active), und laeuft beim
   Loslassen sofort weiter. */
@media (hover: hover) and (pointer: fine) {
  .marquee:hover .marquee__track {
    animation-play-state: paused;
  }
}

@media (hover: none) {
  .marquee:active .marquee__track {
    animation-play-state: paused;
  }
}

.marquee:focus-within .marquee__track {
  animation-play-state: paused;
}

.marquee__group {
  display: flex;
  gap: var(--reel-gap);
  padding-right: var(--reel-gap);
}

@keyframes tiMarqueeLeft {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

@keyframes tiMarqueeRight {
  from { transform: translateX(-50%); }
  to   { transform: translateX(0); }
}

/* --- Einzelne Kachel (9:16 wie das fertige Video) --- */
.reel {
  flex: 0 0 auto;
  /* Gleiche HOEHE, nicht gleiche Breite. Die Vorlagen sind 1:1 und 4:5; in
     ein gemeinsames Format gezwungen bekam jedes dritte Creative Balken.
     So behaelt jedes sein echtes Format: quadratische Kacheln werden breit,
     hochformatige schmal, und das Band bekommt einen Rhythmus, statt eine
     Reihe geklonter Kaesten zu sein. Die Breite ergibt sich aus dem Bild -
     deshalb hier keine Angabe dazu.
     Denselben Kniff nutzt #team fuer seine zwei Fotoformate. */
  height: var(--reel-h);
  margin: 0;
}

.reel__img {
  display: block;
  /* Hoehe fuehrt, Breite folgt. object-fit braucht es nicht mehr: das Bild
     hat exakt das Seitenverhaeltnis, das es beansprucht, es gibt nichts zu
     beschneiden und nichts aufzufuellen. */
  height: 100%;
  width: auto;
  transition: transform 480ms var(--ti-ease-entrance, ease);
}

/* Der Rahmen der Foto-Kachel. Sie war einmal ein <button>, der das Creative
   in einer Lightbox gross zeigte - das ist im August 2026 auf Kundenwunsch
   entfernt worden: die Lightbox liess sich nicht zuverlaessig schliessen und
   sperrte danach die ganze Seite (html.ti-lb-open blieb stehen). Ein Band,
   das laeuft, ist ohnehin keine gute Klickflaeche - man zielt auf etwas, das
   wegfaehrt. Die Kachel ist im Markup reine Anschauung, deshalb <span>.
   Seit 2026-10-24 (Kundenwunsch) gibt es wieder eine Einzelansicht, diesmal
   als natives <dialog> (js/main.js Abschnitt 17); das Band haelt beim Zeigen
   und beim Antippen an, so laesst sich die Kachel treffen. */
.reel__open {
  display: block;
  position: relative;
  height: 100%;
  overflow: hidden;
  border-radius: var(--ti-r-3);
  background-color: var(--ti-n-900);
}

/* Sanftes Heranfahren beim Hover: skaliert wird der Inhalt, nicht die
   Kachel - die Kachelkante bleibt stehen, das Bild waechst dahinter. Nur mit
   echtem Zeigegeraet, auf Touch bliebe der Zustand nach einem Tap haengen. */
@media (hover: hover) and (pointer: fine) {
  .reel:hover .reel__img,
  .reel:hover .reel__placeholder {
    transform: scale(1.07);
  }
}

/* Seit 2026-10-24 (Kundenwunsch) oeffnet ein Klick auf ein Foto-Creative die
   Einzelansicht (js/main.js Abschnitt 17). Die Klasse setzt erst das Skript,
   ohne JS bleibt die Kachel reine Anschauung. */
.reel__open.is-klickbar {
  cursor: zoom-in;
}

.reel__open.is-klickbar:focus-visible {
  outline: 2px solid var(--ti-gold);
  outline-offset: -3px;
}

/* --- Einzelansicht der Foto-Creatives: ganzer Bildschirm, Creative im
   echten Format so gross wie moeglich, Pfeile links und rechts (auf dem
   Handy unten), oben Zaehler und Schliessen. Natives <dialog>, die
   Scrollsperre haengt nur an html.ti-lupe-offen und faellt beim Ereignis
   "close" weg. --- */
.ti-lupe {
  position: fixed;
  inset: 0;
  width: 100%;
  max-width: 100%;
  height: 100dvh;
  max-height: 100dvh;
  margin: 0;
  padding: 0;
  border: 0;
  background-color: rgba(14, 14, 14, 0.96);
  color: var(--ti-paper);
  overflow: hidden;
  overscroll-behavior: contain;
}

.ti-lupe[open] {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
}

.ti-lupe::backdrop {
  background-color: rgba(14, 14, 14, 0.9);
}

html.ti-lupe-offen {
  overflow: hidden;
}

.ti-lupe__kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ti-s-4);
  padding: var(--ti-s-4) var(--ti-s-6);
}

.ti-lupe__zaehler {
  margin: 0;
  font-family: var(--ti-label);
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: rgba(255, 255, 255, 0.7);
}

.ti-lupe__buehne {
  display: grid;
  place-items: center;
  min-height: 0;
  padding: 0 calc(2.75rem + 2 * var(--ti-s-6)) var(--ti-s-6);
  touch-action: pan-y;
  user-select: none;
}

.ti-lupe__bild {
  display: block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: calc(100dvh - 6rem);
  border-radius: var(--ti-r-3);
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.7);
  -webkit-user-drag: none;
}

.ti-lupe__knopf {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 50%;
  background-color: var(--ti-black);
  color: var(--ti-paper);
  cursor: pointer;
  transition:
    background-color var(--ti-dur-base) var(--ti-ease-standard),
    color var(--ti-dur-base) var(--ti-ease-standard);
}

.ti-lupe__knopf:hover {
  background-color: var(--ti-paper);
  color: var(--ti-black);
}

.ti-lupe__knopf:focus-visible {
  outline: 2px solid var(--ti-gold);
  outline-offset: 2px;
}

.ti-lupe__pfeil {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

.ti-lupe__pfeil--zurueck { left: var(--ti-s-6); }
.ti-lupe__pfeil--weiter { right: var(--ti-s-6); }

@media (max-width: 620px) {
  .ti-lupe__kopf { padding: var(--ti-s-3) var(--ti-s-4); }
  .ti-lupe__buehne { padding: 0 0 calc(2.75rem + 2 * var(--ti-s-4)); }
  .ti-lupe__bild { border-radius: 0; max-height: calc(100dvh - 9rem); }
  .ti-lupe__pfeil { top: auto; bottom: var(--ti-s-4); transform: none; }
  .ti-lupe__pfeil--zurueck { left: var(--ti-s-4); }
  .ti-lupe__pfeil--weiter { right: var(--ti-s-4); }
}

/* --- Platzhalter, bis das echte Creative geliefert ist --- */
.reel__placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--ti-s-2);
  background-color: var(--ti-n-900);
  background-image: linear-gradient(
    160deg, rgba(220, 152, 50, 0.14), rgba(220, 152, 50, 0) 55%
  );
}

.reel__placeholder-num {
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: 1.75rem;
  line-height: 1;
  color: var(--ti-gold);
}

/* Bewusst nowrap plus enge Laufweite: in der schmalsten Kachel (Handy)
   bricht "Creative folgt" sonst in zwei Zeilen. */
.reel__placeholder-label {
  font-family: var(--ti-label);
  font-weight: 500;
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ti-n-400);
}

/* --- Zeile 2: statische Videoreihe ---------------------------------------
   Kein Marquee. Die Reihe steht still und wird von Hand verschoben - ein
   laufendes Band waere das Gegenteil von "anklicken und abspielen". Weil auf
   dem Handy sonst nur zwei der acht Kacheln im Bild waeren, ist die Reihe
   waagerecht scrollbar; scroll-snap laesst jede Kachel einrasten, statt sie
   auf halber Breite stehen zu lassen.

   Die Kacheln sind bewusst breiter als in Zeile 1: ein Video, das man
   anklicken soll, muss man auch ansehen koennen. Bei den 168px der oberen
   Zeile ist es zu sehen, aber nicht anzusehen.
   ------------------------------------------------------------------------ */
.reel-row {
  --reel-w-video: clamp(11rem, 52vw, 15rem);
  display: flex;
  gap: var(--reel-gap);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* Platz fuer die Scrollleiste, damit sie nicht auf der untersten
     Kachelkante liegt. Mit JS uebernehmen die Pfeile und die Leiste
     verschwindet - dann faellt auch dieser Abstand weg. */
  padding-bottom: var(--ti-s-2);
  scrollbar-width: thin;
}

/* Mit JS bedienen die Pfeile die Reihe, die Scrollleiste ist dann nur noch
   ein grauer Balken unter den Kacheln. Ohne JS bleibt sie stehen - sie waere
   sonst das einzige Bedienelement, das wir wegnehmen, ohne Ersatz zu geben.
   Gewischt werden kann in beiden Faellen. */
html.js .reel-row {
  padding-bottom: 0;
  scrollbar-width: none;
}

html.js .reel-row::-webkit-scrollbar {
  display: none;
}

/* --- Pfeile statt Scrollleiste ------------------------------------------
   Die Reihe wurde bisher nur ueber ihre Scrollleiste und per Wischen
   bedient. Auf dem Desktop war ein grauer Balken unter den Kacheln das
   Einzige, was von der Bedienung zu sehen war - und er sagt nicht, dass
   rechts noch etwas kommt.

   Die Pfeile stehen dort, wo der Balken lag, und NICHT ueber den Kacheln:
   auf dem Handy landete ein Rand-Pfeil genau auf dem goldenen Play-Knopf der
   naechsten Kachel, und auf dem Desktop stand er auf gleicher Hoehe wie fuenf
   runde Play-Knoepfe - ein sechster Kreis in einer Reihe von Kreisen.

   Rechtsbuendig statt mittig: die Reihe faengt links an und laeuft nach
   rechts weiter, dort steht auch die Bedienung dafuer.
   ------------------------------------------------------------------------ */
.reel-nav {
  display: none;
}

html.js .reel-nav {
  display: flex;
  justify-content: flex-end;
  gap: var(--ti-s-2);
  /* Der Grid-Abstand von .portfolio__rails (--reel-gap) liegt schon
     darueber; die 8px hier machen daraus die Luft, die eine Bedienzeile
     von dem trennt, was sie bedient. */
  margin-top: var(--ti-s-2);
}

.reel-nav__arrow {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  flex: 0 0 auto;
  padding: 0;
  border: 1px solid var(--ti-line);
  border-radius: 50%;
  background-color: var(--ti-paper);
  color: var(--ti-n-900);
  cursor: pointer;
  transition:
    border-color var(--ti-dur-base) var(--ti-ease-standard),
    color var(--ti-dur-base) var(--ti-ease-standard),
    opacity var(--ti-dur-base) var(--ti-ease-standard);
}

.reel-nav__arrow svg {
  width: 1.25rem;
  height: 1.25rem;
  display: block;
}

@media (hover: hover) and (pointer: fine) {
  .reel-nav__arrow:hover:not(:disabled) {
    border-color: var(--ti-gold);
    color: var(--ti-gold-ink);
  }
}

.reel-nav__arrow:focus-visible {
  outline: 2px solid var(--ti-gold);
  outline-offset: 3px;
}

/* Am Ende der Reihe gedaempft, nicht ausgeblendet: die beiden Pfeile stehen
   nebeneinander, und ein verschwindender Knopf schoebe den anderen unter dem
   Daumen weg. */
.reel-nav__arrow:disabled {
  opacity: 0.3;
  cursor: default;
}

.reel-row:focus-visible {
  outline: 2px solid var(--ti-gold);
  outline-offset: 4px;
}

.reel-row .reel {
  width: var(--reel-w-video);
  /* Die Hoehe aus .reel gilt nur fuer die Foto-Kacheln der oberen Zeile.
     Hier fuehrt die Breite, die Hoehe ergibt sich aus dem 9:16 der Videos -
     ohne dieses Zuruecksetzen erbt die Videokachel die Fotohoehe und wird
     zum falschen Format gestaucht. */
  height: auto;
  scroll-snap-align: start;
}

/* .reel__media gehoert seit dem Umbau nur noch der Videozeile: die
   Foto-Kacheln tragen ihren Rahmen in .reel__open, weil sie eine
   Schaltflaeche sind. Die Videos sind echte 1080x1920, hier gilt das feste
   Hochformat also weiter - anders als oben, wo jedes Bild sein eigenes
   Format behaelt. */
.reel--video .reel__media {
  position: relative;
  aspect-ratio: 9 / 16;
  overflow: hidden;
  border-radius: var(--ti-r-3);
  background-color: var(--ti-black);
}

.reel__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background-color: var(--ti-black);
}

/* Der goldene Play-Knopf ist Progressive Enhancement. Ohne JS traegt das
   <video> seine eigenen controls - der Knopf waere dann ein zweites,
   funktionsloses Bedienelement daneben. Deshalb erscheint er nur mit JS,
   und js/main.js nimmt dem Video im selben Schritt die controls ab. */
.reel__play {
  display: none;
}

html.js .reel__play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  cursor: pointer;
  /* Leichter Abdunkler nach unten: das Standbild eines Creatives ist oft
     hell, das goldene Rund braucht darauf einen Grund. */
  background-image: linear-gradient(
    180deg, rgba(14, 14, 14, 0) 45%, rgba(14, 14, 14, 0.5) 100%
  );
  background-color: transparent;
}

html.js .reel__play::before {
  content: "";
  grid-area: 1 / 1;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: 50%;
  background-color: var(--ti-gold);
  transition: transform 240ms var(--ti-ease-entrance, ease);
}

/* Dreieck aus Rahmen statt Icon-Datei. Der kleine Versatz nach rechts
   schiebt die optische Mitte auf die geometrische - ein exakt zentriertes
   Dreieck sieht in einem Kreis nach links verrutscht aus. */
html.js .reel__play::after {
  content: "";
  grid-area: 1 / 1;
  width: 0;
  height: 0;
  border-top: 0.6rem solid transparent;
  border-bottom: 0.6rem solid transparent;
  border-left: 0.95rem solid var(--ti-black);
  margin-left: 0.22rem;
}

@media (hover: hover) and (pointer: fine) {
  html.js .reel__play:hover::before {
    transform: scale(1.08);
  }

  /* Der Zoom aus Zeile 1 gilt hier nicht: die Kachel ist ein Player. Waechst
     sie unter dem Zeiger, wandert der Play-Knopf weg. */
  .reel--video:hover .reel__placeholder {
    transform: none;
  }
}

html.js .reel__play:focus-visible {
  outline: 2px solid var(--ti-gold);
  outline-offset: -4px;
}

/* Laeuft das Video, ist der Knopf weg und das <video> traegt wieder seine
   eigenen controls. */
html.js .reel--video.is-playing .reel__play {
  display: none;
}


/* --- Abschluss der Sektion: nur der CTA --- */
.portfolio__foot {
  margin-top: var(--ti-s-7);
  display: flex;
  justify-content: center;
}


/* --- Vergleich alt vs. neu (Loesung), seit 2026-10-24 als Gegenueberstellung
   (Kundenwunsch): zwei Spalten nebeneinander statt Umschalter, auf jeder
   Breite. Seit 2026-10-26 im Look der Tafeln von #fit (Kundenwunsch: fuegte
   sich nicht ins Gesamtbild): helle Tafel, schmale farbige Oberkante (alt
   rot, neu gruen), Titel in League Spartan mittig, Punkte mit Haarlinie und
   getoentem quadratischem Marker. "vs." als Quadrat wie .versus__vs.
   Jede Spalte ist ein Subgrid ueber Kopf und fuenf Punkte, dadurch stehen
   die Paare links und rechts auf einer Hoehe, auch wenn ein Punkt umbricht. --- */
.compare {
  position: relative;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: auto repeat(5, auto);
  column-gap: var(--ti-s-3);
}

.compare__col {
  position: relative;
  overflow: hidden;
  grid-row: 1 / -1;
  display: grid;
  grid-template-rows: subgrid;
  row-gap: 0;
  padding: var(--ti-s-5) var(--ti-s-3) var(--ti-s-3);
  border: 1px solid var(--ti-line);
  border-radius: var(--ti-r-3);
  background-color: var(--ti-off-white);
}

.compare__col::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
}

.compare__col--old::before { background-color: var(--ti-danger); }
.compare__col--new::before { background-color: var(--ti-green); }
.compare__col--new { transition-delay: 80ms; }

.compare__kopf {
  padding-bottom: var(--ti-s-4);
  text-align: center;
}

.compare__name {
  margin: 0;
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: var(--ti-fs-h3-display);
  line-height: 1.15;
  letter-spacing: -0.015em;
  white-space: nowrap;
}

.compare__col--old .compare__name { color: var(--ti-fg-2); }
.compare__col--new .compare__name { color: var(--ti-green-ink); }

.compare__name span {
  display: block;
  margin-top: 0.45rem;
  font-family: var(--ti-label);
  font-weight: 600;
  font-size: 0.6875rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ti-fg-2);
}

/* Die Liste gibt ihre Punkte direkt an das Subgrid der Spalte weiter. */
.compare__list {
  display: contents;
}

.compare__list li {
  display: flex;
  align-items: flex-start;
  gap: var(--ti-s-3);
  margin: 0;
  padding-block: var(--ti-s-3);
  border-top: 1px solid var(--ti-line);
  color: var(--ti-fg-2);
  font-size: var(--ti-fs-body-s);
  line-height: 1.5;
}

/* Getoenter Marker wie .fit__mark: quadratisch, kein Kreis. */
.compare__list li::before {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  margin-top: 0.05rem;
  border-radius: var(--ti-r-2);
  font-weight: 700;
  line-height: 1;
}

.compare__col--old .compare__list li::before {
  content: "\00d7";
  font-size: 1.05rem;
  color: var(--ti-danger);
  background-color: rgba(196, 56, 44, 0.12);
}

.compare__col--new .compare__list li::before {
  content: "\2713";
  font-size: 0.8125rem;
  color: var(--ti-green-ink);
  background-color: rgba(47, 143, 95, 0.14);
}

/* "vs." in der Fuge, abgerundetes Quadrat wie .versus__vs: schwarz, weisse
   Schrift, weisser Rand gegen die Kanten der Tafeln. */
.compare__vs {
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: 1rem;
  letter-spacing: -0.01em;
  color: var(--ti-paper);
  background-color: var(--ti-black);
  border: 2px solid var(--ti-paper);
  border-radius: var(--ti-r-3);
  box-shadow: 0 8px 20px -12px rgba(14, 14, 14, 0.6);
}

@media (max-width: 599px) {
  .compare__vs { display: none; }
  .compare__col { padding-left: var(--ti-s-2); padding-right: var(--ti-s-2); }
  /* "Social-Recruiting" bricht nicht am Bindestrich um, die Groesse folgt der Breite. */
  .compare__name { font-size: min(var(--ti-fs-h3-display), 4.6vw); }
  .compare__name span { font-size: 0.625rem; letter-spacing: 0.14em; }
  .compare__list li { flex-direction: column; gap: var(--ti-s-2); font-size: 0.8125rem; }
}

@media (min-width: 768px) {
  .compare { column-gap: var(--ti-s-5); }
  .compare__col { padding: var(--ti-s-7) var(--ti-s-6) var(--ti-s-5); }
  .compare__kopf { padding-bottom: var(--ti-s-5); }
  .compare__list li { gap: var(--ti-s-4); font-size: 1rem; padding-block: var(--ti-s-4); }
}

/* --- Schritte (Unser Ablauf in 4 Schritten): Sequenz mit goldener Linie.

   Die Linie wird beim Scrollen gezeichnet: js/main.js setzt fortlaufend
   --steps-progress (0..1) an .steps-wrap, das CSS macht daraus ein scaleY
   (mobil) bzw. scaleX (ab 1024px). Sobald die Linie eine Nummer erreicht,
   bekommt der Schritt .is-reached und die Nummer kippt von schwarz auf Gold.

   Faellt JS aus, greift der Default-Wert 1 in var() - die Linie steht dann
   sofort voll gezeichnet da, kein Inhalt haengt an der Animation. --- */
.steps__head {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}

.steps__head h2 {
  max-width: none;
  margin-inline: auto;
}

.steps__head .section__intro {
  margin-inline: auto;
  max-width: 52ch;
}

.steps-wrap {
  position: relative;
  max-width: 46rem;
  margin-inline: auto;
}

.steps__line {
  position: absolute;
  /* Mitte des 3.25rem grossen Marken-Quadrats. Wer die Quadratgroesse
     aendert, muss diese Werte (und die Desktop-Regel) mitziehen, sonst
     laeuft die Linie nicht mehr durch die Mitte der Icons. */
  left: 1.625rem;
  top: 1.625rem;
  bottom: 1.625rem;
  width: 2px;
  background-color: var(--ti-line);
  overflow: hidden;
}

.steps__line-fill {
  position: absolute;
  inset: 0;
  background-color: var(--ti-gold);
  transform: scaleY(var(--steps-progress, 1));
  transform-origin: top;
  /* Kurz genug, dass die Linie am Scrollen klebt, lang genug, dass sie bei
     groben Scroll-Spruengen nicht springt. */
  transition: transform 140ms linear;
}

.steps {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--ti-s-7);
}

.steps__item {
  display: flex;
  gap: var(--ti-s-5);
  align-items: flex-start;
}

.steps__item:nth-child(2) { transition-delay: 80ms; }
.steps__item:nth-child(3) { transition-delay: 160ms; }
.steps__item:nth-child(4) { transition-delay: 240ms; }

/* Das Quadrat sitzt auf der Linie und ist der Fortschrittsanzeiger: dunkel
   mit goldenem Icon, solange die Linie es noch nicht erreicht hat, danach
   Gold mit dunklem Icon.

   Hub und Vergroesserung laufen ueber zwei Custom Properties statt ueber
   zwei konkurrierende transform-Regeln: sonst wuerde der Hover beim
   Darueberfahren die Vergroesserung des erreichten Zustands ueberschreiben.
   transform selbst bleibt animierbar, die Aenderung einer Variablen rechnet
   den Wert neu. */
.steps__num {
  flex: 0 0 auto;
  position: relative;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  height: 3.25rem;
  border-radius: var(--ti-r-2);
  background-color: var(--ti-black);
  color: var(--ti-gold);
  --num-scale: 1;
  --num-lift: 0px;
  transform: translateY(var(--num-lift)) scale(var(--num-scale));
  transition:
    background-color var(--ti-dur-slow) var(--ti-ease-standard),
    color var(--ti-dur-slow) var(--ti-ease-standard),
    box-shadow var(--ti-dur-slow) var(--ti-ease-standard),
    transform var(--ti-dur-base) var(--ti-ease-standard);
}

.steps__num svg {
  stroke-linecap: square;
  stroke-linejoin: miter;
}

/* Die Nummer als kleine Plakette in der Ecke des Quadrats. Sie ist Zierde -
   die Reihenfolge steht im <ol>, das ganze Quadrat traegt aria-hidden. */
.steps__badge {
  position: absolute;
  top: -0.5rem;
  right: -0.5rem;
  min-width: 1.5rem;
  padding: 0.125rem 0.25rem;
  border-radius: var(--ti-r-1);
  background-color: var(--ti-gold);
  color: var(--ti-black);
  font-family: var(--ti-label);
  font-weight: 600;
  font-size: 0.6875rem;
  letter-spacing: 0.06em;
  line-height: 1.35;
  text-align: center;
}

.steps__item.is-reached .steps__num {
  background-color: var(--ti-gold);
  color: var(--ti-black);
  box-shadow: 0 0 0 6px rgba(220, 152, 50, 0.16);
  --num-scale: 1.06;
}

/* Der Text steht in einer eigenen Karte. Die Oberkante ist bewusst 2px
   statt 1px: sie ist die Flaeche, die beim Hover auf Gold kippt, und traegt
   dieselbe Rolle wie die Oberkante der Tafeln in #vergleich. */
.steps__body {
  flex: 1 1 auto;
  min-width: 0;
  padding: var(--ti-s-5);
  background-color: var(--ti-paper);
  border: 1px solid var(--ti-line);
  border-top: 2px solid var(--ti-line);
  border-radius: var(--ti-r-3);
  transition:
    transform var(--ti-dur-base) var(--ti-ease-standard),
    border-color var(--ti-dur-base) var(--ti-ease-standard);
}

/* Eine Stufe unter der uebrigen h3-Groesse der Seite (--ti-fs-h4 statt
   --ti-fs-h3) und der Text auf 1rem statt der 1.0625rem des Fliesstextes:
   in einer viertelbreiten Karte wirkte beides sonst zu gross. Die Karte ist
   ein Baustein in einer Vierer-Reihe, keine eigene Sektion. */
.steps__title {
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: var(--ti-fs-h4);
  line-height: 1.2;
  letter-spacing: -0.01em;
  margin-bottom: var(--ti-s-2);
  transition: color var(--ti-dur-base) var(--ti-ease-standard);
}

.steps__text {
  color: var(--ti-fg-2);
  font-size: var(--ti-fs-body);
  margin-bottom: 0;
  max-width: 50ch;
}

/* Hub, goldene Oberkante und goldene Ueberschrift nur mit echtem
   Zeigegeraet - sonst bliebe der Zustand auf dem Handy nach einem Tap
   haengen. Angefasst werden die Kinder, nicht .steps__item: das Element
   traegt die Reveal-Transition (Abschnitt 11) und wuerde sie sonst
   ueberschreiben - dasselbe Muster wie bei den Karten in #warum-wir. */
@media (hover: hover) and (pointer: fine) {
  .steps__item:hover .steps__num {
    --num-lift: -4px;
  }

  .steps__item:hover .steps__body {
    transform: translateY(-4px);
    border-top-color: var(--ti-gold);
  }

  .steps__item:hover .steps__title {
    color: var(--ti-gold);
  }
}

.steps__foot {
  margin-top: var(--ti-s-8);
  display: flex;
  justify-content: center;
}

/* --- Ablauf auf Schwarz ---
   Die noch nicht gezeichnete Linie war --ti-line (#E5E5E3). Auf Schwarz
   waere das ein heller Strich, der aussieht, als waere er schon gezogen -
   der Fortschritt liesse sich dann nicht mehr ablesen. Sie wird zur
   Haarlinie.

   Die noch nicht erreichte Nummer war ein schwarzes Quadrat; auf schwarzem
   Grund ist die unsichtbar. Sie wird eine Stufe heller, die Ziffer bleibt
   gold. Die erreichte Nummer (Gold mit schwarzer Ziffer) bleibt, wie sie
   ist - der Umschlag ist auf Schwarz sogar deutlicher als vorher. Deren
   Regel ist spezifischer und gewinnt gegen die Zeile hier. */
.section--dark .steps__line {
  background-color: rgba(255, 255, 255, 0.16);
}

/* Vor dem Erreichen: dunkles Quadrat mit grauer Umrandung und WEISSER
   Glyphe. Das Gold ist damit dem erreichten Zustand vorbehalten und der
   Umschlag beim Scrollen deutlicher - vorher waren beide Zustaende gold
   und unterschieden sich nur in der Flaeche. */
.section--dark .steps__num {
  background-color: var(--ti-n-800);
  color: var(--ti-paper);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22);
}

/* Der erreichte Zustand behaelt Gold mit dunkler Glyphe. Die Regel steht
   hier noch einmal, weil die Zeile darueber jetzt auch color setzt und
   gleich spezifisch waere. */
.section--dark .steps__item.is-reached .steps__num {
  background-color: var(--ti-gold);
  color: var(--ti-black);
  box-shadow: 0 0 0 6px rgba(220, 152, 50, 0.16);
}

.section--dark .steps__body {
  background-color: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.1);
}

.section--dark .steps__text {
  color: rgba(255, 255, 255, 0.75);
}

/* Auf Schwarz traegt der Titel Weiss; beim Hover kippt er auf Gold
   (7,9:1 auf der Kartenflaeche). */
@media (hover: hover) and (pointer: fine) {
  .section--dark .steps__item:hover .steps__title {
    color: var(--ti-gold);
  }
}

/* --- Warum wir: drei gleichrangige USP-Karten unter einem mittigen Kopf.
   Frueher standen hier alternierende Flag-Cut-Zeilen; die drei Gruende waren
   dabei erst beim Lesen als Dreiergruppe erkennbar. Jetzt tragen drei gleich
   gebaute Karten je ein Icon-Quadrat, eine "X statt Y"-Headline und drei
   Zeilen Text - die Sektion ist damit auf einen Blick lesbar.

   Das Icon-Quadrat ist bewusst SCHWARZ mit goldener Glyphe, nicht umgekehrt:
   der orangene Signatur-Punkt bleibt so dem Markenauftritt vorbehalten und
   wird nicht dreifach nebeneinander wiederholt. --- */
.reasons__head {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}

/* max-width: none wie bei #cases/#vergleich - sonst bricht die Headline auf
   dem Desktop unnoetig dreizeilig. */
.reasons__head h2 {
  max-width: none;
  margin-inline: auto;
}

.reasons__head .section__intro {
  max-width: 58ch;
  margin-inline: auto;
}

.reasons {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--ti-s-5);
}

.reason {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--ti-s-6) var(--ti-s-5);
  background-color: var(--ti-paper);
  border: 1px solid var(--ti-line);
  border-radius: var(--ti-r-3);
}

.reason:nth-child(2) { transition-delay: 60ms; }
.reason:nth-child(3) { transition-delay: 120ms; }

.reason__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 3.25rem;
  height: 3.25rem;
  margin-bottom: var(--ti-s-5);
  border-radius: var(--ti-r-2);
  background-color: var(--ti-black);
  color: var(--ti-gold);
  /* Die Karte selbst traegt die Reveal-Transition (siehe Abschnitt 11) -
     ein eigener Hover-Uebergang auf .reason wuerde sie ueberschreiben.
     Deshalb reagiert nur das Icon. */
  transition:
    transform var(--ti-dur-base) var(--ti-ease-standard),
    box-shadow var(--ti-dur-base) var(--ti-ease-standard);
}

.reason__icon svg {
  stroke-linecap: square;
  stroke-linejoin: miter;
}

@media (hover: hover) and (pointer: fine) {
  .reason:hover .reason__icon {
    transform: translateY(-2px) scale(1.06);
    box-shadow: 0 10px 22px -12px rgba(14, 14, 14, 0.7);
  }
}

.reason__title {
  font-size: var(--ti-fs-h4);
  line-height: 1.25;
  max-width: none;
  margin: 0 0 var(--ti-s-3);
}

.reason__text {
  color: var(--ti-fg-2);
  font-size: var(--ti-fs-body-s);
  margin: 0;
  max-width: 38ch;
}

/* --- Warum wir auf Schwarz ---
   Die Karte kann nicht weiss bleiben: drei weisse Bloecke auf Schwarz
   waeren drei Leuchtkaesten und lauter als die Headline darueber. Sie wird
   zur leicht aufgehellten Flaeche mit Haarlinie - dieselbe Machart wie das
   Termin-Panel im Abschluss-CTA.

   Das Icon-Quadrat war schwarz mit goldener Glyphe und ist auf schwarzem
   Grund nicht mehr zu sehen. Es wird eine Stufe heller statt gold: die
   Regel "der orangene Punkt bleibt der Marke vorbehalten und steht nicht
   dreimal nebeneinander" gilt auf Schwarz genauso. */
.section--dark .reason {
  background-color: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.12);
}

.section--dark .reason__icon {
  background-color: var(--ti-n-700);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12);
}

.section--dark .reason__text {
  color: rgba(255, 255, 255, 0.75);
}

/* Der Hover-Schatten war ein schwarzer Schlagschatten - auf Schwarz
   passiert damit sichtbar nichts. Auf der dunklen Flaeche traegt der
   Gold-Glow die Rueckmeldung. */
@media (hover: hover) and (pointer: fine) {
  .section--dark .reason:hover .reason__icon {
    box-shadow:
      inset 0 0 0 1px rgba(255, 255, 255, 0.12),
      0 10px 22px -10px rgba(220, 152, 50, 0.55);
  }
}

/* ==========================================================================
   9d. PASST ES? (#passt-es)
   Selbstqualifizierung in zwei Tafeln: links passt es, rechts nicht.
   Bewusst leiser als #vergleich - dort trennt schwarze Flaeche gegen helle,
   hier bleiben beide Tafeln hell und die Farbe steckt nur in der Oberkante
   und im getoenten Marker. Zweimal derselbe laute Auftritt haette den
   Vergleich weiter oben entwertet.

   Kontraste: Haken --ti-green-ink (#20734C) auf hellgruener Flaeche = 5,4:1,
   Kreuz --ti-danger (#C4382C) auf hellroter Flaeche = 4,9:1. Beide ueber AA.
   ========================================================================== */
.fit__head {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}

.fit__head h2 {
  max-width: none;
  margin-inline: auto;
}

.fit__head .section__intro {
  max-width: 56ch;
  margin-inline: auto;
}

.fit__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--ti-s-5);
}

.fit__panel {
  position: relative;
  overflow: hidden;
  padding: var(--ti-s-6) var(--ti-s-5);
  border: 1px solid var(--ti-line);
  border-radius: var(--ti-r-3);
  background-color: var(--ti-off-white);
  text-align: center;
}

/* Die farbige Oberkante ist das einzige Flaechen-Signal - schmal genug,
   dass die Tafeln ruhig bleiben. */
.fit__panel::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
}

.fit__panel--yes::before { background-color: var(--ti-green); }
.fit__panel--no::before  { background-color: var(--ti-danger); }

.fit__panel--no { transition-delay: 80ms; }

.fit__panel-title {
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: var(--ti-fs-h3-display);
  line-height: 1.15;
  letter-spacing: -0.015em;
  margin: 0 0 var(--ti-s-5);
}

.fit__panel--yes .fit__panel-title { color: var(--ti-green-ink); }
.fit__panel--no  .fit__panel-title { color: var(--ti-fg-2); }

.fit__list {
  text-align: left;
}

.fit__row {
  display: flex;
  align-items: flex-start;
  gap: var(--ti-s-4);
  padding-block: var(--ti-s-3);
}

.fit__row + .fit__row {
  border-top: 1px solid var(--ti-line);
}

/* Getoent statt gefuellt: derselbe Marker wie in #vergleich, nur eine
   Lautstaerke leiser. */
.fit__mark {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: var(--ti-r-2);
  margin-top: 0.15rem;
}

.fit__panel--yes .fit__mark {
  background-color: rgba(47, 143, 95, 0.14);
  color: var(--ti-green-ink);
}

.fit__panel--no .fit__mark {
  background-color: rgba(196, 56, 44, 0.12);
  color: var(--ti-danger);
}

.fit__text {
  display: block;
  color: var(--ti-fg-2);
  font-size: var(--ti-fs-body-s);
  line-height: 1.5;
}

.fit__foot {
  margin-top: var(--ti-s-7);
  display: flex;
  justify-content: center;
}

/* ==========================================================================
   9e. TEAM (#team)
   Zwei Zeilen, das Bild wechselt ab 1024px die Seite. Name und Position
   liegen IM Bild ueber einem dunklen Verlauf, der Text steht daneben.

   Der Trick gegen das Format-Problem: beide Fotos bekommen ab 1024px
   dieselbe HOEHE (--team-h), die Breite ergibt sich aus dem
   Seitenverhaeltnis (aspect-ratio). Hochformat 4:5 und Querformat 3:2
   stehen dadurch in einer gemeinsamen Zeilenhoehe, statt als zwei
   unterschiedlich grosse Bloecke zu wirken. Die Grid-Spalte des Bildes
   steht auf `auto` und folgt dieser Breite.
   ========================================================================== */
.team__head {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}

.team__head h2 {
  max-width: none;
  margin-inline: auto;
}

.team__head .section__intro {
  max-width: 58ch;
  margin-inline: auto;
}

.team__rows {
  display: grid;
  gap: var(--ti-s-8);
}

.team__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--ti-s-5);
  align-items: center;
}

.team__row--crew { transition-delay: 80ms; }

.team__photo {
  position: relative;
  overflow: hidden;
  min-width: 0;
  margin: 0;
  border-radius: var(--ti-r-3);
  background-color: var(--ti-n-100);
  box-shadow: 0 24px 48px -32px rgba(14, 14, 14, 0.55);
}

.team__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.team__photo--portrait  { aspect-ratio: 4 / 5; }
.team__photo--landscape { aspect-ratio: 3 / 2; }

/* Name und Position im Bild. Der Verlauf traegt die Schrift auch dann,
   wenn das spaetere Foto unten hell ist - und macht den hellen
   Platzhalter darunter dunkel genug fuer weissen Text. */
.team__caption {
  position: absolute;
  inset: auto 0 0;
  padding: var(--ti-s-4) var(--ti-s-5) var(--ti-s-5);
  /* Verlauf statt deckender Flaeche, damit vom Foto mehr sichtbar bleibt.
     ACHTUNG: Die Stufen sind so gesetzt, dass die goldene Positionszeile
     noch im dichten Teil (>= 0,88) liegt - sie ist die kontrastkritische
     Zeile, nicht der weisse Name. Erst darueber faellt der Verlauf schnell
     auf 0 ab, deshalb braucht es keinen zweiten Verlauf mehr obendrauf. */
  background-image: linear-gradient(
    to top,
    rgba(14, 14, 14, 0.92) 0%,
    rgba(14, 14, 14, 0.88) 78%,
    rgba(14, 14, 14, 0.45) 92%,
    rgba(14, 14, 14, 0) 100%
  );
  color: var(--ti-paper);
  text-align: left;
}

.team__role {
  display: block;
  font-family: var(--ti-label);
  font-weight: 600;
  /* Enger gesperrt als die uebrigen Labels: "GRUENDER & GESCHAEFTSFUEHRER"
     muss in die rund 236px Innenbreite der Hochformat-Kachel passen. */
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-size: var(--ti-fs-label);
  /* Gold auf dunklem Verlauf - die AA-Ausnahme gegen Gold-Text gilt nur auf
     hellem Grund. */
  color: var(--ti-gold);
  margin: 0 0 var(--ti-s-2);
}

.team__name {
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: var(--ti-fs-h3-display);
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--ti-paper);
  margin: 0;
}

.team__body {
  min-width: 0;
}

/* Kurze Gold-Kante als Anker fuer die Textspalte: ohne sie stuende dort
   nach dem Umzug von Name und Position nur noch loser Fliesstext. */
.team__rule {
  display: block;
  width: 2.5rem;
  height: 3px;
  background-color: var(--ti-gold);
  margin-bottom: var(--ti-s-5);
}

.team__lead {
  font-size: var(--ti-fs-body-l);
  font-weight: 600;
  color: var(--ti-fg);
  margin: 0 0 var(--ti-s-4);
  max-width: 46ch;
}

.team__text {
  color: var(--ti-fg-2);
  margin: 0;
  max-width: 52ch;
}

/* --- Team auf Schwarz ---
   Nur die zwei Textrollen der Spalte: Ueberschriften und Subheadline
   erledigt .section--dark. Die Bildunterschriften in den Fotos liegen auf
   ihrem eigenen Verlauf und bleiben unveraendert - sie standen nie auf der
   Sektionsflaeche.

   Die Textspalte bekommt eine eigene, halbdurchsichtige Kachel
   (Kundenwunsch September 2026): auf dem Buerofoto lag der Text vorher
   direkt auf dem Bild und lief ueber wechselnd helle und dunkle Stellen.
   Die Kachel gibt ihm einen ruhigen Grund, ohne das Foto zuzudecken -
   dieselbe Machart wie die Karten in #warum-wir, nur dichter, weil hier
   ein Bild darunter liegt statt einer Flaeche.

   backdrop-filter ist Zugabe und keine Voraussetzung: wo er fehlt, traegt
   schon die Flaeche allein. Gerechnet ist der Kontrast ohne ihn. */
.section--dark .team__body {
  padding: var(--ti-s-6) var(--ti-s-5);
  background-color: rgba(14, 14, 14, 0.62);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: var(--ti-r-3);
  backdrop-filter: blur(8px);
}

.section--dark .team__lead {
  color: var(--ti-paper);
}

.section--dark .team__text {
  color: rgba(255, 255, 255, 0.75);
}

/* --- Kennzahlen (Ergebnisse) --- */
/* Bilanz-Tafel statt Karten-Grid: keine Kaesten, keine Rundungen, nur
   Haarlinien. Passt zur scharfen Editorial-Anmutung der uebrigen Seite und
   spart auf dem Handy die Innenabstaende von vier einzelnen Karten. */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0;
  margin-bottom: var(--ti-s-6);
  border-top: 2px solid var(--ti-fg);
}

/* Der Abstand nach unten war fuer die Kundenstimmen darunter gedacht. Die
   sind auskommentiert, ohne sie stand unter den Kennzahlen 32 bzw. 64 Pixel
   mehr Luft als ueber jedem anderen Abschnittsende (Kundenwunsch
   2026-10-06: Abstand nach unten wie nach oben). */
.stat-grid:last-child {
  margin-bottom: 0;
}

.stat {
  padding: var(--ti-s-5) var(--ti-s-4) var(--ti-s-5) 0;
}

/* Senkrechte Trennlinie vor der zweiten Spalte. */
.stat:nth-child(2n) {
  padding-right: 0;
  padding-left: var(--ti-s-4);
  border-left: 1px solid var(--ti-line);
}

/* Waagerechte Trennlinie zwischen erster und zweiter Zeile. */
.stat:nth-child(-n + 2) {
  border-bottom: 1px solid var(--ti-line);
}

.stat:nth-child(2) { transition-delay: 90ms; }
.stat:nth-child(3) { transition-delay: 180ms; }

.stat__value {
  display: block;
  font-family: var(--ti-display);
  font-size: clamp(2.25rem, 5.4vw, 3.25rem);
  font-weight: 900;
  line-height: 0.95;
  letter-spacing: -0.02em;
  /* Seit 2026-10-29 das dunklere Gold (5,4:1 auf Weiss). Das Brand-Gold
     erreichte auf der hellen Flaeche nur 2,45:1 und lag unter WCAG AA
     (Hinweis aus der Seitenanalyse). */
  color: var(--ti-gold-ink);
  margin-bottom: var(--ti-s-3);
  font-variant-numeric: tabular-nums;
}

/* min-height ueber zwei Zeilen: "besetzte Stellen" laeuft einzeilig,
   "guenstigste Bewerbung" zweizeilig - ohne die Reserve saessen die
   .stat__note-Zeilen der vier Kacheln auf zwei verschiedenen Hoehen und
   die Reihe franste unten aus. Zwei Zeilen sind das Maximum ueber alle
   vier Labels; wer ein dreizeiliges ergaenzt, zieht den Wert mit. */
.stat__label {
  display: block;
  color: var(--ti-fg);
  font-weight: 600;
  font-size: 0.875rem;
  line-height: 1.3;
  min-height: 2.6em;
  max-width: 18ch;
}

.stat__note {
  display: block;
  margin-top: var(--ti-s-2);
  color: var(--ti-fg-3);
  font-size: 0.75rem;
  line-height: 1.35;
  max-width: 20ch;
}

.stat-source {
  font-size: var(--ti-fs-body-s);
  color: var(--ti-fg-3);
  margin: 0;
}

/* --- Kundenstimmen (Ergebnisse) --- */
.quote-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--ti-s-5);
}

.quote {
  margin: 0;
  background-color: var(--ti-paper);
  border: 1px solid var(--ti-line);
  border-radius: var(--ti-r-2);
  padding: var(--ti-s-6);
}

.quote__text {
  font-style: normal;
  margin-bottom: var(--ti-s-4);
}

.quote__author {
  color: var(--ti-fg-2);
  font-size: var(--ti-fs-body-s);
  font-weight: 600;
}

/* ==========================================================================
   9b. CASE STUDIES (#cases)
   Jede Referenz ist eine eigene Kachel: heller Kartenkoerper mit 8px-Radius
   (Marken-Maximum), duenner Kante und flacher Tiefe, unten buendig
   abgeschlossen von der schwarzen Ergebnis-Leiste. Vorher trennten nur
   Linien - die Zusammengehoerigkeit einer Referenz war dadurch nicht
   ablesbar.

   Kein gleichfoermiges Karten-Grid: die Kacheln stehen einspaltig
   untereinander, Kopf und Anzeige wechseln ab 1024px die Seite
   (.case--flip). Innenabstand liegt als --case-pad an der Kachel, damit
   die Ergebnis-Leiste per negativem Rand exakt bis an die Kante laeuft.
   ========================================================================== */
/* Kopf der Sektion steht auf jeder Breite mittig - wie im Portfolio.
   max-width: none, damit die Headline auf dem Desktop in EINE Zeile passt:
   .section__head wuerde sie sonst auf 65ch der Fliesstext-Schrift begrenzen,
   das reicht fuer "Starke Ergebnisse fuer starke Unternehmen." nicht. */
.cases__head {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}

.cases__head h2 {
  max-width: none;
  margin-inline: auto;
}

.cases__head .section__intro {
  margin-inline: auto;
}

.cases__list {
  display: flex;
  flex-direction: column;
  /* Seit 2026-10-28 wie die Case Studies der anderen Leistungsseiten
     (`sektionen/CaseStudies.astro`): lange Anlaufstrecke zwischen den Karten. */
  gap: var(--ti-s-8);
}
@media (min-width: 1024px) {
  .cases__list { gap: clamp(10rem, 55svh, 28rem); }
}

/* --- Stapel-Effekt: die Referenzen schieben sich beim Scrollen
   uebereinander und treten dabei zurueck (Kundenwunsch September 2026).

   Die Mechanik ist position: sticky - jede Kachel bleibt unter dem Header
   stehen, die naechste laeuft darueber. Das Zuruecktreten (kleiner werden,
   abdunkeln) haengt an zwei Custom Properties, die js/main.js (Abschnitt 16)
   je Frame setzt.

   Drei Punkte, die zusammengehoeren und beim Umbau leicht auseinanderfallen:

   1. VERKLEINERT WIRD MIT scale, NICHT MIT transform. Die Kacheln tragen
      .reveal, und das setzt transform: translateY(16px) mitsamt einer
      500ms-Transition darauf. Ein transform: scale() hier wuerde die
      Einblendung ueberschreiben - und laege es unter .is-visible, liefe der
      Stapelwert durch dieselbe 500ms-Transition und haengte sichtbar hinterher.
      Die eigenstaendige scale-Eigenschaft ist davon unabhaengig: sie wird
      nicht transitioniert und rechnet sich mit dem translate der Einblendung
      zusammen, statt es zu ersetzen.

   2. transform-origin liegt OBEN (50% 0). Nur dann bleibt die Oberkante beim
      Verkleinern stehen - die ist der sichtbare Teil einer gestapelten
      Kachel. Nebenbei haelt das die Rechnung in main.js stabil: die dort
      gemessene Oberkante wandert durch das Verkleinern nicht.

   3. SEIT DEM 23.09.2026 KEIN SCHLEIER MEHR: der Inhalt der verdeckten Akte
      blendet aus, ueberstehende Teile schneidet js/main.js per clip-path ab.

   Gestapelt wird erst ab 1024px. Darunter sind die Akten 1000 bis 1600px
   hoch, also bis zum Zweieinhalbfachen des Fensters - eine Kachel bliebe
   dort ueber tausend Scrollpixel lang stehen, bevor die naechste kommt.
   Das liest sich als haengende Seite, nicht als Effekt. Ohne JS und bei
   prefers-reduced-motion stehen die Kacheln ebenfalls schlicht
   untereinander (.is-stacked setzt nur JS).

   DIE KLEBEHOEHE IST GERECHNET, NICHT GESETZT. Eine feste Hoehe waere
   entweder zu gross (auf einem 900px hohen Notebook liegt der Viewport bei
   rund 790px, die groesste Akte bei 774px - die Kachel klebte dann so weit
   unten, dass ihre Ergebnis-Leiste nie ins Bild kaeme) oder unnoetig klein.
   min() nimmt deshalb den kleineren von zwei Werten: den Wunschabstand
   unter dem Header, und den Abstand, bei dem die groesste Kachel gerade
   noch vollstaendig ins Fenster passt. Auf hohen Fenstern gewinnt der
   Wunschabstand und die Kacheln stapeln sich sauber unter dem Header; auf
   flachen rutscht der Stapel nach oben, notfalls mit negativem Wert ueber
   den Fensterrand hinaus. In JEDEM Fall bleibt die Ergebnis-Leiste
   erreichbar - und genau darum geht es, sie traegt die Kennzahlen.

   JEDE AKTE KLEBT 14px TIEFER ALS DIE VORIGE (--case-stagger). Ohne diese
   Staffelung klebten alle auf derselben Hoehe, die verdeckte Kachel laege
   also exakt hinter der naechsten - und weil sie beim Zuruecktreten auch
   noch schmaler wird, waere von ihr nichts mehr zu sehen. Der Effekt liefe
   dann zwar, waere aber unsichtbar. Mit der Staffelung schaut von jeder
   erledigten Akte ein Streifen heraus und der Stapel wird ablesbar.

   --cases-stack-tallest (Hoehe der groessten Akte), --cases-stack-n (Anzahl)
   und --case-stack-i (Position, 0-basiert) setzt js/main.js, Abschnitt 16.
   Gerechnet wird hier: so bleibt der Breakpoint und jedes Mass im
   Stylesheet. Fehlen die Werte, faellt alles auf den Wunschabstand
   zurueck. --- */
@media (min-width: 1024px) {
  html.js .cases__list.is-stacked {
    --case-stagger: 1.5rem; /* seit 2026-10-28 wie auf den anderen Leistungsseiten (--raum-6) */
  }

  html.js .cases__list.is-stacked .case {
    position: sticky;
    /* Der verdichtete Header plus Luft. Nicht --header-h: bis die Kacheln
       drankommen, ist laengst gescrollt und der Header verdichtet.
       Der Platz fuer die volle Staffelung geht vom verfuegbaren Raum ab -
       sonst rutschte die UNTERSTE Kachel des Stapels aus dem Fenster. */
    top: calc(
      min(
        calc(var(--header-h-scrolled) + 1rem),
        calc(
          100vh - var(--cases-stack-tallest, 0px) - var(--ti-s-5) -
            (var(--cases-stack-n, 1) - 1) * var(--case-stagger)
        )
      ) + var(--case-stack-i, 0) * var(--case-stagger)
    );
    scale: var(--case-stack-scale, 1);
    transform-origin: 50% 0;
  }

  /* Seit dem 23.09.2026: statt eines Schleiers blendet der Inhalt der
     verdeckten Akte aus, und was unter der naechsten herausragen wuerde,
     wird abgeschnitten (js/main.js, Abschnitt 16). So ueberschneidet sich
     sichtbar nichts, auch bei unterschiedlich hohen Akten. */
  html.js .cases__list.is-stacked .case > * {
    opacity: var(--case-stack-fade, 1);
  }
}

/* --- Seit dem 2026-10-21 im Look der Case Studies der anderen Seiten
   (Kundenwunsch: alle Case Studies gleich, `components/sektionen/
   CaseStudies.astro` und die Karten der Startseite): schwarze Karte mit
   goldener Kante 2px und leisem Goldschimmer, Nummer im goldenen Kasten,
   Kundenname in Versalien, darunter die Branche, gruener Titel mit dem
   groessten Nutzen, Felder als dunkle Kacheln (Projekt, besetzte Stellen),
   das Ergebnis gruen hervorgehoben mit grossen Kennzahlen. Rechts die
   Anzeigen, so gross wie die Spalte zulaesst. Die Sektion steht auf Schwarz
   (.section--dark). Die Flaeche ist deckend, sonst scheinen beim Stapeln die
   Karten darunter durch. --- */
.case {
  --case-pad: clamp(1.25rem, 3vw, 2.75rem);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--ti-s-5);
  padding: var(--case-pad);
  color: var(--ti-paper);
  border: 2px solid var(--ti-gold);
  border-radius: var(--ti-r-3);
  background:
    radial-gradient(120% 90% at 100% 0%, rgba(220, 152, 50, 0.1), transparent 62%),
    var(--ti-black);
  box-shadow: 0 -20px 50px -30px rgba(0, 0, 0, 0.9);
}

/* Unter 1024 Pixeln eine Spalte: die linke Spalte loest sich auf, damit die
   Anzeigen direkt unter dem Projekttext stehen und nicht erst nach allen
   Feldern. */
.case__spalte {
  display: contents;
}

.case__kopf   { order: 1; }
.case__titel  { order: 2; }
.case__spalte > .case__feld:not(.case__data):not(.case__result) { order: 3; }
.case__media  { order: 4; }
.case__data   { order: 5; }
.case__result { order: 6; }

.case__kopf {
  display: flex;
  align-items: center;
  gap: var(--ti-s-4);
}

.case__nummer {
  flex: none;
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border: 1px solid var(--ti-gold);
  border-radius: var(--ti-r-1);
  font-family: var(--ti-display);
  font-size: 1.125rem;
  font-weight: 800;
  line-height: 1;
  color: var(--ti-gold);
}

.case__kopf-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.section--dark .case__name,
.case__name {
  margin: 0;
  font-family: var(--ti-sans);
  font-size: 0.875rem;
  font-weight: 800;
  line-height: 1.3;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ti-paper);
}

.case__name .dot-mark {
  width: 0.4em;
  height: 0.4em;
}

.case__branch {
  margin: 0;
  max-width: none;
  font-size: 0.75rem;
  color: rgba(255, 255, 255, 0.75);
}

.case__titel {
  margin: 0;
  max-width: none;
  font-family: var(--ti-display);
  font-size: clamp(1.25rem, 2vw, 1.5rem);
  font-weight: 800;
  line-height: 1.2;
  color: var(--ti-green-fg);
}

.case__feld {
  display: flex;
  flex-direction: column;
  gap: var(--ti-s-2);
  padding: var(--ti-s-4);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--ti-r-2);
  background-color: #1c1c1c;
}

.case__feld-titel,
.case__data-title {
  margin: 0;
  font-family: var(--ti-label);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--ti-gold);
}

.case__context {
  margin: 0;
  max-width: none;
  font-size: 0.875rem;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.75);
}

.case__context strong {
  color: var(--ti-paper);
  font-weight: 700;
}

/* --- Besetzte Stellen als Strichliste im Feld --- */
.case__roles {
  margin: 0;
  padding: 0;
  list-style: none;
}

.case__roles li {
  display: flex;
  align-items: baseline;
  gap: var(--ti-s-3);
  padding-block: var(--ti-s-2);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  font-size: 0.875rem;
  color: rgba(255, 255, 255, 0.75);
}

.case__roles li:last-child {
  border-bottom: 0;
  padding-block-end: 0;
}

.case__roles-num {
  flex: none;
  min-width: 3rem;
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: 1.125rem;
  line-height: 1;
  color: var(--ti-paper);
  font-variant-numeric: tabular-nums;
}

/* --- Ergebnis: gruene Kante und Schleier wie auf den Leistungsseiten, die
   beiden belegten Zahlen gross nebeneinander. Der Schleier liegt als
   Verlaufsebene ueber der Grundfarbe, damit die Flaeche deckend bleibt. --- */
.case__feld--ergebnis {
  border: 2px solid var(--ti-green-fg);
  border-left-width: 4px;
  background:
    linear-gradient(rgba(76, 195, 138, 0.12), rgba(76, 195, 138, 0.12)),
    #1c1c1c;
}

.case__feld--ergebnis .case__feld-titel {
  color: var(--ti-green-fg);
}

.case__figures {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ti-s-2) var(--ti-s-6);
}

.case__figure {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 var(--ti-s-2);
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--ti-paper);
}

.case__figure b {
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  line-height: 1;
  letter-spacing: -0.015em;
  color: var(--ti-green-fg);
  font-variant-numeric: tabular-nums;
}

.case__stamp {
  margin: 0;
  max-width: none;
  display: inline-flex;
  align-items: center;
  gap: var(--ti-s-2);
  font-size: 0.8125rem;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.75);
}

.case__stamp::before {
  content: "";
  flex: none;
  width: 8px;
  height: 8px;
  background-color: var(--ti-green-fg);
}

/* Limitless laeuft noch: Rahmendaten statt Ergebnis, deshalb neutral statt
   gruen. Gruen bleibt den belegten Zahlen vorbehalten. */
.case__feld--ergebnis:has(.case__figures--running) {
  border-color: rgba(255, 255, 255, 0.35);
  background: #1c1c1c;
}

.case__feld--ergebnis:has(.case__figures--running) .case__feld-titel {
  color: var(--ti-gold);
}

.case__figures--running .case__figure b {
  color: var(--ti-paper);
}

.case__feld--ergebnis:has(.case__figures--running) .case__stamp::before {
  background-color: var(--ti-gold);
}

/* --- Original-Anzeigen. Jedes Creative behaelt sein echtes Format, nichts
   wird beschnitten. Zwei Anzeigen stehen nebeneinander, eine einzelne
   bekommt die volle Spaltenbreite (hochkant begrenzt). --- */
.case__media {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
  gap: var(--ti-s-4);
}

.case__shot {
  margin: 0;
  flex: 1 1 0;
  min-width: 0;
  max-width: 26rem;
}

.case__shot img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--ti-r-2);
  box-shadow: 0 18px 40px -20px rgba(0, 0, 0, 0.9);
}

.case__shot--portrait {
  flex: 0 1 auto;
  width: min(100%, 17rem);
}

.case__shot--desktop {
  display: none;
}

.case__shot--video .case__video-frame {
  position: relative;
  overflow: hidden;
  border-radius: var(--ti-r-2);
  background-color: var(--ti-black);
  aspect-ratio: 9 / 16;
  box-shadow: 0 18px 40px -20px rgba(0, 0, 0, 0.9);
}

.case__shot figcaption {
  margin-top: var(--ti-s-3);
  font-family: var(--ti-label);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-size: 0.75rem;
  color: rgba(255, 255, 255, 0.6);
}

/* Zwei Anzeigen als versetztes Paar (Steinmeister, SAS Connect): jede gut
   sechs Zehntel der Spalte breit, die zweite rechts unten ueber der ersten.
   So stehen beide deutlich groesser als nebeneinander und fuellen die Hoehe
   der Karte. Die Unterschrift der ersten steht oben, die der zweiten unten
   rechts, damit keine verdeckt wird. */
.case__media--paar {
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: 0;
}

.case__media--paar .case__shot {
  flex: none;
  width: 62%;
  max-width: none;
}

.case__media--paar .case__shot:first-of-type {
  align-self: flex-start;
  display: flex;
  flex-direction: column-reverse;
}

.case__media--paar .case__shot:first-of-type figcaption {
  margin: 0 0 var(--ti-s-3);
}

.case__media--paar .case__shot:last-of-type {
  position: relative;
  align-self: flex-end;
  margin-top: -24%;
  text-align: right;
}

.case__media--paar .case__shot:last-of-type img {
  outline: 4px solid var(--ti-black);
}

.case__shot figcaption {
  overflow-wrap: anywhere;
}

/* Ab 1024 Pixeln zwei Spalten wie auf den anderen Seiten: links Kopf, Titel
   und Felder, rechts die Anzeigen, senkrecht mittig und so gross wie die
   Spalte zulaesst. */
@media (min-width: 1024px) {
  .case {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
    gap: clamp(1.5rem, 3vw, 2.75rem);
    align-items: center;
  }

  .case__spalte {
    display: flex;
    flex-direction: column;
    gap: var(--ti-s-4);
    min-width: 0;
  }

  .case__media {
    align-self: center;
  }

  .case__shot--desktop {
    display: block;
  }

  .case__shot--portrait {
    width: min(100%, 19rem);
  }

  .case__media--quad .case__shot {
    flex: 0 1 calc(50% - var(--ti-s-4) / 2);
  }

  .case__media--paar .case__shot {
    width: 64%;
  }
}

@media (max-width: 480px) {
  .case__name {
    letter-spacing: 0.16em;
  }
}

.case__video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.case__video--embed {
  border: 0;
}

/* --- Zwei-Klick-Video: Poster + Einwilligung statt sofortigem Iframe ---
   Der Schleier ist ein Verlauf von unten, kein flaechiger Schwarzfilm: das
   Standbild ist das eigentliche Argument (echte Anzeige, echter Mitarbeiter)
   und soll sichtbar bleiben. Nur unter dem Button verdichtet er sich so
   weit, dass Label und Hinweiszeile sicher lesbar sind. */
.video-consent {
  position: relative;
  width: 100%;
  height: 100%;
}

.video-consent__poster {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.video-consent__veil {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: var(--ti-s-3);
  padding: var(--ti-s-5);
  text-align: center;
  background: linear-gradient(
    to top,
    rgba(14, 14, 14, 0.94) 0%,
    rgba(14, 14, 14, 0.88) 22%,
    rgba(14, 14, 14, 0.55) 42%,
    rgba(14, 14, 14, 0.12) 62%,
    rgba(14, 14, 14, 0) 78%
  );
}

.video-consent__btn {
  display: inline-flex;
  align-items: center;
  gap: var(--ti-s-3);
  min-height: 44px;
  padding: var(--ti-s-3) var(--ti-s-5);
  background-color: var(--ti-gold);
  color: var(--ti-ink);
  font-family: var(--ti-label);
  font-size: var(--ti-fs-body-s);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: var(--ti-r-2);
  transition:
    background-color var(--ti-dur-base) var(--ti-ease-standard),
    transform var(--ti-dur-base) var(--ti-ease-standard);
}

/* Gleiche Reaktion wie der Haupt-CTA: Gold-Schein statt Farbwechsel. */
.video-consent__btn:hover,
.video-consent__btn:focus-visible {
  transform: translateY(-2px) scale(1.015);
  box-shadow: 0 10px 28px rgba(220, 152, 50, 0.42);
}

.video-consent__icon svg {
  display: block;
  width: 1.15em;
  height: 1.15em;
}

/* 0.78 Weiss auf dem dichten Teil des Verlaufs = ueber 9:1. Der Hinweis
   muss lesbar sein, er ist die Einwilligung. */
.video-consent__note {
  margin: 0;
  max-width: 26ch;
  color: rgba(255, 255, 255, 0.78);
  font-size: var(--ti-fs-caption);
  line-height: 1.4;
}

/* --- Abschluss der Sektion: nur der CTA, mittig - dieselbe Fusszeile wie
   unter dem Portfolio und dem Vergleich. Er steht ausserhalb von
   .cases__list: innerhalb wuerde ihn der Stapel-Effekt mitnehmen und der
   Knopf klebte als sechste "Referenz" unter dem Header. --- */
.cases__foot {
  margin-top: var(--ti-s-7);
  display: flex;
  justify-content: center;
}

/* ==========================================================================
   9d. EINBLICKE IN DEN WERBEANZEIGENMANAGER (#einblicke)
   Die Screenshots kommen in sehr unterschiedlichen Seitenverhaeltnissen
   (breite Tabellen, mal 5:1, mal 10:1). Statt sie zu beschneiden, bekommt
   jeder denselben Fensterrahmen: die Leiste mit den drei Punkten ist das
   verbindende Element, das Bild darin behaelt sein eigenes Mass.

   Mobil ist der Bildbereich waagerecht scrollbar (die Tabelle waere sonst
   auf Handybreite nicht mehr lesbar), deshalb traegt er tabindex="0" - er
   muss auch per Tastatur scrollbar sein.
   ========================================================================== */
.proof__head {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}

.proof__head h2 {
  max-width: none;
  margin-inline: auto;
}

/* "Werbeanzeigenmanager" ist ein langes Wort: seit die Headlines 2026-10-26
   groesser sind (30 Pixel auf dem Handy), passt es unter rund 390 Pixeln nur
   mit etwas kleinerer Schrift in die Zeile, ohne getrennt zu werden. */
@media (max-width: 400px) {
  .proof__head h2 { font-size: min(var(--ti-fs-h2), calc((100vw - 3rem) / 11.2)); }
}

.proof__head .section__intro {
  margin-inline: auto;
  max-width: 56ch;
}

/* minmax(0, 1fr) statt 1fr: sonst wachsen die Rahmen auf die Mindestbreite
   ihres Inhalts (46rem) und schieben die ganze Seite waagerecht auf. Scrollen
   soll nur .shot__view, nie das Dokument. */
.proof__list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--ti-s-7);
}

.shot,
.shot__frame,
.shot__view {
  min-width: 0;
}

.shot {
  margin: 0;
}

.shot__frame {
  background-color: var(--ti-paper);
  border: 1px solid var(--ti-line);
  border-radius: var(--ti-r-3);
  overflow: hidden;
  box-shadow:
    0 1px 2px rgba(14, 14, 14, 0.04),
    0 18px 36px -22px rgba(14, 14, 14, 0.4);
}

/* Fensterleiste: signalisiert "echter Screenshot aus einem Werkzeug" und
   faengt die unterschiedlichen Bildhoehen optisch auf. */
.shot__bar {
  display: flex;
  align-items: center;
  gap: var(--ti-s-3);
  padding: var(--ti-s-3) var(--ti-s-4);
  background-color: var(--ti-n-100);
  border-bottom: 1px solid var(--ti-line);
}

.shot__dots {
  display: inline-flex;
  gap: 6px;
  flex: none;
}

.shot__dots i {
  width: 8px;
  height: 8px;
  border-radius: var(--ti-r-1);
  background-color: var(--ti-n-300);
}

.shot__chrome {
  font-family: var(--ti-label);
  font-weight: 500;
  font-size: var(--ti-fs-label);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ti-fg-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.shot__view {
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
}

.shot__view:focus-visible {
  outline: 2px solid var(--ti-gold);
  outline-offset: -2px;
}

/* Mindestbreite, damit die Tabellen auf dem Handy lesbar bleiben - darunter
   wird gescrollt statt geschrumpft. */
.shot__img {
  display: block;
  width: 100%;
  min-width: 46rem;
  height: auto;
}

.shot__caption {
  margin-top: var(--ti-s-4);
  color: var(--ti-fg-2);
  font-size: var(--ti-fs-body-s);
  text-align: center;
  max-width: 62ch;
  margin-inline: auto;
}

.proof__hint {
  margin-top: var(--ti-s-5);
  margin-inline: auto;
  color: var(--ti-fg-3);
  font-size: var(--ti-fs-body-s);
  text-align: center;
  max-width: none;
}

.proof__foot {
  margin-top: var(--ti-s-7);
  display: flex;
  justify-content: center;
}

/* ==========================================================================
   9c. VERGLEICH (#vergleich)
   Zwei Tafeln nebeneinander: links schwarz (wir), rechts hell (die anderen).
   Der Kontrast der Flaechen traegt die Aussage, deshalb kommt die rechte
   Tafel bewusst zurueckhaltend daher - ohne Rot-Grell und ohne Spott.

   Kopf, Tafel-Koepfe und CTA stehen mittig. Die Zeilen selbst bleiben
   linksbuendig: mit Icon davor waere zentrierter Text nicht mehr lesbar.
   ========================================================================== */
.versus__head {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}

/* max-width: none wie bei den Cases - damit die Headline ab Tablet in eine
   Zeile passt. Mobil bricht sie am Container. */
.versus__head h2 {
  max-width: none;
  margin-inline: auto;
}

.versus__head .section__intro {
  margin-inline: auto;
}

.versus__grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--ti-s-6);
}

.versus__panel {
  position: relative;
  padding: var(--ti-s-6) var(--ti-s-5);
  border-radius: var(--ti-r-3);
  border: 1px solid var(--ti-line);
  text-align: center;
}

/* Unsere Tafel ist die laute: schwarzer Grund mit gruenem Schimmer, gruene
   Kante, gruener Schein. Dazu eine gruene Oberkante als Signal. */
.versus__panel--us {
  background-color: var(--ti-black);
  background-image:
    radial-gradient(120% 80% at 50% 0%, rgba(47, 143, 95, 0.34), transparent 62%);
  border-color: rgba(76, 195, 138, 0.55);
  color: var(--ti-paper);
  box-shadow:
    0 0 0 1px rgba(76, 195, 138, 0.16),
    0 22px 48px -26px rgba(31, 107, 71, 0.85);
}

.versus__panel--us::before,
.versus__panel--others::before {
  content: "";
  position: absolute;
  inset: -1px -1px auto;
  height: 4px;
  border-radius: var(--ti-r-3) var(--ti-r-3) 0 0;
}

.versus__panel--us::before {
  background-color: var(--ti-green-fg);
}

/* Die Gegenseite bleibt flach und leise: kein Schein, keine Tiefe, gedaempfte
   Schrift. Der Unterschied entsteht aus der Zurueckhaltung, nicht aus Spott. */
.versus__panel--others {
  background-color: var(--ti-paper);
  border-color: var(--ti-n-200);
  box-shadow: none;
}

.versus__panel--others::before {
  background-color: var(--ti-n-300);
}

/* Hover nur mit echtem Zeigegeraet: auf dem Handy bliebe der Zustand nach
   einem Tap an der Tafel haengen. Beide Tafeln heben sich an, jede aber in
   ihrer eigenen Tonlage - unsere legt gruen nach, die Gegenseite bekommt
   nur so viel Tiefe, dass die Reaktion spuerbar ist. */
.versus__panel {
  transition:
    transform var(--ti-dur-slow) var(--ti-ease-standard),
    box-shadow var(--ti-dur-slow) var(--ti-ease-standard),
    border-color var(--ti-dur-slow) var(--ti-ease-standard);
}

@media (hover: hover) and (pointer: fine) {
  .versus__panel--us:hover {
    transform: translateY(-6px);
    border-color: var(--ti-green-fg);
    box-shadow:
      0 0 0 1px rgba(76, 195, 138, 0.35),
      0 32px 60px -28px rgba(31, 107, 71, 0.95);
  }

  .versus__panel--us:hover .versus__panel-title {
    color: var(--ti-green-fg);
  }

  .versus__panel--others:hover {
    transform: translateY(-4px);
    border-color: var(--ti-n-300);
    box-shadow: 0 18px 34px -24px rgba(14, 14, 14, 0.45);
  }
}

/* Die "vs."-Plakette sitzt zwischen den Tafeln. */
.versus__vs {
  justify-self: center;
  order: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  margin-block: calc(-1 * var(--ti-s-3));
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: 1rem;
  letter-spacing: -0.01em;
  color: var(--ti-paper);
  background-color: var(--ti-black);
  border-radius: var(--ti-r-3);
  box-shadow: 0 8px 20px -12px rgba(14, 14, 14, 0.6);
}

.versus__panel--us { order: 1; }
.versus__panel--others { order: 3; }

.versus__panel-title {
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: var(--ti-fs-h3-display);
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin: 0 0 var(--ti-s-2);
}

.versus__panel--us .versus__panel-title {
  color: var(--ti-paper);
}

/* Die Gegenseite steht bewusst leiser - sie ist der Vergleichswert, nicht
   das Angebot. */
.versus__panel--others .versus__panel-title {
  color: var(--ti-fg-2);
}

.versus__panel-sub {
  font-size: var(--ti-fs-body-s);
  margin: 0 0 var(--ti-s-5);
  max-width: none;
}

.versus__panel--us .versus__panel-sub {
  color: rgba(255, 255, 255, 0.7);
}

.versus__panel--others .versus__panel-sub {
  color: var(--ti-fg-3);
}

.versus__list {
  list-style: none;
  margin: 0;
  padding: 0;
  text-align: left;
}

.versus__row {
  display: flex;
  align-items: flex-start;
  gap: var(--ti-s-4);
  padding-block: var(--ti-s-4);
  border-top: 1px solid var(--ti-line);
}

.versus__panel--us .versus__row {
  border-top-color: rgba(255, 255, 255, 0.12);
}

/* Marker: quadratisch wie das Signatur-Motiv, nicht rund. Gruen steht wie
   in den Case-Kacheln fuer "belegt/erreicht", die Gegenseite bleibt neutral
   grau statt alarmrot. */
.versus__mark {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: var(--ti-r-2);
  margin-top: 0.1rem;
}

/* Gefuellt statt getoent: der Haken ist gruen unterlegt, das Kreuz rot.
   Beide Glyphen stehen auf ihrer Flaeche mit ueber 5:1 Kontrast. */
.versus__panel--us .versus__mark {
  background-color: var(--ti-green-fg);
  color: var(--ti-black);
  box-shadow: 0 0 0 4px rgba(76, 195, 138, 0.16);
}

.versus__panel--others .versus__mark {
  background-color: var(--ti-danger);
  color: var(--ti-paper);
  box-shadow: 0 0 0 4px rgba(196, 56, 44, 0.1);
}

.versus__text {
  display: block;
}

.versus__label {
  display: block;
  font-weight: 700;
  font-size: var(--ti-fs-body);
  margin-bottom: var(--ti-s-1);
}

.versus__panel--others .versus__label {
  color: var(--ti-fg-2);
  font-weight: 600;
}

.versus__note {
  display: block;
  font-size: var(--ti-fs-body-s);
}

.versus__panel--us .versus__note {
  color: rgba(255, 255, 255, 0.66);
}

.versus__panel--others .versus__note {
  color: var(--ti-fg-3);
}

.versus__foot {
  margin-top: var(--ti-s-7);
  display: flex;
  justify-content: center;
}

/* --- Funnel-Strecke: echte Schrittfolge, mobil horizontal scrollbar.
   Liegt in derselben Kachel-Optik wie die Referenzen darueber - mit der
   frueheren schwarzen Trennlinie haette der Block nach den Kacheln wie ein
   Rest ausgesehen. --- */
/* ==========================================================================
   4b. FUNNEL-SHOWCASE (eigener, dunkler Abschnitt mit Karussell)
   Bewusst schwarz als Abwechslung zum hellen Case-Abschnitt darueber und als
   eigenstaendiger Block. Globale Headline + Subheadline (auf Desktop zentriert),
   darunter ein full-bleed Karussell: jede Folie ist 100% des Viewports breit
   und snappt. Wischen (Touch/Trackpad), Pfeile und Punkte wechseln den Funnel.
   Die Nav ist Progressive Enhancement (html.js).
   ========================================================================== */
.funnels-section {
  background-color: var(--ti-black);
  color: var(--ti-paper);
  overflow: hidden;
}

.funnels__head {
  max-width: 60ch;
  margin-bottom: var(--ti-s-6);
}

/* Auf Desktop mittig zentriert; mobil linksbuendig (Default). Breit genug,
   dass die groessere Headline in eine Zeile passt und die Subheadline (mit
   eigener, schmalerer max-width) auf zwei Zeilen umbricht. */
@media (min-width: 1024px) {
  .funnels__head {
    max-width: 60rem;
    margin-inline: auto;
    text-align: center;
  }
}

.funnels__title {
  font-family: var(--ti-display);
  font-weight: 900;
  /* Groesser als eine Standard-h3, damit die globale Headline heraussticht.
     Mobil bleibt sie auf der 26px-Stufe (Mobile Headline-Skala), ab ca.
     1200px erreicht sie 2,75rem (44px). */
  font-size: clamp(1.625rem, 1.1rem + 2.2vw, 2.75rem);
  line-height: 1.06;
  letter-spacing: -0.02em;
  margin: 0 0 var(--ti-s-4);
  color: var(--ti-paper);
}

.funnels__lead {
  color: rgba(255, 255, 255, 0.78);
  margin: 0;
}

/* Auf Desktop die Subheadline auf genau zwei Zeilen begrenzen (mit Montserrat
   liegt die 3->2-Zeilen-Schwelle bei ~840px; 56rem/896px haelt sicheren
   Abstand dazu). */
@media (min-width: 1024px) {
  .funnels__lead {
    max-width: 56rem;
    margin-inline: auto;
  }
}

/* Full-bleed Viewport: horizontales Scroll-Snap, Scrollbar versteckt (die Nav
   uebernimmt die Steuerung). Die Folien tragen KEINEN gap - so ist
   scrollLeft = index * clientWidth und das JS kann exakt rechnen. */
.funnels__viewport {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.funnels__viewport::-webkit-scrollbar {
  display: none;
}

.fnl {
  flex: 0 0 100%;
  min-width: 0;
  scroll-snap-align: start;
}

.fnl__inner {
  max-width: min(100%, 84rem);
  margin-inline: auto;
  padding-inline: clamp(1rem, 4vw, 2.5rem);
  padding-block: var(--ti-s-2);
}

/* Kunde + Branche auf einer Ebene, linksbuendig (auf jeder Breite - Wunsch
   fuer mobil und Desktop). Erst der Kundenname, dann die Branche daneben;
   sitzt am linken Rand der Folie, leicht links versetzt zur zentrierten
   Sektions-Headline. Bricht die Branche bei schmalen Folien um, rutscht sie
   linksbuendig unter den Namen. */
.fnl__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: var(--ti-s-3);
  row-gap: var(--ti-s-1);
  text-align: left;
  margin-bottom: var(--ti-s-5);
}

.fnl__client {
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: var(--ti-fs-h3-display);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--ti-paper);
  margin: 0;
}

.fnl__branch {
  font-family: var(--ti-label);
  font-weight: 600;
  font-size: var(--ti-fs-body-l);
  letter-spacing: 0.02em;
  color: var(--ti-gold);
  margin: 0;
}

/* Alle fuenf Screenshots einer Folie in einer Reihe. Bewusst auch mobil
   5-spaltig (die Folie zeigt den ganzen Funnel auf einen Blick, gewischt wird
   zum naechsten Kunden - nicht innerhalb der Folie). */
.fnl__strip {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(0.35rem, 1.4vw, 1rem);
  align-items: start;
}

/* Geraeterahmen. Bewusste Ausnahme von der Marken-Regel "max 8px Radius":
   hier ist die Rundung kein UI-Element, sondern die Kontur eines Handys -
   mit 8px wirkten die Kacheln wie Karten, nicht wie Screenshots.
   Der Rahmen laeuft ueber vw-clamps mit, weil dieselbe Reihe von rund
   62px (Handy, 5 Spalten) bis rund 230px (Desktop) breit wird. Auf dem
   schwarzen Abschnitt traegt eine helle Haarlinie die Kontur, nicht die
   Flaeche - ein schwarzer Rahmen auf Schwarz waere unsichtbar. */
.fnl__phone {
  margin: 0;
  min-width: 0;
  padding: clamp(3px, 0.85vw, 11px);
  background:
    linear-gradient(155deg, #4a4a52 0%, #2a2a30 38%, #1d1d21 100%);
  border: 1px solid rgba(255, 255, 255, 0.26);
  border-radius: clamp(10px, 2.7vw, 32px);
  box-shadow:
    0 22px 40px -22px rgba(0, 0, 0, 0.95),
    inset 0 1px 0 rgba(255, 255, 255, 0.16);
}

.fnl__phone img {
  display: block;
  width: 100%;
  height: auto;
  border: 0;
  /* Immer eine Spur enger als der Rahmen, sonst steht in den Ecken ein
     heller Zwickel zwischen Bild und Kante. */
  border-radius: clamp(7px, 1.9vw, 22px);
  background-color: var(--ti-paper);
}

/* --- Steuerung (Pfeile + Punkte). Nur mit JS sichtbar. --- */
.funnels__nav {
  display: none;
  align-items: center;
  justify-content: center;
  gap: var(--ti-s-4);
  margin-top: var(--ti-s-5);
}

html.js .funnels__nav {
  display: flex;
}

.funnels__arrow {
  width: 2.75rem;
  height: 2.75rem;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.06);
  color: var(--ti-paper);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition:
    background-color var(--ti-dur-base) var(--ti-ease-standard),
    border-color var(--ti-dur-base) var(--ti-ease-standard),
    color var(--ti-dur-base) var(--ti-ease-standard);
}

.funnels__arrow:hover:not(:disabled),
.funnels__arrow:focus-visible:not(:disabled) {
  border-color: var(--ti-gold);
  color: var(--ti-gold);
  background-color: rgba(255, 255, 255, 0.1);
}

.funnels__arrow:disabled {
  opacity: 0.3;
  cursor: default;
}

/* Kein gap: die Buttons sind 44px breit (Trefferflaeche), der optische
   Abstand entsteht aus der Differenz zum 0,6rem-Quadrat darin. Ein zusaetz-
   licher gap wuerde die Punktreihe auseinanderziehen; ein negativer Rand
   wuerde die Trefferflaechen ueberlappen lassen. */
.funnels__dots {
  display: inline-flex;
  gap: 0;
}

/* Marken-Quadrat als Punkt. Sichtbar bleiben es 0,6rem - die Trefferflaeche
   ist aber 44x44px (WCAG 2.5.8): der Button traegt die Groesse, das Quadrat
   zeichnet ::before. Ohne das waere der einzige Hinweis darauf, dass es drei
   Referenz-Funnel gibt, auf dem Handy kaum treffbar. */
.funnels__dot {
  position: relative;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.funnels__dot::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 1px;
  background-color: rgba(255, 255, 255, 0.28);
  transform: translate(-50%, -50%);
  transition:
    background-color var(--ti-dur-base) var(--ti-ease-standard),
    transform var(--ti-dur-base) var(--ti-ease-standard);
}

.funnels__dot.is-active::before {
  background-color: var(--ti-gold);
  transform: translate(-50%, -50%) scale(1.2);
}

/* --- FAQ-Accordion (nativ via details/summary, ohne JS bedienbar) --- */
/* Kopf und Spalte stehen mittig (Kundenwunsch August 2026). Die Fragen
   selbst bleiben linksbuendig: eine Zeile mit Text links und Aufklapp-Zeichen
   rechts kippt zentriert sofort aus der Achse, und zwoelf verschieden lange
   zentrierte Fragen haetten zwoelf verschiedene Anfangskanten - nichts, woran
   das Auge beim Ueberfliegen entlanglaeuft. Zentriert wird der Block, nicht
   der Inhalt. */
.faq__head {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}

.faq__head h2 {
  max-width: none;
  margin-inline: auto;
}

.faq__head .section__intro {
  max-width: 52ch;
  margin-inline: auto;
}

.faq {
  display: grid;
  gap: var(--ti-s-4);
  max-width: 800px;
  margin-inline: auto;
}

.faq__item {
  background-color: var(--ti-paper);
  border: 1px solid var(--ti-line);
  border-radius: var(--ti-r-2);
  overflow: hidden;
}

.faq__question {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ti-s-5);
  padding: var(--ti-s-5) var(--ti-s-6);
  font-family: var(--ti-sans);
  font-weight: 700;
  font-size: var(--ti-fs-body-l);
  color: var(--ti-fg);
}

.faq__question::-webkit-details-marker {
  display: none;
}

/* Rotierender +/- Indikator: zwei Balken, der vertikale rotiert bei
   [open] um 90 Grad auf den horizontalen - visuell "+" -> "-". */
.faq__icon {
  position: relative;
  flex: 0 0 auto;
  width: 1rem;
  height: 1rem;
}

.faq__icon::before,
.faq__icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  background-color: var(--ti-gold);
}

.faq__icon::before {
  width: 100%;
  height: 2px;
  transform: translate(-50%, -50%);
}

.faq__icon::after {
  width: 2px;
  height: 100%;
  transform: translate(-50%, -50%);
  transition: transform var(--ti-dur-base) var(--ti-ease-standard);
}

.faq__item[open] .faq__icon::after {
  transform: translate(-50%, -50%) rotate(90deg);
}

/* Oeffnen-Animation rein per CSS (grid-template-rows 0fr -> 1fr), damit sie
   auch ohne JS funktioniert. Das author-CSS "display:grid" ueberschreibt
   die UA-Regel "details:not([open]) > *:not(summary){display:none}". */
.faq__answer {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--ti-dur-slow) var(--ti-ease-standard);
}

.faq__item[open] .faq__answer {
  grid-template-rows: 1fr;
}

.faq__answer-inner {
  overflow: hidden;
  min-height: 0;
}

.faq__answer-inner p {
  padding: var(--ti-s-1) var(--ti-s-6) var(--ti-s-5);
  color: var(--ti-fg-2);
  margin: 0;
}

/* CTA am Ende einer Antwort. Der Innenabstand der Antwort haengt am <p>,
   nicht am Container - deshalb sitzt der Knopf ebenfalls in einem <p> und
   erbt ihn. Nur das obere Polster faellt weg: den Abstand zum Text traegt
   schon dessen padding-bottom. */
.faq__cta {
  padding-top: 0;
}

/* --- Abschluss-CTA --- */
/* --- Abschluss-CTA: Checkliste links, Termin-Panel rechts.
   Uebernimmt den Aufbau der frueheren Angebot-Sektion, aber auf Schwarz -
   der Abschluss bleibt damit die Klammer zum Hero. Kopf mittig, die
   Checkliste und das Panel linksbuendig (mit Haken davor waere zentrierter
   Text unlesbar). --- */
.final-cta {
  position: relative;
  background-color: var(--ti-black);
  color: var(--ti-paper);
}

.final-cta__head {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}

.final-cta__title {
  max-width: none;
  margin-inline: auto;
  color: var(--ti-paper);
}

.final-cta__intro {
  color: rgba(255, 255, 255, 0.75);
  max-width: 60ch;
  margin: 0 auto;
}

.final-cta__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--ti-s-6);
  align-items: start;
}

.final-cta__eyebrow {
  font-family: var(--ti-label);
  font-weight: 600;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  font-size: var(--ti-fs-label);
  color: rgba(255, 255, 255, 0.6);
  margin-bottom: var(--ti-s-5);
}

.final-cta__checklist li {
  position: relative;
  padding-left: var(--ti-s-6);
  margin-bottom: var(--ti-s-4);
  color: rgba(255, 255, 255, 0.82);
  font-size: var(--ti-fs-body-l);
}

.final-cta__checklist li:last-child {
  margin-bottom: 0;
}

/* Gold als Haken auf Schwarz ist unkritisch - die AA-Ausnahme gegen
   Gold-Text gilt nur auf hellem Grund. */
.final-cta__checklist li::before {
  content: "\2713";
  position: absolute;
  left: 0;
  top: 0;
  font-weight: 700;
  color: var(--ti-gold);
}

.final-cta__panel {
  background-color: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--ti-r-3);
  padding: var(--ti-s-6) var(--ti-s-5);
}

.final-cta__panel-meta {
  display: block;
  font-family: var(--ti-label);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-size: var(--ti-fs-label);
  color: rgba(255, 255, 255, 0.6);
  margin-bottom: var(--ti-s-3);
}

.final-cta__panel-title {
  color: var(--ti-paper);
  margin-bottom: var(--ti-s-3);
}

.final-cta__panel-text {
  color: rgba(255, 255, 255, 0.75);
  margin-bottom: var(--ti-s-6);
}

.final-cta__btn {
  width: 100%;
}

/* Die Bewertung sitzt direkt unter dem Button und traegt dort denselben
   dunklen Chrome wie im Hero. */
.final-cta__panel .rating {
  margin-top: var(--ti-s-5);
}

/* Seit 2026-09-30 steht hier der Kontakt-Funnel (Astro-Komponente
   `ui/KontaktFunnel`, bringt Flaeche und Rahmen selbst mit) statt des Panels. */
.final-cta__funnel {
  min-width: 0;
}

/* ==========================================================================
   10. FOOTER
   Schwarzer Grund, weisse Wortmarke, Abschluss-Panel im Brand-Ton,
   Kontakt-/Rechtliches-Spalten, Copyright-Zeile.
   ========================================================================== */
.site-footer {
  background-color: var(--ti-black);
  color: var(--ti-paper);
  padding-block: var(--ti-s-9) var(--ti-s-6);
  /* Duenne Trennkante zum ebenfalls schwarzen Abschluss-CTA (Sektion 9):
     macht die schwarze Klammer Hero...Abschluss-CTA/Footer als bewusste
     Komposition lesbar statt als zusammengelaufene Flaeche. */
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.site-footer__inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--ti-s-8);
}

.site-footer__brand {
  display: flex;
  flex-direction: column;
  gap: var(--ti-s-3);
}

.site-footer__logo {
  display: inline-flex;
  align-items: center;
  margin: 0;
}

.site-footer__logo img {
  height: 2.25rem;
  width: auto;
}

.site-footer__logo-word {
  font-family: var(--ti-display);
  font-weight: 900;
  font-size: 1.35rem;
  letter-spacing: -0.01em;
  color: var(--ti-paper);
  line-height: 1;
}

.site-footer__logo-sub {
  font-family: var(--ti-label);
  font-weight: 500;
  font-size: 0.6875rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
}

.site-footer__tagline {
  color: rgba(255, 255, 255, 0.68);
  font-size: var(--ti-fs-body-s);
  max-width: 42ch;
  margin: 0;
}

.site-footer__heading {
  font-family: var(--ti-label);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  margin: 0 0 var(--ti-s-3);
}

.site-footer__address {
  font-style: normal;
  color: rgba(255, 255, 255, 0.78);
  font-size: var(--ti-fs-body-s);
}

.site-footer__address p {
  margin: 0 0 var(--ti-s-2);
  max-width: none;
}

.site-footer__address p:last-child {
  margin-bottom: 0;
}

/* Die Kontakt- und Rechtslinks standen bei 16px Hoehe deutlich unter der
   44px-Mindestgroesse (WCAG 2.5.8). Telefonnummer und E-Mail sind auf dem
   Handy ein direkter Conversion-Pfad. padding-block statt Schriftgroesse:
   die Zeilen behalten ihre Position, nur die Flaeche waechst. */
.site-footer__address a,
.site-footer__social a,
.site-footer__legal-list a {
  display: inline-block;
  padding-block: var(--ti-s-3);
}

.site-footer__address a {
  color: rgba(255, 255, 255, 0.78);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(255, 255, 255, 0.3);
}

.site-footer__address a:hover,
.site-footer__address a:focus-visible {
  color: var(--ti-gold);
  text-decoration-color: var(--ti-gold);
}

.site-footer__social {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ti-s-4);
  margin-top: var(--ti-s-4);
}

.site-footer__social a {
  color: rgba(255, 255, 255, 0.78);
  font-size: var(--ti-fs-body-s);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(255, 255, 255, 0.3);
}

.site-footer__social a:hover,
.site-footer__social a:focus-visible {
  color: var(--ti-gold);
  text-decoration-color: var(--ti-gold);
}

.site-footer__legal-list {
  display: flex;
  flex-direction: column;
  gap: var(--ti-s-2);
}

.site-footer__legal-list a {
  color: rgba(255, 255, 255, 0.78);
  font-size: var(--ti-fs-body-s);
}

.site-footer__legal-list a:hover,
.site-footer__legal-list a:focus-visible {
  color: var(--ti-gold);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.site-footer__bottom {
  margin-top: var(--ti-s-8);
  padding-top: var(--ti-s-5);
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}

.site-footer__copyright {
  color: rgba(255, 255, 255, 0.55);
  font-size: var(--ti-fs-caption);
  margin: 0;
}

/* ==========================================================================
   11. REVEAL-ANIMATIONEN (Progressive Enhancement)
   Startzustand nur setzen, wenn JS aktiv ist (html.js). Ohne JS bleibt
   alles sofort sichtbar. js/main.js schaltet zusaetzlich einen Sicherheits-
   Fallback (Timeout), falls der IntersectionObserver nie feuert.
   ========================================================================== */
html.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 500ms var(--ti-ease-standard),
    transform 500ms var(--ti-ease-standard);
  will-change: opacity, transform;
}

html.js .reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* ==========================================================================
   12. BREAKPOINTS (min-width, mobil-zuerst)
   ========================================================================== */

/* --- >= 480px: kleine Phones quer / grosse Phones --- */
@media (min-width: 480px) {
  .hero__cta {
    width: auto;
  }

  .hero__actions {
    flex-direction: row;
    align-items: center;
  }
}

/* --- >= 768px: Tablets --- */
@media (min-width: 768px) {
  /* Ab Tablet ist Platz fuer die Kennzahl-Notiz unter dem Label. */
  .hero__stat-note {
    display: block;
  }

  /* Groessere Logos und mehr Luft dazwischen; Dauer haelt das Tempo bei
     rund 49px/s (2880px Gruppenbreite / 58s). */
  .hero__logos {
    --reel-speed-1: 58s;
    --reel-speed-2: 58s;
    --logo-w: 11rem;
    --logo-gap: 4rem;
  }

  .hero__stat {
    padding: var(--ti-s-5) var(--ti-s-4) 0 0;
  }

  .hero__stat + .hero__stat {
    padding-left: var(--ti-s-4);
  }


  /* Ab hier passen die Tabellen in die Breite - der Scroll-Hinweis
     verschwindet, weil nichts mehr zu scrollen ist. */
  .shot__img {
    min-width: 0;
  }

  .proof__hint {
    display: none;
  }


  /* Mehr Platz -> groessere Kacheln und etwas mehr Luft dazwischen. Die
     Laufgeschwindigkeit bleibt gleich, die Baender wirken dadurch ruhiger. */
  .portfolio {
    --reel-h: 17rem;
    --reel-gap: var(--ti-s-4);
    /* Gruppenbreite = Hoehe * Summe der Seitenverhaeltnisse + Abstaende,
       nicht mehr Kachelzahl * feste Breite: die Kacheln sind unterschiedlich
       breit. 272px * 25.2 + 29 * 16 = 7318px / 146.5s = 50px/s, dasselbe
       Tempo wie mobil. tools/creatives-import.sh rechnet den Wert nach jedem
       Lauf aus. */
    --reel-speed-1: 146.5s;
    --reel-speed-2: 36s;
  }

  .reel__placeholder-label {
    font-size: var(--ti-fs-label);
    letter-spacing: 0.2em;
  }

  /* Ohne diese Zeile begrenzt .section__head den Kopf auf 65ch der
     Fliesstext-Schrift - die zweizeilige Headline braucht hier mehr. */
  .portfolio__head {
    max-width: none;
  }

  body {
    font-size: 1.0625rem;
  }

  /* Ab Tablet ist Platz fuer das lange Label und die normale Button-Groesse. */
  .site-header__cta {
    padding: var(--ti-s-3) var(--ti-s-5);
    /* Eine Stufe unter dem Standard-Button und enger gesperrt: der
       Header-CTA soll den Weg zeigen, nicht mit dem Hero-CTA um
       Aufmerksamkeit konkurrieren. Stand hier bis September 2026 auf
       0.8125rem/0.22em - letzteres noch aus der Zeit der schmalen
       Schrift. */
    font-size: 0.75rem;
    --btn-track: 0.10em;
  }

  .site-header__cta-short {
    display: none;
  }

  .site-header__cta-long {
    display: inline;
  }

  /* Vier Spalten nebeneinander: die waagerechte Trennlinie entfaellt, die
     senkrechte steht vor jeder Spalte ausser der ersten. */
  .stat-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    margin-bottom: var(--ti-s-8);
  }

  .stat-grid:last-child {
    margin-bottom: 0;
  }

  .stat {
    padding: var(--ti-s-6) var(--ti-s-5) var(--ti-s-6) 0;
    border-bottom: 0;
  }

  .stat:nth-child(-n + 2) {
    border-bottom: 0;
  }

  .stat:not(:first-child) {
    padding-left: var(--ti-s-5);
    padding-right: var(--ti-s-5);
    border-left: 1px solid var(--ti-line);
  }

  .stat:last-child {
    padding-right: 0;
  }

  .quote-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Mittig statt oben ausgerichtet: die Checkliste ist deutlich kuerzer als
     das Panel, oben angeschlagen bliebe links eine grosse Leerflaeche. */
  .final-cta__grid {
    grid-template-columns: 1fr 1fr;
    gap: var(--ti-s-7);
    align-items: center;
  }

  /* Termin-Panel links, Checkliste rechts. Die Lesereihenfolge im Markup
     bleibt Checkliste -> Panel (erst was dich erwartet, dann der Termin),
     getauscht wird nur die Darstellung ab zwei Spalten. Mobil stapelt es
     unveraendert in Markup-Reihenfolge. */
  .final-cta__col {
    order: 2;
  }

  .final-cta__panel,
  .final-cta__funnel {
    order: 1;
  }

  .final-cta__panel {
    padding: var(--ti-s-7) var(--ti-s-6);
  }


  /* Zwei Tafeln nebeneinander. Anders als bei #vergleich reicht dafuer schon
     das Tablet-Mass: die Zeilen sind kurze Saetze ohne Zusatzzeile. */
  /* Kein align-items: start - die beiden Tafeln sollen gleich hoch
     abschliessen, sonst wirkt die kuerzere Seite abgeschnitten. */
  .fit__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .site-footer__inner {
    grid-template-columns: 2fr 1fr 1fr;
    gap: var(--ti-s-6);
  }

  .site-footer__bottom {
    grid-column: 1 / -1;
  }
}

/* --- >= 1024px: kleiner Desktop --- */
@media (min-width: 1024px) {
  .hero {
    padding-block: clamp(4rem, 7vw, 6.5rem) 0;
    /* Ab hier bestimmt das Raster die Breite, nicht mehr die 44rem-Kante. */
    --hero-media-w: 100%;
  }

  /* Fenster links, Pitch rechts daneben. Das Fenster bekommt die groessere
     Spalte - es ist das Element, das oben stehen soll. */
  .hero__main {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: clamp(2rem, 4vw, 3.5rem);
    align-items: center;
    margin-bottom: var(--ti-s-8);
  }

  .hero__pitch {
    gap: var(--ti-s-6);
  }

  /* Auf Desktop steht der Pitch wieder in Lesereihenfolge: Text, CTA,
     Bewertung. Nur mobil wird der CTA nach oben gezogen. */
  .hero__pitch > .hero__subtitle { order: 1; }
  .hero__pitch > .hero__actions  { order: 2; }
  .hero__pitch > .rating         { order: 3; }

  /* Bewusst kleiner als das Token-Maximum (6rem): oberhalb von rund 72px
     schiebt die dreizeilige Headline das VSL-Fenster auf 800px hohen
     Notebooks unter die Falz. Ohne Fenster stand hier zwischen August und
     September 2026 clamp(3.5rem, 6.1vw, 6rem) - mit dem Fenster ist dieser
     Platz nicht mehr frei. Die Headline bleibt trotzdem die groesste Type
     der Seite. */
  .hero__title {
    max-width: 17ch;
    margin-bottom: var(--ti-s-6);
  }

  .stat-grid {
    grid-template-columns: repeat(3, 1fr);
  }

  .stat-grid--4 {
    grid-template-columns: repeat(4, 1fr);
  }


  .cases__list {
    gap: var(--ti-s-9);
  }

  /* Ab hier laufen die vier Schritte waagerecht: die Linie liegt hinter den
     Nummern und wird von links nach rechts gezeichnet. Sie beginnt und endet
     in der Mitte der aeusseren Nummern, deshalb die 12,5%-Einzuege (vier
     gleich breite Spalten). */
  .steps-wrap {
    max-width: none;
  }

  .steps {
    flex-direction: row;
    /* stretch statt flex-start: zusammen mit flex:1 an der Karte stehen die
       vier Karten dadurch gleich hoch, egal wie lang ihr Text ist. */
    align-items: stretch;
    gap: var(--ti-s-5);
  }

  .steps__item {
    flex: 1 1 0;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: var(--ti-s-5);
  }

  .steps__line {
    left: 12.5%;
    right: 12.5%;
    top: 1.625rem;
    bottom: auto;
    width: auto;
    height: 2px;
  }

  .steps__line-fill {
    transform: scaleX(var(--steps-progress, 1));
    transform-origin: left;
  }

  .steps__body {
    width: 100%;
    flex: 1 1 auto;
  }

  .steps__text {
    max-width: 34ch;
    margin-inline: auto;
  }

  /* Die drei Gruende erst hier nebeneinander: auf dem Tablet waeren die
     Karten rund 220px breit, die "X statt Y"-Headline liefe darin ueber
     fuenf Zeilen. */
  .reasons {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--ti-s-6);
  }

  .reason {
    padding: var(--ti-s-7) var(--ti-s-6);
  }

  .fit__panel {
    padding: var(--ti-s-7) var(--ti-s-6);
  }

  /* Team: Bild und Text nebeneinander. Die Bildspalte steht auf `auto` und
     nimmt genau die Breite an, die sich aus --team-h und dem
     Seitenverhaeltnis ergibt - dadurch sind beide Fotos gleich hoch und
     trotzdem jeweils im richtigen Format. Die untere Zeile dreht per
     `order` die Seiten; im Markup steht das Bild weiter vorn, damit es
     mobil zuerst kommt. */
  .team__rows {
    gap: var(--ti-s-9);
  }

  .team__row {
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: clamp(2.5rem, 5vw, 4.5rem);
  }

  .team__photo {
    --team-h: clamp(17rem, 26vw, 25rem);
    height: var(--team-h);
    width: auto;
  }

  .team__row--crew {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .team__row--crew .team__photo { order: 2; }
  .team__row--crew .team__body  { order: 1; }

  /* Die drei Gruende erst hier nebeneinander: auf dem Tablet waeren die
     Karten rund 220px breit, die "X statt Y"-Headline liefe darin ueber
     fuenf Zeilen. */
  .reasons {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--ti-s-6);
  }

  .reason {
    padding: var(--ti-s-7) var(--ti-s-6);
  }

  .fit__panel {
    padding: var(--ti-s-7) var(--ti-s-6);
  }

  /* Team: Bild und Text nebeneinander. Die Bildspalte steht auf `auto` und
     nimmt genau die Breite an, die sich aus --team-h und dem
     Seitenverhaeltnis ergibt - dadurch sind beide Fotos gleich hoch und
     trotzdem jeweils im richtigen Format. Die untere Zeile dreht per
     `order` die Seiten; im Markup steht das Bild weiter vorn, damit es
     mobil zuerst kommt. */
  .team__rows {
    gap: var(--ti-s-9);
  }

  .team__row {
    grid-template-columns: auto minmax(0, 1fr);
    column-gap: clamp(2.5rem, 5vw, 4.5rem);
  }

  .team__photo {
    --team-h: clamp(17rem, 26vw, 25rem);
    height: var(--team-h);
    width: auto;
  }

  .team__row--crew {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .team__row--crew .team__photo { order: 2; }
  .team__row--crew .team__body  { order: 1; }

  /* Erst ab hier nebeneinander: darunter waeren die Zeilen zu schmal und
     die Paare stuenden ohnehin untereinander. */
  .versus__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--ti-s-6);
    align-items: start;
  }

  .versus__panel {
    padding: var(--ti-s-7) var(--ti-s-6);
  }

  /* Unsere Tafel steht eine Spur hoeher und traegt mehr Luft - dieselbe
     Hierarchie wie bei einem hervorgehobenen Tarif. */
  .versus__panel--us {
    margin-top: calc(-1 * var(--ti-s-4));
    padding-bottom: calc(var(--ti-s-7) + var(--ti-s-4));
  }

  /* Aus dem Fluss genommen und genau in die Fuge gesetzt. */
  .versus__vs {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    margin-block: 0;
    z-index: 1;
    border: 2px solid var(--ti-bg-alt);
  }


}

/* --- >= 1280px: grosser Desktop ---
   (Die Hero-Headline steht bereits ab 1024px auf 17ch, siehe oben.) */

/* ==========================================================================
   12b. TAP-TARGETS AUF TOUCH-GERAETEN
   Textlinks sind nur so hoch wie ihre Zeile (~18px). Auf dem Handy ist das
   zu klein - WCAG 2.2 (2.5.8) verlangt mindestens 24x24 CSS-Pixel, die
   Plattform-Guidelines von Apple und Google empfehlen 44px. Greift per
   (pointer: coarse) nur dort, wo mit dem Finger bedient wird.
   ========================================================================== */
@media (pointer: coarse) {
  .site-footer__address a,
  .site-footer__social a,
  .site-footer__legal-list a,
  .site-header__logo {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  /* Die Eltern muessen die neue Hoehe uebernehmen: ein inline-flex-Link
     mit min-height ragt sonst aus der Zeilenbox seines <li>/<p> heraus und
     hinterlaesst darunter unerklaerlichen Leerraum. */
  .site-footer__address p,
  .site-footer__social li,
  .site-footer__legal-list li {
    display: flex;
  }

  /* Die Links bringen ihre Hoehe jetzt selbst mit - die zusaetzlichen
     Abstaende der Container wuerden den Footer sonst auseinanderziehen. */
  .site-footer__address p {
    margin-bottom: 0;
  }

  .site-footer__legal-list,
  .site-footer__social {
    gap: 0;
  }
}

/* ==========================================================================
   13. prefers-reduced-motion
   Bewegungen/Transitions praktisch abschalten, Reveal- und Hero-Elemente
   sofort sichtbar. Smooth-Scroll deaktivieren. Parallax wird zusaetzlich in
   js/main.js per matchMedia-Guard gar nicht erst gestartet.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  /* Animationen (Marquee, Puls, Hero-Stagger, Parallax) sind hier die
     eigentlichen Ausloeser und werden abgeschaltet.

     Transitions werden NICHT abgeschaltet, sondern auf 120ms verkuerzt:
     "reduzierte Bewegung" heisst nicht "keine Rueckmeldung". Ein globales
     0.001ms nimmt auch den Hover-Zustand der Buttons, das Aufklappen des
     FAQ-Accordions und den Wechsel der Umschalter in #loesung mit - der
     Nutzer verliert damit die Bestaetigung, dass seine Eingabe angekommen
     ist. Was bleibt, sind Farb- und Deckkraftwechsel; die Wege durch den
     Raum nimmt der Block darunter einzeln heraus. */
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 120ms !important;
    scroll-behavior: auto !important;
  }

  /* Kein Element bewegt sich beim Hover/Fokus - die Zustaende bleiben
     ueber Farbe, Kante und Schatten trotzdem ablesbar. */
  .btn--cta:focus-visible,
  .btn--cta:hover,
  .reason:hover .reason__icon,
  .case__shot:hover img,
  .case__shot--video:hover .case__video-frame,
  .versus__panel--us:hover,
  .versus__panel--others:hover {
    transform: none;
  }

  /* Der aktive Punkt behaelt seine Zentrierung, verliert nur die
     Vergroesserung - sonst springt er aus der Reihe. */
  .funnels__dot.is-active::before {
    transform: translate(-50%, -50%);
  }

  html.js .reveal {
    opacity: 1;
    transform: none;
  }

  html.js .hero--animate-in .hero__word,
  html.js .hero--animate-in.hero--animated .hero__word {
    opacity: 1;
    transform: none;
  }

  .scroll-progress__fill {
    transition: none;
  }

  .hero__flag,
  .hero__dots {
    transform: none !important;
  }

  /* Die Baender stehen still. Die globale Regel oben wuerde die Animation
     sonst in 0.001ms bis zum Endzustand durchlaufen lassen - das Band waere
     um -50% verschoben. Stattdessen: Track zurueck auf 0, Kopie raus (sonst
     stuenden alle Kacheln doppelt im Scrollbereich) und die Zeile von Hand
     scrollbar machen, damit alle Kacheln erreichbar bleiben. */
  .marquee {
    overflow-x: auto;
    -webkit-mask-image: none;
    mask-image: none;
  }

  .marquee__track {
    animation: none !important;
    transform: none !important;
  }

  .marquee__group[aria-hidden="true"] {
    display: none;
  }

  /* Die Linie steht sofort voll gezeichnet, die Nummern im Endzustand -
     js/main.js startet die Scroll-Animation hier gar nicht erst. */
  .steps-wrap {
    --steps-progress: 1;
  }

  .steps__num,
  .steps__line-fill {
    transition: none;
  }

  .reel__img,
  .reel__placeholder {
    transition: none;
  }

  .reel:hover .reel__img,
  .reel:hover .reel__placeholder {
    transform: none;
  }
}

/* ==========================================================================
   14. EINWILLIGUNG (Banner + Einstellungen)

   Das Markup baut js/consent.js, deshalb steht hier nur die Optik. Die
   Flaeche ist schwarz wie Hero, Funnel und Footer - der Banner soll als
   Teil der Marke lesbar sein und nicht als fremdes Plugin.

   Zwei Regeln, die nicht Kosmetik sind:

   - "Ablehnen" und "Akzeptieren" liegen nebeneinander, beide 44px hoch,
     beide mit einem Klick erreichbar. Ein grauer, kleiner Ablehnen-Link
     neben einem fetten Gold-Button waere keine freie Einwilligung.
   - Der Banner sitzt unten und ist KEIN Overlay ueber der ganzen Seite:
     die Seite bleibt lesbar und bedienbar, solange nicht entschieden ist.
     Nur die Einstellungen legen sich als Dialog darueber.
   ========================================================================== */

.ti-cc {
  /* Der Container selbst faengt keine Klicks ab - sonst laege eine
     unsichtbare Flaeche ueber der ganzen Seite. */
  pointer-events: none;
}

.ti-cc__banner,
.ti-cc__backdrop {
  pointer-events: auto;
}

/* ---------- Banner ---------- */
.ti-cc__banner {
  position: fixed;
  inset: auto 0 0 0;
  z-index: var(--z-consent);
  display: none;
  background: var(--ti-black);
  border-top: 2px solid var(--ti-gold);
  box-shadow: 0 -12px 32px rgba(14, 14, 14, .28);
  color: var(--ti-paper);
  padding: 1.25rem 1rem calc(1.25rem + env(safe-area-inset-bottom, 0px));
}

.ti-cc__banner.is-open {
  display: block;
}

.ti-cc__inner {
  width: min(72rem, 100%);
  margin-inline: auto;
  display: grid;
  gap: 1rem;
}

.ti-cc__eyebrow {
  font-family: var(--ti-label);
  font-size: var(--ti-fs-label);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--ti-gold);
  margin: 0 0 .35rem;
}

.ti-cc__copy {
  font-size: var(--ti-fs-body-s);
  line-height: 1.6;
  color: rgba(255, 255, 255, .82);
  margin: 0;
  max-width: 62ch;
}

.ti-cc__copy a,
.ti-cc__foot a {
  color: var(--ti-paper);
  text-decoration: underline;
  text-underline-offset: .18em;
}

.ti-cc__actions {
  display: flex;
  flex-wrap: wrap;
  gap: .625rem;
}

/* ---------- Buttons ----------
   Bewusst nicht .btn: der Marken-Button traegt Quadrat-Punkt, Sperrung
   und Gold-Glow. Drei davon nebeneinander in einer Leiste waeren lauter
   als die Seite dahinter. Gleiche Hoehe (44px Trefferflaeche), gleiche
   Schrift, nur die Fuellung unterscheidet Zustimmen von Ablehnen. */
.ti-cc__btn {
  flex: 1 1 auto;
  min-height: 44px;
  padding: .625rem 1.1rem;
  border-radius: var(--ti-r-1);
  border: 1px solid rgba(255, 255, 255, .28);
  background: transparent;
  color: var(--ti-paper);
  font-family: var(--ti-sans);
  font-size: var(--ti-fs-body-s);
  font-weight: 600;
  cursor: pointer;
  transition:
    background-color var(--ti-dur-base) var(--ti-ease-standard),
    border-color var(--ti-dur-base) var(--ti-ease-standard),
    color var(--ti-dur-base) var(--ti-ease-standard);
}

.ti-cc__btn--primary {
  background: var(--ti-gold);
  border-color: var(--ti-gold);
  color: var(--ti-black);
}

@media (hover: hover) and (pointer: fine) {
  .ti-cc__btn--ghost:hover {
    background: rgba(255, 255, 255, .1);
    border-color: rgba(255, 255, 255, .5);
  }

  .ti-cc__btn--primary:hover {
    background: #E8A945;
    border-color: #E8A945;
  }
}

.ti-cc__btn:focus-visible {
  outline: 2px solid var(--ti-gold);
  outline-offset: 2px;
}

/* ---------- Einstellungen (Dialog) ---------- */
.ti-cc__backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--z-consent-modal);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: rgba(14, 14, 14, .72);
  overflow-y: auto;
}

.ti-cc__backdrop.is-open {
  display: flex;
}

.ti-cc__modal {
  width: min(34rem, 100%);
  background: var(--ti-black);
  border: 1px solid rgba(255, 255, 255, .16);
  border-top: 2px solid var(--ti-gold);
  border-radius: var(--ti-r-3);
  color: var(--ti-paper);
  padding: 1.5rem;
  margin-block: auto;
}

.ti-cc__title {
  font-family: var(--ti-display);
  font-size: var(--ti-fs-h3);
  font-weight: 800;
  line-height: 1.15;
  color: var(--ti-paper);
  margin: 0 0 1.25rem;
}

.ti-cc__cat {
  border-top: 1px solid rgba(255, 255, 255, .14);
  padding-block: 1rem;
}

.ti-cc__cat-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: .4rem;
}

.ti-cc__cat-name {
  font-family: var(--ti-display);
  font-size: var(--ti-fs-body-l);
  font-weight: 700;
}

.ti-cc__cat-fixed {
  font-family: var(--ti-label);
  font-size: var(--ti-fs-label);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ti-gold);
}

.ti-cc__cat-desc {
  font-size: var(--ti-fs-body-s);
  line-height: 1.6;
  color: rgba(255, 255, 255, .72);
  margin: 0;
  max-width: none;
}

/* ---------- Schalter ----------
   Das Kaestchen liegt sichtbar unter dem Regler statt display:none - so
   bleibt es fuer Tastatur und Screenreader ein echtes Kaestchen, und der
   Fokusring haengt am Regler. */
.ti-cc__switch {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
}

.ti-cc__switch input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.ti-cc__slider {
  width: 3rem;
  height: 1.625rem;
  border-radius: var(--ti-r-pill);
  background: rgba(255, 255, 255, .2);
  border: 1px solid rgba(255, 255, 255, .28);
  position: relative;
  transition: background-color var(--ti-dur-base) var(--ti-ease-standard);
}

.ti-cc__slider::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 3px;
  width: 1.125rem;
  height: 1.125rem;
  border-radius: 50%;
  background: var(--ti-paper);
  transform: translateY(-50%);
  transition: transform var(--ti-dur-base) var(--ti-ease-standard);
}

.ti-cc__switch input:checked + .ti-cc__slider {
  background: var(--ti-gold);
  border-color: var(--ti-gold);
}

.ti-cc__switch input:checked + .ti-cc__slider::after {
  transform: translate(1.3125rem, -50%);
}

.ti-cc__switch input:focus-visible + .ti-cc__slider {
  outline: 2px solid var(--ti-gold);
  outline-offset: 2px;
}

/* Beschriftung nur fuer Screenreader - sichtbar steht der Name daneben. */
.ti-cc__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.ti-cc__modal-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .625rem;
  border-top: 1px solid rgba(255, 255, 255, .14);
  padding-top: 1.25rem;
}

.ti-cc__foot {
  font-size: var(--ti-fs-body-s);
  color: rgba(255, 255, 255, .6);
  margin: 1rem 0 0;
  text-align: center;
}

/* Ab Tablet steht der Text links und die Buttons rechts daneben: der
   Banner belegt dann eine statt drei Zeilen. */
@media (min-width: 768px) {
  .ti-cc__banner {
    padding-inline: 1.5rem;
  }

  .ti-cc__inner {
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: 1.75rem;
  }

  .ti-cc__actions {
    flex-wrap: nowrap;
  }

  .ti-cc__btn {
    flex: 0 0 auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .ti-cc__btn,
  .ti-cc__slider,
  .ti-cc__slider::after {
    transition-duration: var(--ti-dur-fast);
  }
}
