/* ============================================================
   TriCore — Video-Hero mit Scroll-Scrubbing
   Eigenständiges Modul: css/hero-video.css + js/hero-video.js
   Nutzt die Design-Tokens aus css/styles.css (--font, --ease, …),
   funktioniert dank Fallbacks aber auch standalone.

   Layout der Nav und der Headline folgen dem minimalen Pill-Entwurf:
   Nav-Elemente tragen ihren eigenen Hintergrund (schwarze bzw. hell-
   graue Pillen), die Headline steht unten links. Die Videomechanik
   (Stopps, Scrubbing, Headline-Wechsel) bleibt davon unberührt.
   ============================================================ */

.tc-hero-root {
  --tc-ink: #202a36;
  --tc-black: #0a0a0a;          /* Pill-Schwarz */
  --tc-chip: #f4f4f6;           /* Pill-Hellgrau lt. Spezifikation */
  --tc-chip-ink: #3a3a3f;
  --tc-ease-out: cubic-bezier(0.16, 1, 0.3, 1);

  /* Ein Raster für Nav und Headline: gleiche Kantenabstände links/rechts */
  --tc-pad-x: 16px;
  --tc-pad-y: 16px;
  /* 32 statt 28 px: mit 2 x 3 px Pillenrand ergibt das 38 px Hoehe –
     naeher am 44-px-Touch-Ziel, ohne die Nav sichtbar zu vergroebern. */
  --tc-ctl: 32px;               /* Durchmesser der runden Bedienelemente */
  --tc-hero-bottom: 5.5rem;     /* Abstand der Headline zur Unterkante */

  /* Wunschbreite des Logos. Die Datei (tricore-logo-tight.png) ist ohne
     Rand beschnitten, die Breite ist also die sichtbare Breite: auf dem
     Handy 250 px (55 px hoch), auf dem Desktop 300 px (65 px hoch). Das
     ist gut 20 % mehr Logo als frueher mit der randbehafteten Datei –
     bei niedrigerer Leiste. Bleibt weniger Platz, faellt das Logo ueber
     max-width zurueck – siehe .tcnav__logo. */
  --tc-logo-w: 250px;

  /* Masse der beiden Knopf-Pillen. Auf Desktop 30 % groesser. */
  --tc-btn-ctl: var(--tc-ctl);
  --tc-btn-font: 11px;
  --tc-btn-pad: 3px;
  --tc-btn-gap: 8px;
  --tc-btn-icon: 12px;

  position: relative;
  font-family: var(--font, "Inter", -apple-system, BlinkMacSystemFont,
    "Segoe UI", Roboto, Helvetica, Arial, sans-serif);
}

@media (min-width: 768px) {
  .tc-hero-root {
    --tc-pad-x: 32px;
    --tc-pad-y: 24px;
    --tc-ctl: 36px;
    --tc-hero-bottom: 3.5rem;
    --tc-logo-w: 300px;         /* 65 px hoch */

    /* Eine Stufe groesser als die alten 42/14/16: die Nav-Pillen sollen
       auf dem Desktop deutlicher als Bedienelemente auftreten. */
    --tc-btn-ctl: 46px;
    --tc-btn-font: 15px;
    --tc-btn-pad: 4px;
    --tc-btn-gap: 11px;
    --tc-btn-icon: 18px;
  }
}

/* ============================ NAV ============================ */
.tcnav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  /* Die Leiste selbst faengt keine Klicks ab – nur ihre Bedienelemente.
     So bleibt die Geste ueber der vollen Hero-Flaeche nutzbar. */
  pointer-events: none;
}

/* Kein Lichtschleier mehr noetig: jedes Nav-Element bringt seinen eigenen
   Hintergrund mit und ist damit auf jedem Videobild lesbar. */

/* ---------- Leiste nach dem Hero ----------
   js/main.js setzt .is-scrolled auf die Nav, sobald im Hero die erste
   Etappe laeuft oder der Hero verlassen ist. Dann legt sich eine
   weichgezeichnete Flaeche hinter Logo und Pillen.

   Die Flaeche ist helles Glas in Naturweiss, nicht mehr das dunkle
   Anthrazit der Seite: das Logo bleibt auf Kundenwunsch immer in seinen
   Originalfarben, und die schwarze Wortmarke braucht einen hellen Grund.
   Die Deckung liegt bei 45 %: der dunkle Seiteninhalt scheint kraeftig
   durch und toent die Leiste grau. Damit die schwarze Wortmarke darauf
   lesbar bleibt, behaelt das Logo seinen Lichtsaum (siehe .tcnav__logo).
   Der kraeftige Blur haelt das Durchscheinende ruhig. Ueber dem Video
   bleibt die Nav ohne Flaeche. */
.tcnav::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(255, 253, 249, 0.45);
  -webkit-backdrop-filter: saturate(180%) blur(34px);
  backdrop-filter: saturate(180%) blur(34px);
  border-bottom: 1px solid rgba(28, 27, 23, 0.08);
  /* Weicher Schatten nach unten: die Leiste liegt ueber dem dunklen
     Inhalt, statt wie ein aufgeklebter Streifen zu wirken. */
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.22);
  opacity: 0;
  transition: opacity 0.35s ease;
  pointer-events: none;
}
.tcnav.is-scrolled::before { opacity: 1; }
/* Klicks faengt die Leiste erst ab, wenn der Hero durchgescrollt ist –
   durch die Glasflaeche hindurch soll niemand auf dahinterliegenden
   Seiteninhalt klicken. Bewusst NICHT an .is-scrolled gebunden: die
   Flaeche erscheint schon waehrend der ersten Hero-Etappe, und dort
   muss die Wischgeste ueber der Leiste weiterhin das Video schalten. */
.tcnav.is-past-hero { pointer-events: auto; }

/* Die hellgrauen Pillen (Sprachwahl, Kontakt) verschwimmen sonst mit
   dem hellen Glas – eine Haarlinie haelt ihre Form. */
.tcnav.is-scrolled .tcnav__lang,
.tcnav.is-scrolled .tcnav__cta {
  box-shadow: inset 0 0 0 1px rgba(10, 10, 10, 0.1);
}

/* Drei Spalten: links die Notdienst-Pille (nur Desktop), in der Mitte das
   Logo, rechts das Menue. Beide Randspalten sind gleich breit (1fr), nur
   so steht das Logo wirklich in der Bildmitte. */
.tcnav__inner {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
  padding: var(--tc-pad-y) var(--tc-pad-x);
  animation: tc-nav-in 0.8s var(--tc-ease-out) both;
}

.tcnav__side {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}
/* Links das Menue samt Tag-Pille, rechts die Notdienst-Pille.
   position: relative traegt das Menue-Panel – es haengt deshalb immer
   unter seiner Pille, egal auf welcher Seite die gerade steht. */
.tcnav__side--start { justify-self: start; position: relative; }
.tcnav__side--end   { justify-self: end; }

.tcnav__brand,
.tcnav__menu,
.tcnav__cta,
.tcnav__lang,
.tcnav__mobile {
  pointer-events: auto;
}

/* ---------- Logo ---------- */
.tcnav__brand {
  display: flex;
  align-items: center;
  justify-self: center;
  /* Damit die Mittelspalte schrumpfen darf, wenn --tc-logo-w nicht
     zwischen die Randspalten passt. */
  min-width: 0;
  text-decoration: none;
}
.tcnav__logo {
  /* Ueber die Breite gesteuert, nicht ueber die Hoehe: so greift
     max-width: 100% (aus styles.css) und das Seitenverhaeltnis bleibt
     erhalten, statt das Bild zu stauchen. */
  width: var(--tc-logo-w);
  height: auto;
  display: block;
  /* Sehr weicher Lichtsaum – auf hellen Bildstellen unsichtbar, sichert
     die dunkle Wortmarke aber gegen dunkle Videobilder ab. */
  filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.6));
  /* Weicher Wechsel, wenn die dunkle Variante die Marke auf der
     Glasleiste auf Weiss dreht. */
  transition: filter 0.35s ease;
}

/* Unterhalb von 850 px steht das Logo links statt in der Mitte. Damit
   entfaellt die Zwangslage der mittigen Variante – die verlangt links wie
   rechts gleich viel Platz, also Logo + zweimal Menue-Pille, was auf ein
   Telefon nicht passt. Linksbuendig genuegt Logo + einmal Pille, und
   beides steht wieder in einer Zeile.

   Die Logospalte ist 1fr: sie bekommt genau das, was nach der Pille
   uebrig bleibt. Zusammen mit max-width: 100% (aus styles.css) schrumpft
   das Logo auf sehr schmalen Geraeten von selbst mit, statt in die Pille
   zu ragen. Die Notdienst-Pille bleibt hier ausgeblendet – neben Logo
   und Menue ist fuer sie erst ab 850 px Platz.

   Das Menue wechselt hier die Seite: auf dem Desktop steht es links,
   auf dem Handy rechts neben dem Logo. Das Panel folgt ihm.

   Der Block steht bewusst NACH .tcnav__brand: beide Regeln sind gleich
   spezifisch, ein Media-Query zaehlt dabei nicht mit. Weiter oben wuerde
   das justify-self: center der Basisregel gewinnen. */
@media (max-width: 849px) {
  .tcnav__inner {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "brand menu";
  }
  .tcnav__side--end   { display: none; }
  .tcnav__side--start { grid-area: menu; justify-self: end; }
  .tcnav__brand       { grid-area: brand; justify-self: start; }
}

/* Das Logo sass in der einzeiligen Nav zeitweise 10 px hoeher – auf
   Kundenwunsch steht es wieder auf der Mittelachse der Pillen. */

/* ---------- Runde Bedienelemente in den Pillen ---------- */
.tcnav__dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tc-btn-ctl);
  height: var(--tc-btn-ctl);
  flex-shrink: 0;
  border-radius: 50%;
}
.tcnav__dot svg {
  width: var(--tc-btn-icon);
  height: var(--tc-btn-icon);
  display: block;
  transition: transform 0.35s var(--tc-ease-out);
}
.tcnav__dot--light { background: #fff; color: var(--tc-black); }
.tcnav__dot--dark  { background: var(--tc-black); color: #fff; }

/* ---------- Menü-Pille (schwarz) ---------- */
.tcnav__menu {
  display: inline-flex;
  align-items: center;
  gap: var(--tc-btn-gap);
  padding: var(--tc-btn-pad) calc(var(--tc-btn-pad) * 5) var(--tc-btn-pad) var(--tc-btn-pad);
  border: 0;
  border-radius: 999px;
  background: var(--tc-black);
  color: #fff;
  font-family: inherit;
  font-size: var(--tc-btn-font);
  font-weight: 500;
  letter-spacing: 0.01em;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.22);
}
/* Aus dem Plus wird beim Öffnen ein Kreuz */
.tcnav__menu[aria-expanded="true"] .tcnav__dot svg { transform: rotate(45deg); }

/* Die fruehere Tag-Pille ("Technisches FM | Infrastrukturelles FM")
   ist auf Kundenwunsch entfallen – die Begriffe stehen jetzt in der
   Hero-Rubrikzeile. */

/* ---------- Sprach-Pille DE/EN (hellgrau, zwei Segmente) ----------
   Laut Briefing ein fixes Element der Hauptnavigation. Sie steht links
   bei der Menue-Pille, nicht rechts: die Randspalten des Nav-Rasters
   sind gleich breit (1fr auto 1fr), und rechts sitzt bereits die
   breitere Kontakt-Pille. Links kostet die Sprachwahl deshalb keine
   Breite der Logospalte – rechts wuerde sie das Logo zwischen 850 und
   1120 px zusammenschieben. */
.tcnav__lang {
  display: none;
  align-items: center;
  gap: 2px;
  height: var(--tc-ctl);
  padding: 0 3px;
  border-radius: 999px;
  background: var(--tc-chip);
}
.tcnav__lang-btn {
  padding: 0 9px;
  height: calc(var(--tc-ctl) - 6px);
  border: 0;
  border-radius: 999px;
  background: none;
  font-family: inherit;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.06em;
  line-height: 1;
  color: var(--tc-chip-ink);
  cursor: pointer;
  transition: background-color 0.2s ease, color 0.2s ease;
}
.tcnav__lang-btn[aria-pressed="true"] {
  background: var(--tc-black);
  color: #fff;
  cursor: default;
}
.tcnav__lang-btn[aria-pressed="false"]:hover { background: rgba(0, 0, 0, 0.07); }

/* Auf dem Desktop zieht die Sprachpille mit den grossen Knopf-Pillen
   mit. Steht bewusst NACH den Basisregeln: gleiche Spezifitaet, ein
   Media-Query zaehlt nicht mit – weiter oben wuerden die 11 px gewinnen. */
@media (min-width: 768px) {
  .tcnav__lang-btn { font-size: 12.5px; }
}

/* Zusammen mit der Notdienst-Pille ab 850 px – darunter steht die
   Sprachwahl im Menue-Panel. */
@media (min-width: 850px) {
  .tcnav__lang { display: inline-flex; }
}

/* ---------- Rechte Pille (hellgrau, schwarzer Knopf) ---------- */
.tcnav__cta {
  display: none;
  align-items: center;
  gap: var(--tc-btn-gap);
  padding: var(--tc-btn-pad) calc(var(--tc-btn-pad) * 5.5) var(--tc-btn-pad) var(--tc-btn-pad);
  border-radius: 999px;
  background: var(--tc-chip);
  color: var(--tc-black);
  font-size: var(--tc-btn-font);
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
}
.tcnav__cta .tcnav__dot svg {
  width: calc(var(--tc-btn-icon) + 2px);
  height: calc(var(--tc-btn-icon) + 2px);
}

/* Die Notdienst-Pille erscheint erst mit der einzeiligen Nav – darunter
   waere links neben dem Logo ohnehin kein Platz. */
@media (min-width: 850px) {
  .tcnav__cta { display: inline-flex; }
}
/* ---------- Menü-Panel ---------- */
/* Sitzt im selben Nav-Feld wie die Menue-Pille und haengt damit immer
   direkt unter ihr – auf dem Desktop linksbuendig, auf dem Handy
   rechtsbuendig (siehe Media-Query oben). */
.tcnav__mobile {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  min-width: 220px;
  padding: 8px;
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: saturate(180%) blur(20px);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  border: 1px solid rgba(0, 0, 0, 0.06);
  border-radius: 18px;
  box-shadow: 0 12px 40px rgba(15, 40, 70, 0.16),
    0 40px 90px rgba(15, 40, 70, 0.12);
}
.tcnav__mobile[hidden] { display: none; }
.tcnav__mobile a {
  /* 12 px statt 10: hebt die Zeilen auf rund 44 px Touch-Hoehe. */
  padding: 12px 14px;
  border-radius: 12px;
  font-size: 15px;
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--tc-black);
  text-decoration: none;
  transition: background-color 0.2s ease;
}
.tcnav__mobile a:hover { background: var(--tc-chip); }

/* Sprachwahl im Panel – ersetzt unterhalb von 850 px die Pille oben,
   damit die Umschaltung auf jeder Breite erreichbar bleibt. */
.tcnav__mobile-lang {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  padding: 12px 14px 4px;
  border-top: 1px solid rgba(0, 0, 0, 0.08);
}
.tcnav__mobile-lang > span {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #8b8b90;
}
.tcnav__mobile-lang .tcnav__lang { display: inline-flex; margin-left: auto; }

@media (min-width: 850px) {
  .tcnav__mobile-lang { display: none; }
}

/* Auf dem Handy steht die Menue-Pille rechts – das Panel richtet sich mit
   aus, sonst haengt es ueber den Rand hinaus. Muss NACH der Regel oben
   stehen: gleiche Spezifitaet, ein Media-Query zaehlt dabei nicht mit. */
@media (max-width: 849px) {
  .tcnav__mobile { left: auto; right: 0; }
}

/* ---------- Unterseiten (Impressum, Datenschutz) ----------
   Dort gibt es keinen Hero: die Leiste steht von Anfang an auf Glas
   (.is-scrolled und .is-past-hero stehen fest im HTML), und statt des
   Menues fuehrt die schwarze Pille zurueck zur Startseite. Die
   Sprachwahl bleibt auf jeder Breite sichtbar – ohne Menue gibt es
   kein Panel, das sie unterhalb von 850 px aufnehmen koennte. */
.tcnav--sub .tcnav__lang { display: inline-flex; }

/* Auf sehr schmalen Geraeten reicht der runde Knopf allein; der Text
   wuerde das Logo sonst unter die Lesbarkeitsgrenze druecken. */
@media (max-width: 479px) {
  .tcnav--sub .tcnav__menu { padding: var(--tc-btn-pad); }
  .tcnav--sub .tcnav__menu-label { display: none; }
}

/* ======================= SCROLL-HERO ======================= */
.tchero {
  position: relative;
  /* Der Hero belegt genau einen Bildschirm. Er braucht keine Scroll-
     Distanz mehr: die Etappen werden von Gesten ausgelöst, nicht von der
     Scrollposition. Tempo steuert STEP_MS in hero-video.js. */
  height: 100vh;
  height: 100svh;
}

.tchero__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  background: #1c1b17;
}

/* Standbild fest hinter dem Video.

   Bis hierher lag hinter dem <video> nur das dunkle #1c1b17. Sobald
   js/hero-video.js die fertig geladene Datei als Blob-Quelle setzt,
   setzt der Browser das Videoelement zurueck - fuer ein, zwei Takte
   zeichnet es gar nichts. Auf dem Telefon blitzte in dieser Luecke der
   dunkle Grund durch; das war das gemeldete Flackern beim Neuladen.

   Dasselbe Bild, das ohnehin schon als poster-Attribut steht, liegt
   deshalb dauerhaft darunter. Es zeigt Bild 0, also genau den Stand,
   auf dem der Hero startet - eine Luecke im Videobild faellt damit
   nicht mehr auf. Der Ausschnitt deckt sich mit dem der Handy-Fassung:
   das Poster ist 1942 x 1080, die Handy-Fassung ein mittiger Beschnitt
   daraus auf 970 x 1080; ueber cover zeigen beide dieselbe Bildmitte.

   Liegt vor dem Video in der Malreihenfolge (Pseudoelement vor dem
   ersten Kind) und damit sicher dahinter. */
.tchero__sticky::before {
  content: "";
  position: absolute;
  inset: 0;
  background: url("../assets/video/tricore-hero-poster.jpg?v=20") center / cover
    no-repeat;
}

.tchero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;                /* object-cover */
  /* Eigene Compositing-Ebene, damit ein neues Videobild nicht die
     darüberliegenden Headlines neu zeichnen lässt. Kein
     will-change: contents – das verhindert eher Optimierungen,
     als dass es hilft. */
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* Kein weisser Schleier ueber dem Video – das Bild bleibt unberuehrt.
   Die Headline steht damit direkt auf dem Videobild. */

/* ---------- Headline-Bühne: unten links ---------- */
.tchero__stage {
  position: absolute;
  inset: 0;
  z-index: 10;
  pointer-events: none;
  /* Einflug der Headline. Die Buehne traegt die Bewegung, damit die vom
     JS gesetzte Deckkraft der einzelnen Slides unberuehrt bleibt.

     Ohne Verzoegerung, also zusammen mit dem Seitenaufbau. Frueher
     stand hier 0,8 s Wartezeit. Die Buehne liegt ueber der ganzen
     Flaeche, und ihre Deckkraft-und-Verschiebung-Animation zwingt
     Safari dazu, die vier Slides - jeder mit eigenem will-change - in
     eine gemeinsame Compositing-Ebene zu heben. Sprang das mitten im
     Laden an, war der Wechsel auf dem Telefon als kurzes Aufblitzen zu
     sehen. Faengt die Animation gleich zu Beginn an, faellt die
     Umstellung in den ersten Bildaufbau und bleibt unsichtbar - und die
     erste Headline steht sofort, statt erst nach einer knappen
     Sekunde. */
  animation: tc-headline-in 0.8s var(--tc-ease-out) both;
}

.tchero__slide {
  position: absolute;
  left: var(--tc-pad-x);
  right: var(--tc-pad-x);
  bottom: var(--tc-hero-bottom);
  text-align: left;
  opacity: 0;
  will-change: opacity, transform;
}

/* Schrift steht ohne Schleier direkt auf dem Video. Gemessen ueber alle
   vier Stopps: dunkles #202A36 kommt nur auf Kontrast 1,4–2,4 (zu wenig),
   Weiss auf 6,0–10,4. Der weiche Schatten ist als Form nicht sichtbar,
   sichert die Kanten aber gegen helle Bildstellen (Himmel, Lampen). */
.tchero__label {
  margin: 0 0 0.9rem;
  /* 13 px statt 11: auf dem Telefon stand die Rubrikzeile sonst deutlich
     kleiner unter der grossen Headline, als der Desktop es zeigt. */
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.85);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45), 0 4px 24px rgba(0, 0, 0, 0.35);
}

.tchero__title {
  margin: 0;
  /* Zeilenmass, damit die Headlines von selbst auf zwei Zeilen brechen,
     statt ueber die halbe Bildbreite zu laufen. */
  max-width: 15ch;
  /* Notbremse fuer sehr schmale Geraete: "Gartendienstleistung" passt bei
     360 px gerade noch. Darunter bricht das Wort um, statt die Seite
     seitlich scrollbar zu machen. */
  overflow-wrap: break-word;
  /* Handy-Groesse, deutlich angehoben von 8vw. Die Grenze setzt das
     laengste Wort: "Verantwortung." sind 14 Zeichen, in Inter rund das
     7-fache der Schriftgroesse. Bei 375 px Geraetebreite bleiben nach
     2 x 16 px Rand 343 px, also passen rund 49 px – 11,5vw sind dort
     43 px und lassen Luft. Bei 320 px greift das Minimum von 2,5rem. */
  font-size: clamp(2.5rem, 11.5vw, 4.5rem);
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.03em;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3), 0 10px 44px rgba(0, 0, 0, 0.45);
}

@media (min-width: 768px) {
  /* Die Rubrikzeile darf auf dem Desktop praesenter sein – 14 px statt
     12 tragen unter der grossen Headline besser. */
  .tchero__label { font-size: 14px; }
  /* 40 % groesser als die Ausgangswerte clamp(2.5rem, 5.5vw, 4.5rem) */
  .tchero__title { font-size: clamp(3.5rem, 7.7vw, 6.3rem); }
}

/* ---------- Fortschritt & Scroll-Hinweis: unten rechts ---------- */
/* Beide sitzen rechts, damit sie der Headline unten links nicht in die
   Quere kommen. */
.tchero__dots {
  position: absolute;
  z-index: 10;
  right: var(--tc-pad-x);
  bottom: calc(var(--tc-pad-y) + 0.5rem);
  display: flex;
  gap: 0.5rem;
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.6s ease;
}

.tchero__dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.35);
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.3);
  transition: background-color 0.35s ease, transform 0.35s var(--tc-ease-out);
}
.tchero__dot.is-active {
  background: rgba(255, 255, 255, 0.95);
  transform: scale(1.35);
}

.tchero__hint {
  position: absolute;
  z-index: 10;
  right: var(--tc-pad-x);
  bottom: calc(var(--tc-pad-y) + 2rem);
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.9);
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
  pointer-events: none;
  opacity: 1;
  transition: opacity 0.5s ease;
}

.tchero__hint svg { width: 14px; height: 14px; animation: tc-nudge 1.8s var(--tc-ease-out) infinite; }

@keyframes tc-nudge {
  0%, 100% { transform: translateY(-2px); opacity: 0.55; }
  50%      { transform: translateY(2px);  opacity: 1; }
}

/* ---------- Einflug ---------- */
@keyframes tc-nav-in {
  from { opacity: 0; transform: translateY(-16px); }
  to   { opacity: 1; transform: none; }
}

@keyframes tc-headline-in {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: none; }
}

/* ---------- Ladezustand ---------- */
.tchero__loader {
  position: absolute;
  z-index: 12;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  opacity: 0;
  transition: opacity 0.4s ease;
}
/* Ring rotiert – der Prozenttext bleibt bewusst ruhig stehen */
.tchero__loader::before {
  content: "";
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.28);
  border-top-color: rgba(255, 255, 255, 0.95);
  box-shadow: 0 1px 8px rgba(0, 0, 0, 0.25);
  animation: tc-spin 0.9s linear infinite;
}
.tchero__loader::after {
  content: attr(data-pct);
  font-size: 0.8125rem;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.92);
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.45);
  font-variant-numeric: tabular-nums;
}
/* Ladeanzeige erscheint erst, wenn das Laden merklich dauert - bei
   schnellem Netz oder aus dem Cache sieht man sie nie. */
.tchero.is-loading .tchero__loader { opacity: 1; }
/* Sobald das Video bereit ist, hat "fertig" immer Vorrang – auch falls
   beide Klassen kurzzeitig gleichzeitig gesetzt sein sollten. */
.tchero.is-ready .tchero__loader { opacity: 0; pointer-events: none; }

@keyframes tc-spin { to { transform: rotate(360deg); } }

/* ---------- Filter ueber dem Video ----------
   Das Hero-Video bekommt einen leichten warmen Filter, damit der
   Einstieg zur Farbwelt der Seite passt. Der Verlauf unten nimmt den
   Seitengrund (#1c1b17) schon im Video auf. Die Textebenen liegen auf
   z-index 10+, der Schleier auf 1 – er liegt also nur ueber dem
   Videobild, nicht ueber Headline, Punkten oder Lader. */
.tchero__video,
/* Das Standbild dahinter bekommt denselben Filter - sonst haette der
   kurze Moment, in dem es durchscheint, eine andere Farbwelt. */
.tchero__sticky::before {
  filter: sepia(0.18) saturate(0.82) brightness(0.94) contrast(1.02);
}
.tchero__sticky::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg,
    rgba(28, 27, 23, 0.10) 0%,
    rgba(28, 27, 23, 0.16) 55%,
    rgba(28, 27, 23, 0.34) 100%);
  pointer-events: none;
}

/* ---------- Reduzierte Bewegung ---------- */
@media (prefers-reduced-motion: reduce) {
  .tchero__hint svg { animation: none; }
  .tchero__loader { animation-duration: 2.4s; }
  .tcnav__inner,
  .tchero__stage { animation: none; }
}
