const DS = window.IseeITDesignSystem_37fb1f;

// Sanftes Scrollen zu einem Element — dieselbe Kurve wie die Anker-Navigation der App,
// nutzbar auch auf Unterseiten (Fachgebiete, Unternehmen).
window.sanftZu = function (el, versatz) {
  if (typeof el === 'string') el = document.getElementById(el);
  if (!el) return;
  var ziel = Math.max(0, el.getBoundingClientRect().top + window.pageYOffset - (versatz == null ? 100 : versatz));
  var start = window.pageYOffset, weg = ziel - start;
  if (window.matchMedia('(prefers-reduced-motion: reduce)').matches || Math.abs(weg) < 40) { window.scrollTo(0, ziel); return; }
  var dauer = Math.min(1900, 620 + Math.abs(weg) * 0.34), t0 = performance.now();
  var schritt = function (t) {
    var p = Math.min(1, (t - t0) / dauer);
    var e = p < .5 ? 4 * p * p * p : 1 - Math.pow(-2 * p + 2, 3) / 2;
    window.scrollTo(0, start + weg * e);
    if (p < 1) requestAnimationFrame(schritt);
  };
  requestAnimationFrame(schritt);
};

function useBlobSrc(url, fortschritt) {
  const [src, setSrc] = React.useState(null);
  React.useEffect(() => {
    if (!url) { setSrc(null); return; }
    let alive = true, obj;
    fetch(url).then(async r => {
      if (!r.ok) throw new Error('http ' + r.status);
      const laenge = fortschritt ? +(r.headers.get('Content-Length') || 0) : 0;
      if (!fortschritt || !r.body || !laenge) return r.blob();
      const leser = r.body.getReader(); const teile = []; let da = 0;
      for (;;) { const s = await leser.read(); if (s.done) break; teile.push(s.value); da += s.value.length; if (alive) fortschritt(Math.min(1, da / laenge)); }
      return new Blob(teile, { type: r.headers.get('Content-Type') || 'video/mp4' });
    }).then(b => { if (!alive) return; obj = URL.createObjectURL(b); setSrc(obj); }).catch(() => { if (alive && fortschritt) setSrc('fehlgeschlagen'); });
    return () => { alive = false; if (obj) URL.revokeObjectURL(obj); };
  }, [url]);
  return src;
}

// Sprachumschalter: ein Regler — eine helle Platte gleitet in einem gemeinsamen
// Rahmen zur gewählten Sprache. Die nicht gewählten Tasten bleiben vollständig
// durchsichtig (das Hero-Video scheint durch); die gewählte trägt ihre eigene Farbe.
const SPRACHFARBE = { de: '#A63A1E', en: '#221E19', es: '#A3521A', el: '#0E6E74' }; // konstant: liegt stets auf der cremefarbenen Platte
const SPRACHEN_KURZ = [['de', 'DE'], ['en', 'EN'], ['el', 'EL'], ['es', 'ES']];
const SPRACHEN_LANG = [['de', 'Deutsch'], ['en', 'English'], ['el', 'Ελληνικά'], ['es', 'Español']];

function SprachPlatte({ eintraege, lang, waehle, label, gross, fuellen, fett }) {
  const box = React.useRef(null);
  const [p, setP] = React.useState({ x: 0, b: 0, sitzt: false });
  const [an, setAn] = React.useState(false);
  const messen = React.useCallback(() => {
    const w = box.current; if (!w) return;
    const el = w.querySelector('[data-aktiv="ja"]'); if (!el) return;
    const x = el.offsetLeft, b = el.offsetWidth;
    setP(v => (v.sitzt && Math.abs(v.x - x) < .5 && Math.abs(v.b - b) < .5) ? v : { x, b, sitzt: true });
  }, []);
  React.useLayoutEffect(() => { messen(); }, [messen, lang, eintraege, gross, fuellen]);
  React.useEffect(() => {
    const f = () => messen();
    window.addEventListener('resize', f, { passive: true });
    if (document.fonts && document.fonts.ready) document.fonts.ready.then(f).catch(() => {});
    const id = requestAnimationFrame(() => setAn(true));
    return () => { window.removeEventListener('resize', f); cancelAnimationFrame(id); };
  }, [messen]);
  const still = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  const taste = (aktiv, code) => ({
    position: 'relative', zIndex: 1, appearance: 'none', WebkitAppearance: 'none', background: 'none', border: 0, borderRadius: 0, margin: 0, cursor: 'pointer', boxSizing: 'border-box',
    padding: gross ? '10px 15px' : fuellen ? '13px 8px' : '7px 4px',
    minWidth: gross || fuellen ? 'auto' : '38px',
    minHeight: fuellen ? '44px' : 'auto',
    flex: fuellen ? '1 1 0' : '0 0 auto',
    textAlign: 'center',
    font: gross ? (fett ? "700 13.5px/1 var(--font-grotesk)" : "500 13.5px/1 var(--font-grotesk)") : (fett ? "700 11.5px/1 var(--font-mono)" : "500 11.5px/1 var(--font-mono)"),
    letterSpacing: gross ? '-.005em' : '.06em',
    color: aktiv ? SPRACHFARBE[code] : (fett ? '#FBF8F3' : 'rgba(251,248,243,.82)'),
    textShadow: aktiv ? 'none' : (fett ? '0 1px 12px rgba(34,30,25,.66), 0 1px 3px rgba(34,30,25,.35)' : '0 1px 12px rgba(34,30,25,.55)'),
    /* Der Text färbt sich einen Wimpernschlag nach dem Eintreffen der Platte. */
    transition: 'color .42s ease ' + (aktiv ? '.14s' : '0s')
  });
  return <div ref={box} className="sprachplatte" role="group" aria-label={label} style={{ position: 'relative', display: fuellen ? 'flex' : 'inline-flex', width: fuellen ? '100%' : 'auto', flex: 'none', border: fett ? '1px solid rgba(251,248,243,.55)' : '1px solid rgba(251,248,243,.38)' }}>
    {/* Die Platte ragt 1px über den Rahmen hinaus: an der gewählten Sprache verschwindet die Umrandung unter ihr, statt als dunkler Saum durchzuscheinen. */}
    <span aria-hidden="true" style={{ position: 'absolute', left: 0, top: '-1px', bottom: '-1px', width: (p.b + 2) + 'px', transform: 'translateX(' + (p.x - 1) + 'px)', background: '#FBF8F3', opacity: p.sitzt ? 1 : 0, transition: an && !still ? 'transform .62s cubic-bezier(.34,.72,.14,1), width .62s cubic-bezier(.34,.72,.14,1), opacity .35s ease' : 'none' }}></span>
    {eintraege.map(([code, txt]) => <button key={code} type="button" data-aktiv={lang === code ? 'ja' : 'nein'} aria-pressed={lang === code} onClick={() => waehle(code)} style={taste(lang === code, code)}>{txt}</button>)}
  </div>;
}

// Hell/Dunkel-Schalter: Sonne/Mond im Header, Wahl bleibt gespeichert (Startwert: Systemeinstellung).
function ThemaKnopf() {
  const { t } = React.useContext(window.SpracheCtx);
  const [dunkel, setDunkel] = React.useState(() => document.documentElement.getAttribute('data-thema') === 'dunkel');
  const [hov, setHov] = React.useState(false);
  // Einmaliges Aufleuchten: erst wenn der Hero betrachtet wurde und der Besucher ein Stück gescrollt hat — derselbe Lichtstrahl wie auf der Ladeblende.
  const [blitz, setBlitz] = React.useState(false);
  React.useEffect(() => {
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
    let t1, t2, aus = false;
    const beiScroll = () => {
      if (aus || window.pageYOffset < window.innerHeight * 1.05) return;
      aus = true; window.removeEventListener('scroll', beiScroll);
      t1 = setTimeout(() => { setBlitz(true); t2 = setTimeout(() => setBlitz(false), 1600); }, 350);
    };
    window.addEventListener('scroll', beiScroll, { passive: true });
    return () => { window.removeEventListener('scroll', beiScroll); clearTimeout(t1); clearTimeout(t2); };
  }, []);
  const wechsle = () => setDunkel(d => {
    const n = !d;
    if (n) document.documentElement.setAttribute('data-thema', 'dunkel'); else document.documentElement.removeAttribute('data-thema');
    try { localStorage.setItem('iseeit-thema', n ? 'dunkel' : 'hell'); } catch (e) {}
    return n;
  });
  const label = dunkel ? (t.nav.themaHell || 'Helles Design') : (t.nav.themaDunkel || 'Dunkles Design');
  return <button type="button" onClick={wechsle} aria-label={label} title={label} aria-pressed={dunkel}
    onMouseEnter={() => setHov(true)} onMouseLeave={() => setHov(false)}
    style={{ position: 'relative', overflow: 'hidden', width: '38px', height: '38px', flex: 'none', display: 'flex', alignItems: 'center', justifyContent: 'center', background: hov ? 'rgba(251,248,243,.1)' : 'rgba(251,248,243,.05)', border: hov ? '1px solid var(--gold-hell)' : '1px solid rgba(251,248,243,.62)', color: hov ? 'var(--gold-hell)' : '#FBF8F3', cursor: 'pointer', padding: 0, transition: 'color .25s ease, border-color .25s ease' }}>
    {blitz && <span aria-hidden="true" style={{ position: 'absolute', inset: 0, pointerEvents: 'none', background: 'linear-gradient(100deg,rgba(251,248,243,0) 38%,rgba(251,248,243,.55) 50%,rgba(251,248,243,0) 62%) no-repeat 100% 0/300% 100%', animation: 'markeGlanz 1.5s cubic-bezier(.45,0,.2,1) both' }}></span>}
    {dunkel
      ? <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" aria-hidden="true"><circle cx="12" cy="12" r="4.1"></circle><path d="M12 2.6v2.5M12 18.9v2.5M2.6 12h2.5M18.9 12h2.5M5.2 5.2l1.8 1.8M17 17l1.8 1.8M18.8 5.2L17 7M7 17l-1.8 1.8"></path></svg>
      : <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M20.4 13.9A8.4 8.4 0 0 1 10.1 3.6a8.4 8.4 0 1 0 10.3 10.3z"></path></svg>}
  </button>;
}

function SiteHeader({ onNav, onGoto }) {
  const { t, lang, waehle } = React.useContext(window.SpracheCtx);
  const schmal = window.useSchmal();
  const [offen, setOffen] = React.useState(false);
  const [prog, setProg] = React.useState(0);
  const [kopfH, setKopfH] = React.useState(58);
  const kopfRef = React.useRef(null);
  const reiheRef = React.useRef(null), navRef = React.useRef(null), logoRef = React.useRef(null), grpRef = React.useRef(null);
  /* Griechisch braucht in der Navigation deutlich mehr Breite als Englisch. Statt die
     Zeile schrumpfen und überlappen zu lassen, misst die Kopfzeile den Bedarf: passt die
     Navigation nicht neben Logo, Sprachen und Kontakt, wandert sie ins Menü. */
  const [engpass, setEngpass] = React.useState(false);
  React.useEffect(() => {
    if (schmal) { setEngpass(false); return; }
    const messe = () => {
      const reihe = reiheRef.current, nav = navRef.current, logo = logoRef.current, grp = grpRef.current;
      if (!reihe || !nav || !logo || !grp) return;
      const cs = getComputedStyle(reihe);
      const platz = reihe.clientWidth - parseFloat(cs.paddingLeft) - parseFloat(cs.paddingRight);
      const luecke = parseFloat(cs.columnGap) || 12;
      const brauche = logo.offsetWidth + nav.scrollWidth + grp.offsetWidth + 2 * luecke;
      setEngpass(e => (e ? brauche + 12 > platz : brauche > platz));
    };
    messe();
    window.addEventListener('resize', messe, { passive: true });
    const id = requestAnimationFrame(messe);
    if (document.fonts && document.fonts.ready) document.fonts.ready.then(messe).catch(() => {});
    return () => { window.removeEventListener('resize', messe); cancelAnimationFrame(id); };
  }, [schmal, lang]);
  React.useEffect(() => {
    const f = () => { const m = document.documentElement.scrollHeight - window.innerHeight; setProg(m > 0 ? Math.min(1, window.pageYOffset / m) : 0); };
    window.addEventListener('scroll', f, { passive: true }); f();
    return () => window.removeEventListener('scroll', f);
  }, []);
  React.useEffect(() => { if (!schmal && !engpass) setOffen(false); }, [schmal, engpass]);
  React.useEffect(() => {
    document.body.style.overflow = offen ? 'hidden' : '';
    return () => { document.body.style.overflow = ''; };
  }, [offen]);
  React.useEffect(() => {
    if (!offen) return;
    const f = (e) => { if (e.key === 'Escape') setOffen(false); };
    window.addEventListener('keydown', f);
    return () => window.removeEventListener('keydown', f);
  }, [offen]);
  React.useLayoutEffect(() => { if (offen && kopfRef.current) setKopfH(kopfRef.current.offsetHeight); }, [offen, schmal, engpass]);
  const [kHov, setKHov] = React.useState(false);
  const zu = () => setOffen(false);
  const geh = (id) => (e) => { e.preventDefault(); zu(); onNav(id); };
  const eintraege = [['wahl', t.nav.wahl], ['prozess', t.nav.prozess], ['ankommen', t.nav.ankommen], ['ueber-uns', t.nav.wir], ['faq', t.nav.fragen]];
  const L = (id, txt) => <a key={id} href={'#' + id} onClick={geh(id)} style={{ color: 'var(--sektion-text)', textDecoration: 'none', padding: '4px 0', whiteSpace: 'nowrap', transition: 'color .25s ease' }} onMouseEnter={e => e.target.style.color = 'var(--gold-hell)'} onMouseLeave={e => e.target.style.color = 'var(--sektion-text)'}>{txt}</a>;
  const mLnk = { color: 'var(--sektion-text)', textDecoration: 'none', font: "500 19px/1.25 var(--font-grotesk)", padding: '16px 0', borderBottom: '1px solid rgba(251,248,243,.12)', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '14px' };
  return <header ref={kopfRef} style={{ position: 'sticky', top: 0, zIndex: 60, background: 'var(--sektion)', borderBottom: '1px solid rgba(251,248,243,.14)' }}>
    <div ref={reiheRef} style={{ position: 'relative', maxWidth: 'var(--container)', margin: '0 auto', padding: schmal ? '9px var(--rand)' : '10px var(--rand)', minHeight: schmal ? '54px' : '58px', display: 'flex', alignItems: 'center', ...(schmal ? { justifyContent: 'space-between', gap: '12px' } : { flexWrap: 'nowrap', gap: '12px' }) }}>
      <a ref={logoRef} href="#" onClick={e => { e.preventDefault(); zu(); onGoto('home'); }} style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', flex: 'none' }}>
        <DS.Wortmarke size={25} hell />
      </a>
      {!schmal && <nav ref={navRef} aria-hidden={engpass ? 'true' : undefined} style={{ display: 'flex', flexWrap: 'nowrap', gap: '0 14px', alignItems: 'center', fontSize: '13.5px', letterSpacing: '-.005em', flex: '0 0 auto', ...(engpass ? { position: 'absolute', left: 0, top: 0, visibility: 'hidden', pointerEvents: 'none' } : {}) }}>
        {eintraege.map(([id, tx]) => L(id, tx))}<a href="vergleich/index.html" style={{ color: 'var(--sektion-text)', textDecoration: 'none', padding: '4px 0', whiteSpace: 'nowrap', transition: 'color .25s ease' }} onMouseEnter={e => e.target.style.color = 'var(--gold-hell)'} onMouseLeave={e => e.target.style.color = 'var(--sektion-text)'}>{t.nav.vergleich}</a>
      </nav>}
      {!schmal && <div ref={grpRef} style={{ display: 'flex', alignItems: 'center', gap: '12px', flexWrap: 'nowrap', marginLeft: 'auto', flex: 'none' }}>
        <SprachPlatte eintraege={SPRACHEN_KURZ} lang={lang} waehle={waehle} label={t.nav.sprache} />
        <ThemaKnopf />
        <a href="#kontakt" onClick={geh('kontakt')} onMouseEnter={() => setKHov(true)} onMouseLeave={() => setKHov(false)} style={{ background: kHov ? '#7F2A12' : '#A63A1E', color: '#FFFFFF', border: '1px solid rgba(251,247,242,.85)', textDecoration: 'none', padding: '9px 10px', minWidth: '122px', textAlign: 'center', fontSize: '13.5px', fontWeight: 500, whiteSpace: 'nowrap', transition: 'background var(--dauer-hover) var(--ease)' }}>{t.nav.kontakt}</a>
      </div>}
      {(schmal || engpass) && <div style={{ display: 'flex', alignItems: 'center', gap: '8px', flex: 'none', margin: '-4px -10px -4px 0' }}>{schmal && <ThemaKnopf />}<button onClick={() => setOffen(!offen)} aria-expanded={offen} aria-label={offen ? t.nav.schliessen : t.nav.menue} style={{ width: '44px', height: '44px', margin: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'none', border: 'none', color: 'var(--sektion-text)', cursor: 'pointer', padding: 0 }}>
        <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" aria-hidden="true">{offen ? <path d="M6 6l12 12M18 6L6 18"></path> : <path d="M4 7h16M4 12h16M4 17h16"></path>}</svg>
      </button></div>}
    </div>
    <div style={{ height: '2px', background: 'rgba(251,247,242,.16)' }}><div style={{ height: '2px', width: (prog * 100) + '%', background: 'var(--gold)' }}></div></div>
    {(schmal || engpass) && offen && <div style={{ position: 'fixed', left: 0, right: 0, top: kopfH + 'px', bottom: 0, zIndex: 59, background: 'var(--sektion)', overflowY: 'auto', WebkitOverflowScrolling: 'touch', animation: 'fadeIn .25s ease both' }}>
      <nav style={{ maxWidth: 'var(--container)', margin: '0 auto', padding: '10px var(--rand) 44px', display: 'flex', flexDirection: 'column' }}>
        {eintraege.map(([id, tx]) => <a key={id} href={'#' + id} onClick={geh(id)} style={mLnk}>{tx}</a>)}
        <a href="vergleich/index.html" style={mLnk}>{t.nav.vergleich} <span aria-hidden="true" style={{ color: 'var(--gold-hell)', fontSize: '17px' }}>→</span></a>
        {schmal && <div style={{ marginTop: '28px' }}>
          <SprachPlatte eintraege={SPRACHEN_KURZ} lang={lang} waehle={waehle} label={t.nav.sprache} fuellen />
        </div>}
        {schmal && <a href="#kontakt" onClick={geh('kontakt')} style={{ marginTop: '14px', display: 'block', textAlign: 'center', background: '#A63A1E', color: '#FFFFFF', textDecoration: 'none', padding: '16px 18px', fontSize: '16px', fontWeight: 500, border: '1px solid rgba(251,247,242,.85)' }}>{t.nav.kontakt}</a>}
      </nav>
    </div>}
  </header>;
}

function Hero({ onNav }) {
  const { t, lang, waehle } = React.useContext(window.SpracheCtx);
  const mobil = window.useMobil();
  const still = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  const heroSrc = useBlobSrc(still ? null : 'assets/hero-bergpanorama.mp4', React.useCallback((p) => { if (window.VorhangFortschritt) window.VorhangFortschritt(p); }, []));
  const videoSrc = heroSrc && heroSrc !== 'fehlgeschlagen' ? heroSrc : null;
  // Eingangs-Vorhang (index.html): Der Hero hält Texte und Kamerafahrt zurück, bis das Video
  // abspielbereit ist und der Vorhang sich öffnet — dann steigt alles gemeinsam auf.
  const [bereit, setBereit] = React.useState(() => { const v = document.getElementById('vorhang'); return !v || !!v.dataset.zu; });
  const offenRef = React.useRef(false);
  const oeffnen = React.useCallback(() => {
    if (offenRef.current) return; offenRef.current = true;
    if (!window.VorhangZu || !document.getElementById('vorhang')) { setBereit(true); return; }
    const mind = 3200; // Mindestanzeige: ruhiges Erscheinen (1,9 s) und ein voller Glanzlauf, bevor sich die Blende hebt
    const seit = window.__vorhangStart ? performance.now() - window.__vorhangStart : mind;
    setTimeout(() => window.VorhangZu(), Math.max(0, mind - seit));
  }, []);
  React.useEffect(() => {
    const f = () => setBereit(true);
    window.addEventListener('vorhang-zu', f);
    return () => window.removeEventListener('vorhang-zu', f);
  }, []);
  React.useEffect(() => { if (still || heroSrc === 'fehlgeschlagen') oeffnen(); }, [still, heroSrc, oeffnen]);
  const rise = (d) => bereit ? { animation: `riseIn 1.4s var(--ease) ${d}s both` } : { opacity: 0 };
  const [ctaHov, setCtaHov] = React.useState(false);
  const [pfeilHov, setPfeilHov] = React.useState(false);
  return <section className="hero-voll" style={{ position: 'relative', background: '#221E19', overflow: 'hidden', display: 'flex', alignItems: 'flex-end' }} data-screen-label="Hero">
    {videoSrc ? <video src={videoSrc} autoPlay muted loop playsInline aria-hidden="true" onLoadedData={oeffnen} onCanPlay={oeffnen} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', animation: 'fadeIn 1.4s ease both', transform: bereit ? 'scale(1)' : 'scale(1.07)', transition: 'transform 3s var(--ease)', willChange: 'transform' }}></video> : <img src="assets/hero-standbild.jpg" alt="" aria-hidden="true" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', animation: 'fadeIn 2.2s ease both' }} />}
    {/* Lesbarkeits-Schleier: dunkelt die hellen Videopartien (Himmel) leicht ab, damit die H1 überall so gut trägt wie die Unterzeile. */}
    <div aria-hidden="true" style={{ position: 'absolute', inset: 0, background: 'linear-gradient(180deg, rgba(20,17,13,.34) 0%, rgba(20,17,13,.10) 44%, rgba(20,17,13,.36) 100%)' }}></div>
    <div style={{ position: 'relative', zIndex: 1, maxWidth: 'var(--container)', margin: '0 auto', padding: mobil ? '76px var(--rand) 56px' : 'clamp(56px,10vw,96px) var(--rand) clamp(46px,9vw,68px)', width: '100%', height: mobil ? 'auto' : '650px' }}>
      <h1 className="hero-h1" style={{ margin: 0, maxWidth: 'none', color: '#FFFFFF', fontSize: 'clamp(36px,5.6vw,72px)', lineHeight: 1, letterSpacing: '-.03em', fontWeight: 700, textShadow: '0 2px 28px rgba(20,17,13,.85), 0 1px 5px rgba(20,17,13,.55)', ...rise(.18) }}>{t.hero.titel}</h1>
      <div style={{ marginTop: mobil ? '32px' : '26px', ...rise(.42) }}>
        <div style={{ maxWidth: mobil ? '420px' : 'none' }}>
          {mobil ? <SprachPlatte eintraege={SPRACHEN_KURZ} lang={lang} waehle={waehle} label={t.nav.sprache} fuellen fett /> : <SprachPlatte eintraege={SPRACHEN_LANG} lang={lang} waehle={waehle} label={t.nav.sprache} gross fett />}
        </div>
      </div>
      <a href="#wahl" onClick={e => { e.preventDefault(); onNav('wahl'); }} onMouseEnter={() => setCtaHov(true)} onMouseLeave={() => setCtaHov(false)} style={{ marginTop: mobil ? '28px' : '24px', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', background: ctaHov ? '#7F2A12' : '#A63A1E', color: '#FFFFFF', textDecoration: 'none', fontSize: '17px', fontWeight: 700, width: mobil ? '100%' : '180px', minHeight: '52px', padding: '0 18px', maxWidth: '100%', boxSizing: 'border-box', transition: 'background var(--dauer-hover) var(--ease)', ...rise(.6) }}>{t.hero.cta}</a>
      <p style={{ margin: mobil ? '28px 0 0' : '24px 0 0', font: "500 12.5px/1.8 var(--font-mono)", letterSpacing: '.15em', color: '#FBF8F3', textShadow: '0 1px 14px rgba(34,30,25,.78), 0 1px 3px rgba(34,30,25,.4)', ...rise(.74) }}>{t.hero.nischen}</p>
      <p style={{ margin: '22px 0 0', maxWidth: '960px', color: '#FBF8F3', fontSize: 'clamp(19px,2.3vw,29px)', lineHeight: 1.25, letterSpacing: '-.018em', fontWeight: 700, textShadow: '0 2px 24px rgba(34,30,25,.6), 0 1px 4px rgba(34,30,25,.32)', ...rise(.88) }}>{t.hero.sub}</p>
    </div>
    {!mobil && <button type="button" aria-label={t.hero.weiter} onClick={() => window.sanftZu('versprechen', 58)} onMouseEnter={() => setPfeilHov(true)} onMouseLeave={() => setPfeilHov(false)} style={{ position: 'absolute', left: '50%', bottom: '14px', zIndex: 2, width: '46px', height: '46px', display: 'flex', alignItems: 'center', justifyContent: 'center', background: 'none', border: 'none', cursor: 'pointer', padding: 0, color: pfeilHov ? 'var(--gold-hell)' : 'rgba(251,248,243,.66)', transform: 'translateX(-50%) translateY(' + (pfeilHov ? '3px' : '0') + ')', transition: 'color .3s ease, transform .3s var(--ease)', ...(bereit ? { animation: 'fadeIn 1.6s ease 1.5s both' } : { opacity: 0 }) }}>
      <svg width="27" height="27" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" style={{ filter: 'drop-shadow(0 1px 8px rgba(34,30,25,.55))' }}><path d="M5.5 9.5l6.5 6 6.5-6"></path></svg>
    </button>}
  </section>;
}

function Versprechen({ onNav, onGoto, onAnker }) {
  const { t } = React.useContext(window.SpracheCtx);
  const v = t.versprechen;
  return <section id="versprechen" style={{ background: 'var(--papier)', borderTop: '1px solid var(--linie)', scrollMarginTop: '100px' }} data-screen-label="01 Versprechen">
    <div style={{ maxWidth: 'var(--container)', margin: '0 auto', padding: 'clamp(40px,6vw,60px) var(--rand) var(--sektion-pad)' }}>
      <p style={{ margin: 0, maxWidth: '1100px', whiteSpace: 'pre-line', fontSize: 'var(--fs-statement)', lineHeight: 'var(--lh-statement)', letterSpacing: '-.022em', fontWeight: 600 }}>{v.statement}</p>
      <p style={{ margin: '24px 0 0', maxWidth: '800px', fontSize: '16.5px', lineHeight: 'var(--lh-lang)', color: 'var(--stein)' }}>{v.text}</p>
      {/* Überschrift der Versprechen-Liste: Goldmarke, Mono-Zeile, auslaufende Linie. */}
      <div style={{ margin: '60px 0 0', display: 'flex', alignItems: 'center', gap: '14px' }}>
        <span aria-hidden="true" style={{ width: '9px', height: '9px', background: 'var(--gold)', flex: 'none' }}></span>
        <h3 style={{ margin: 0, font: "500 13px/1.4 var(--font-mono)", letterSpacing: 'var(--ls-kicker)', textTransform: 'uppercase', color: 'var(--backstein)' }}>{v.kicker}</h3>
      </div>
      <div style={{ marginTop: '20px' }}>
        {v.zeilen.map((z, i) => <DS.ZeilenEintrag key={i} mittig titel={<span style={{ color: 'var(--backstein)' }}>{z.t}</span>} letzter={i === v.zeilen.length - 1}>{z.x}</DS.ZeilenEintrag>)}
      </div>
      <div id="nischen-kacheln" style={{ marginTop: '26px', display: 'grid', gridTemplateColumns: 'repeat(auto-fit,minmax(158px,1fr))', gap: '12px', scrollMarginTop: '100px' }}>
        {[['cybersecurity', 'nische-cybersecurity'], ['cloud', 'nische-cloud'], ['devops', 'nische-devops'], ['platform', 'nische-platform-engineering']].map(([n, ziel]) =>
          <a key={n} href={'?seite=nischen#' + ziel} onClick={e => { e.preventDefault(); if (onAnker) onAnker('nischen', ziel); else onGoto && onGoto('nischen'); }} style={{ display: 'block', textDecoration: 'none', color: 'inherit' }}>
            <DS.NischenKachel nische={n} style={{ height: '100%' }} /></a>)}
      </div>
      <p style={{ margin: '18px 0 0', fontSize: '16px' }}><a href="?seite=nischen" onClick={e => { e.preventDefault(); onGoto && onGoto('nischen'); }}>{v.fachgebieteLink}</a> <span style={{ color: 'var(--backstein)' }}>→</span></p>
    </div>
  </section>;
}

function Atempause({ src, video, caption, position }) {
  const still = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  const vFilter = 'saturate(.9) contrast(1.02)';
  const vsrc = useBlobSrc(still ? null : video);
  return <figure style={{ position: 'relative', margin: 0, overflow: 'hidden', minHeight: 'min(56vh,520px)', borderTop: '1px solid var(--linie)', borderBottom: '1px solid var(--linie)' }}>
    {vsrc ? <video src={vsrc} autoPlay muted loop playsInline aria-hidden="true" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: position || 'center', filter: vFilter }}></video> : <img src={src} alt="" aria-hidden="true" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', objectPosition: position || 'center', filter: vFilter }} />}
    <figcaption style={{ position: 'absolute', left: 0, right: 0, bottom: 0, padding: '60px var(--rand) 18px', background: 'linear-gradient(to top, rgba(34,30,25,.6), rgba(34,30,25,0))', color: '#FBF8F3', font: "400 11.5px/1.5 var(--font-mono)", letterSpacing: '.1em' }}>{caption}</figcaption>
  </figure>;
}

function ZumAnfang() {
  const mobil = window.useMobil();
  const [zeig, setZeig] = React.useState(false);
  const [hov, setHov] = React.useState(false);
  React.useEffect(() => {
    // Erscheint erst, wenn der Nutzer ein Stück nach oben scrollt, und verschwindet beim Weiterlesen.
    let letzte = window.pageYOffset, hoch = 0;
    const f = () => {
      const y = window.pageYOffset;
      const d = y - letzte; letzte = y;
      const k = document.getElementById('kontakt');
      const frei = !k || k.getBoundingClientRect().top > window.innerHeight;
      if (y < window.innerHeight || !frei) { hoch = 0; setZeig(false); return; }
      if (d < -1) hoch = Math.min(hoch - d, 400);
      else if (d > 3) { hoch = 0; setZeig(false); return; }
      if (hoch > 70) setZeig(true);
    };
    window.addEventListener('scroll', f, { passive: true });
    return () => window.removeEventListener('scroll', f);
  }, []);
  return <button onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })} aria-label="Zum Seitenanfang" title="Zum Anfang"
    onMouseEnter={() => setHov(true)} onMouseLeave={() => setHov(false)}
    style={{ position: 'fixed', right: mobil ? '16px' : '22px', bottom: mobil ? '16px' : '22px', zIndex: 55, width: '46px', height: '46px', display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#221E19', color: hov ? 'var(--gold-hell)' : '#FBF8F3', border: hov ? '1px solid var(--gold-hell)' : '1px solid rgba(200,129,26,.55)', cursor: 'pointer', padding: 0, opacity: zeig ? 1 : 0, transform: zeig ? 'none' : 'translateY(10px)', pointerEvents: zeig ? 'auto' : 'none', transition: 'opacity .85s var(--ease), transform .85s var(--ease), color .25s ease, border-color .25s ease' }}>
    <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M12 19V5"></path><path d="M5 12l7-7 7 7"></path></svg>
  </button>;
}

Object.assign(window, { SiteHeader, Hero, Versprechen, Atempause, ZumAnfang, SprachPlatte });