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'], ['es', 'ES'], ['el', 'EL']];
const SPRACHEN_LANG = [['de', 'Deutsch'], ['en', 'English'], ['es', 'Español'], ['el', 'Ελληνικά']];
// (i): eine kurze Erklärung hinter einem ruhigen Kreis. Klick öffnet eine Karte, Klick daneben oder Escape schließt sie.
function InfoPunkt({ text, label, rechts, hell, style }) {
const [offen, setOffen] = React.useState(false);
const [hov, setHov] = React.useState(false);
const ref = React.useRef(null);
React.useEffect(() => {
if (!offen) return;
const zu = (e) => { if (ref.current && !ref.current.contains(e.target)) setOffen(false); };
const esc = (e) => { if (e.key === 'Escape') setOffen(false); };
document.addEventListener('mousedown', zu); document.addEventListener('keydown', esc);
return () => { document.removeEventListener('mousedown', zu); document.removeEventListener('keydown', esc); };
}, [offen]);
const ruhig = hell ? 'rgba(251,248,243,.8)' : 'var(--stein)';
const aktiv = offen || hov;
return
{offen && {text}}
;
}
// Flaggen im Sprachumschalter: Deutsch steht für beide Zielländer, daher Deutschland und Schweiz in einer Marke.
const FLAGGE = {
de: ,
en: ,
es: ,
el:
};
const SPRACHNAME = { de: 'Deutsch', en: 'English', es: 'Español', el: 'Ελληνικά' };
function SprachPlatte({ eintraege, lang, waehle, label, gross, fuellen, fett, flaggen, nurFlaggen }) {
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: nurFlaggen ? '8px 7px' : gross ? '10px 15px' : fuellen ? '13px 8px' : flaggen ? '7px 8px' : '7px 4px',
minWidth: gross || fuellen || nurFlaggen ? 'auto' : '38px',
display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: '7px',
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
{/* Die Platte ragt 1px über den Rahmen hinaus: an der gewählten Sprache verschwindet die Umrandung unter ihr, statt als dunkler Saum durchzuscheinen. */}
{eintraege.map(([code, txt]) => )}
;
}
// 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;
// Schimmert beim Überschreiten der Schwelle; wer wieder nach oben scrollt, stellt ihn neu scharf.
let t1, t2, scharf = true;
const beiScroll = () => {
const unten = window.pageYOffset >= window.innerHeight * 1.05;
if (!unten) { scharf = true; return; }
if (!scharf) return;
scharf = false;
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 ;
}
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);
// Die Flaggen klappen beim Lesen nach unten auf die gewählte Sprache zusammen und öffnen sich beim Zurückscrollen wieder.
const [kompakt, setKompakt] = React.useState(false);
React.useEffect(() => {
// Ruhig: erst nach einem guten Stück Weg in eine Richtung (60px), nie unter 260px Scrollhöhe.
let letzte = window.pageYOffset, weg = 0;
const f = () => {
const y = window.pageYOffset, d = y - letzte; letzte = y;
const m = document.documentElement.scrollHeight - window.innerHeight; setProg(m > 0 ? Math.min(1, y / m) : 0);
if ((d > 0 && weg < 0) || (d < 0 && weg > 0)) weg = 0; weg += d;
if (y < 260) { setKompakt(false); weg = 0; } else if (weg > 60) setKompakt(true); else if (weg < -60) setKompakt(false);
};
window.addEventListener('scroll', f, { passive: true }); f();
return () => window.removeEventListener('scroll', f);
}, []);
React.useEffect(() => {
document.body.style.overflow = offen && schmal ? 'hidden' : '';
return () => { document.body.style.overflow = ''; };
}, [offen, schmal]);
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]);
const [kHov, setKHov] = React.useState(false);
const [mHov, setMHov] = React.useState(false);
const [fHov, setFHov] = 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 mLnk = { color: 'var(--sektion-text)', textDecoration: 'none', font: schmal ? "500 19px/1.25 var(--font-grotesk)" : "500 17px/1.25 var(--font-grotesk)", padding: schmal ? '16px 0' : '14px 0', borderBottom: '1px solid rgba(251,248,243,.12)', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: '14px', transition: 'color .25s ease' };
const M = (props, kind) => e.currentTarget.style.color = 'var(--gold-hell)'} onMouseLeave={e => e.currentTarget.style.color = 'var(--sektion-text)'}>{kind};
const rahmen = (hov) => ({ 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', transition: 'color .25s ease, border-color .25s ease, background .25s ease' });
return