/* SEITOPIA — single-page cinematic event site */
const { useState, useEffect, useRef, useMemo } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "grainOpacity": 0.16,
  "strobeIntensity": 0.22,
  "showStrobe": true,
  "heroTone": "cool",
  "ctaLabel": "Tickets sichern",
  "eventDate": "25 . 07 . 2026",
  "ticketUrl": "https://tickets.seitopia.com", /* unused while the "Tickets soon available" overlay is shown — re-wire goTickets() when real ticketing is live */
  "offsetHighlights": -92,
  "offsetLocation": -64,
  "offsetTeam": -96
} /*EDITMODE-END*/;

/* ---------- Reveal-on-scroll hook ---------- */
function useReveal() {
  useEffect(() => {
    const els = document.querySelectorAll('.reveal');
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          e.target.classList.add('in');
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0.18, rootMargin: '0px 0px -8% 0px' });
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, []);
}

/* ---------- Parallax ---------- */
function useParallax() {
  useEffect(() => {
    // skip on touch devices and when user prefers reduced motion
    if (window.matchMedia('(hover: none)').matches) return;
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
    let raf = null;
    const onScroll = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => {
        const y = window.scrollY;
        document.querySelectorAll('[data-parallax]').forEach((el) => {
          const speed = parseFloat(el.dataset.parallax) || 0.2;
          const rect = el.getBoundingClientRect();
          const offset = (rect.top + window.scrollY - y) * speed;
          el.style.transform = `translate3d(0, ${(-y * speed).toFixed(1)}px, 0)`;
        });
        raf = null;
      });
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
}

/* ---------- Scroll progress ---------- */
function useScrollProgress() {
  const [p, setP] = useState(0);
  useEffect(() => {
    const onScroll = () => {
      const h = document.documentElement;
      const max = h.scrollHeight - h.clientHeight;
      setP(max > 0 ? window.scrollY / max : 0);
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  return p;
}

/* ---------- Cursor (desktop) ---------- */
function CinemaCursor() {
  const dotRef = useRef(null);
  const ringRef = useRef(null);
  useEffect(() => {
    if (window.matchMedia('(hover:none)').matches) return;
    let x = window.innerWidth / 2,y = window.innerHeight / 2;
    let rx = x,ry = y;
    const onMove = (e) => {x = e.clientX;y = e.clientY;};
    const onEnter = () => {ringRef.current && (ringRef.current.style.transform += ' scale(1.6)');};
    document.addEventListener('mousemove', onMove);
    let raf;
    const tick = () => {
      rx += (x - rx) * 0.18;
      ry += (y - ry) * 0.18;
      if (dotRef.current) dotRef.current.style.transform = `translate3d(${x - 2}px, ${y - 2}px, 0)`;
      if (ringRef.current) ringRef.current.style.transform = `translate3d(${rx - 14}px, ${ry - 14}px, 0)`;
      raf = requestAnimationFrame(tick);
    };
    tick();
    return () => {document.removeEventListener('mousemove', onMove);cancelAnimationFrame(raf);};
  }, []);
  return (
    <>
      <div ref={dotRef} className="hidden md:block fixed top-0 left-0 w-1 h-1 bg-bone rounded-full pointer-events-none z-[9000] mix-blend-difference" />
      <div ref={ringRef} className="hidden md:block fixed top-0 left-0 w-7 h-7 border border-bone/40 rounded-full pointer-events-none z-[9000] mix-blend-difference transition-transform duration-200" />
    </>);

}

/* ---------- Loader ---------- */
function Loader() {
  return (
    <div className="loader-fade fixed inset-0 z-[10000] bg-black flex flex-col items-center justify-center">
      <div className="font-mono text-[10px] tracking-[0.5em] text-bone/60 mb-6">SEITOPIA / 26</div>
      <div className="w-[60vw] max-w-[420px] h-[1px] bg-bone/15 overflow-hidden">
        <div className="loader-bar h-full w-full bg-bone/80" />
      </div>
      <div className="font-mono text-[9px] tracking-[0.35em] text-bone/40 mt-6">ROUND 2.</div>
    </div>);

}

/* ---------- Top Nav ---------- */
function Nav({ progress, onTickets }) {
  const [open, setOpen] = useState(false);
  const scrollToTop = (e) => {
    if (e) e.preventDefault();
    window.scrollTo({ top: 0, behavior: 'smooth' });
  };
  const items = [
  { id: 'home', label: 'Home', onClick: scrollToTop },
  { id: 'highlights', label: 'Highlights' },
  { id: 'location', label: 'Location' },
  { id: 'team', label: 'Team' }];

  return (
    <>
      {/* progress hairline */}
      <div className="fixed top-0 left-0 right-0 h-[1px] z-[120] bg-bone/10">
        <div className="h-full bg-bone/70 origin-left" style={{ transform: `scaleX(${progress})` }} />
      </div>

      {/* top fade so content scrolling under nav stays readable on mobile */}
      <div className="fixed top-0 left-0 right-0 h-[90px] md:h-[110px] z-[105] pointer-events-none"
           style={{ background: 'linear-gradient(to bottom, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.55) 55%, rgba(0,0,0,0) 100%)' }} />

      <header className="fixed top-0 left-0 right-0 z-[110] px-6 md:px-10 pt-5 md:pt-7 flex items-start justify-between pointer-events-none">
        <div className="pointer-events-auto flex items-center gap-3">
          <div className="w-2 h-2 rounded-full bg-bone/80 animate-pulse" />
          <div className="font-mono text-[10px] tracking-[0.4em] text-bone/70">SEITOPIA</div>
        </div>

        {/* desktop nav */}
        <nav className="hidden md:flex pointer-events-auto items-center gap-8 font-mono text-[11px] tracking-[0.3em] uppercase">
          {items.map((i) =>
          <a key={i.id} href={i.onClick ? '#' : `#${i.id}`}
          onClick={i.onClick}
          className="nav-link">{i.label}</a>
          )}
          <button onClick={onTickets} className="text-bone/90 hover:text-bone transition border border-bone/30 hover:border-bone px-4 py-2 hover:bg-bone hover:!text-black">
            Tickets ↗
          </button>
        </nav>

        {/* mobile burger */}
        <button onClick={() => setOpen((o) => !o)} className="md:hidden pointer-events-auto font-mono text-[10px] tracking-[0.35em] text-bone/80">
          {open ? 'CLOSE' : 'MENU'}
        </button>
      </header>

      {/* mobile sheet */}
      <div className={`fixed inset-0 z-[105] bg-black transition-opacity duration-700 md:hidden ${open ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}>
        <div className="absolute inset-0 opacity-30">
          <div className="blob b1" />
          <div className="blob b2" />
        </div>
        <div className="relative h-full flex flex-col justify-center px-8 gap-2">
          {items.map((i, idx) =>
          <a
            key={i.id}
            href={i.onClick ? '#' : `#${i.id}`}
            onClick={(e) => {if (i.onClick) i.onClick(e);setOpen(false);}}
            className="font-serif text-[14vw] leading-[0.95] tracking-tight text-bone/95"
            style={{ transitionDelay: `${idx * 60}ms`, opacity: open ? 1 : 0, transform: open ? 'translateY(0)' : 'translateY(20px)', transition: 'opacity .8s ease, transform .8s ease' }}>
            
              {i.label}.
            </a>
          )}
          <div className="mt-10 font-mono text-[10px] tracking-[0.35em] text-bone/50">
            25.07.2026 / SEITOPIA
          </div>
        </div>
      </div>
    </>);

}

/* ---------- HERO ---------- */
function Hero({ tweaks, onTickets }) {
  const heroRef = useRef(null);
  const videoRef = useRef(null);

  // Force video playback (Chrome desktop + iOS Safari sometimes block autoplay)
  useEffect(() => {
    const v = videoRef.current;
    if (!v) return;
    // Explicitly mark muted via JS — some Chrome builds ignore the HTML attr on first mount
    v.muted = true;
    v.defaultMuted = true;
    v.playsInline = true;
    const tryPlay = () => {
      const p = v.play();
      if (p && typeof p.catch === 'function') p.catch(() => {});
    };
    tryPlay();
    // Retry once the media stack reports it can actually start
    v.addEventListener('loadedmetadata', tryPlay);
    v.addEventListener('canplay', tryPlay);
    // Retry on first user gesture — iOS / strict Chrome only unlock after one
    const onGesture = () => {tryPlay();cleanup();};
    const cleanup = () => {
      document.removeEventListener('touchstart', onGesture);
      document.removeEventListener('click', onGesture);
      document.removeEventListener('scroll', onGesture);
      document.removeEventListener('mousemove', onGesture);
      document.removeEventListener('keydown', onGesture);
    };
    document.addEventListener('touchstart', onGesture, { once: true, passive: true });
    document.addEventListener('click', onGesture, { once: true });
    document.addEventListener('scroll', onGesture, { once: true, passive: true });
    document.addEventListener('mousemove', onGesture, { once: true, passive: true });
    document.addEventListener('keydown', onGesture, { once: true });
    // Also retry when window regains focus / visibility
    const onVis = () => {if (!document.hidden) tryPlay();};
    document.addEventListener('visibilitychange', onVis);
    return () => {
      cleanup();
      v.removeEventListener('loadedmetadata', tryPlay);
      v.removeEventListener('canplay', tryPlay);
      document.removeEventListener('visibilitychange', onVis);
    };
  }, []);

  // gentle scroll parallax for inner content (desktop only)
  useEffect(() => {
    if (window.matchMedia('(hover: none)').matches) return;
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
    let raf;
    const onScroll = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => {
        const y = window.scrollY;
        if (heroRef.current) {
          const inner = heroRef.current.querySelector('[data-hero-inner]');
          const bg = heroRef.current.querySelector('[data-hero-bg]');
          if (inner) inner.style.transform = `translate3d(0, ${y * 0.25}px, 0)`;
          if (bg) bg.style.transform = `translate3d(0, ${y * 0.12}px, 0) scale(${1 + Math.min(y, 600) * 0.00015})`;
        }
        raf = null;
      });
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  return (
    <section ref={heroRef} id="hero" className="relative h-[100svh] min-h-[640px] w-full overflow-hidden bg-black">
      {/* faux-video stack */}
      <div data-hero-bg className="absolute inset-0">
        {/* hero video — src picked at render time so Chrome doesn't get confused by <source media> */}
        <video
          ref={videoRef}
          key={window.matchMedia && window.matchMedia('(max-width: 768px)').matches ? 'm' : 'd'}
          src={window.__resources?.heroVideo || (window.matchMedia && window.matchMedia('(max-width: 768px)').matches ? "assets/hero-mobile.mp4" : "assets/hero.mp4")}
          poster={window.__resources?.waterNight || "assets/water-night.jpeg"}
          autoPlay
          muted
          loop
          playsInline
          preload="auto"
          className="absolute inset-0 w-full h-full object-cover"
          style={{ filter: 'brightness(0.85) contrast(1.05) saturate(0.9)' }} />
        
        {/* atmospheric water layer behind video as fallback */}
        <div className="absolute inset-0 ken -z-10">
          <img src={window.__resources?.waterNight || "assets/water-night.jpeg"} alt=""
          className="absolute inset-0 w-full h-full object-cover opacity-55 mix-blend-screen" />
        </div>
        {/* drifting blobs */}
        <div className="blob b1" />
        <div className="blob b2" />
        <div className="blob b3" />
        {/* strobe flashes */}
        {tweaks.showStrobe && <>
          <div className="strobe a" />
          <div className="strobe b" />
          <div className="strobe c" />
        </>}
        {/* heavy bottom vignette */}
        <div className="absolute inset-0" style={{
          background: 'radial-gradient(ellipse at 50% 40%, transparent 30%, rgba(0,0,0,0.55) 60%, #000 95%)'
        }} />
        {/* horizontal scanline / cinema bar */}
        <div className="absolute top-0 left-0 right-0 h-[8vh] bg-gradient-to-b from-black to-transparent" />
        <div className="absolute bottom-0 left-0 right-0 h-[18vh] bg-gradient-to-t from-black to-transparent" />
      </div>

      {/* hero content */}
      <div data-hero-inner className="relative h-full flex flex-col items-center justify-center px-6">
        {/* serif wordmark / tagline */}
        <div className="logo-flicker flex flex-col items-center gap-3 md:gap-4 mb-10 md:mb-12 text-center">
          <div className="font-mono text-[10px] md:text-[11px] tracking-[0.5em] text-bone/55 uppercase" style={{ height: "0px" }}>

          </div>
          <h1 className="font-serif font-light italic text-[16vw] md:text-[8vw] leading-[0.92] tracking-[-0.01em] text-bone hero-title-shadow" style={{ width: "230px", height: "35px" }}>

          </h1>
          <div className="font-mono text-[10px] md:text-[11px] tracking-[0.4em] text-bone/65 uppercase">

          </div>
        </div>

        {/* CTA */}
        <button
          onClick={onTickets}
          className="btn-ghost px-8 md:px-10 py-4 md:py-[18px] font-mono uppercase text-[11px] md:text-[12px] tracking-[0.32em] text-bone" style={{ letterSpacing: "3.4px", lineHeight: "2", textAlign: "center", padding: "1px 40px 18px", fontSize: "18px", width: "320px", height: "40px" }}>
          
          {tweaks.ctaLabel}
        </button>

        {/* tiny date footer */}
        <div className="absolute bottom-5 md:bottom-8 left-0 right-0 px-5 md:px-10 flex flex-col md:flex-row items-center md:items-end md:justify-between gap-2 font-mono text-[10px] tracking-[0.35em] text-bone/55">
          <div className="flex items-center gap-3">
            <span className="dot" />
            <span>{tweaks.eventDate}</span>
          </div>
          <div className="hidden md:flex items-center gap-3">
            <span>Lake Sei - Nähe Ilz</span>
          </div>
          <div className="flex items-center gap-2">
            <span>SCROLL</span>
            <span className="block w-6 h-[1px] bg-bone/50" />
          </div>
        </div>
      </div>
    </section>);

}

/* ---------- Marquee strip ---------- */
function Marquee() {
  const text = "Hier steht ihre Werbung ·";
  const items = Array.from({ length: 6 }, (_, i) => text);
  return (
    <div className="relative py-6 md:py-8 border-y border-bone/10 overflow-hidden">
      <div className="marquee font-serif italic text-bone/70 text-[5vw] md:text-[2.4vw] leading-none">
        {items.concat(items).map((t, i) => <span key={i} className="shrink-0">{t}</span>)}
      </div>
    </div>);

}

/* ---------- HIGHLIGHTS ---------- */
const HIGHLIGHTS = [
{ idx: 1, status: 'COMING SOON' },
{ idx: 2, status: 'COMING SOON' },
{ idx: 3, status: 'COMING SOON' },
{ idx: 4, status: 'COMING SOON' },
{ idx: 5, status: 'COMING SOON' }];


function Highlights() {
  return (
    <section id="highlights" className="relative px-6 md:px-10 py-28 md:py-40 bg-black">
      <div className="max-w-[1500px] mx-auto">
        <div className="reveal flex items-baseline justify-between mb-12 md:mb-20">
          <div className="font-mono text-[10px] md:text-[11px] tracking-[0.4em] text-bone/55">
            01 / HIGHLIGHTS
          </div>
          <div className="font-mono text-[10px] tracking-[0.35em] text-bone/40 hidden md:block">
            5 SLOTS · RELEASE NACH UND NACH
          </div>
        </div>

        <h2 className="reveal font-serif font-light text-[18vw] md:text-[10.5vw] leading-[0.85] tracking-tight mb-16 md:mb-24">
          Coming<br />
          <span className="italic text-bone/70">soon</span>.
        </h2>

        <ul className="border-t border-bone/15">
          {HIGHLIGHTS.map((h, i) =>
          <li
            key={h.idx}
            className="reveal lineup-row group flex items-baseline justify-between py-7 md:py-10 gap-4"
            style={{ transitionDelay: `${i * 60}ms` }}>
            
              <div className="flex items-baseline gap-4 md:gap-8 flex-1 min-w-0">
                <span className="font-mono text-[10px] md:text-[11px] tabular-nums text-bone/40 tracking-[0.3em]">
                  {String(i + 1).padStart(2, '0')}
                </span>
                <span className="font-serif text-[12vw] md:text-[6.4vw] leading-[0.95] tracking-[-0.01em] text-bone/85">
                  ?&thinsp;?&thinsp;?&thinsp;?
                </span>
              </div>
              <div className="meta hidden md:flex flex-col items-end gap-1 font-mono text-[10px] tracking-[0.3em] text-bone/55">
                <span>SLOT 0{i + 1}</span>
                <span className="text-bone/35">RELEASE TBA</span>
              </div>
              <div className="font-mono text-[9px] md:text-[10px] tracking-[0.35em] text-bone/40 shrink-0 flex items-center gap-2">
                <span className="inline-block w-1.5 h-1.5 rounded-full bg-bone/60 animate-pulse" />
                {h.status}
              </div>
            </li>
          )}
        </ul>

        <div className="reveal mt-14 md:mt-20 grid grid-cols-1 md:grid-cols-2 gap-6 md:gap-12 font-mono text-[11px] tracking-[0.18em] text-bone/55">
          <p className="leading-[1.7]">Highlights droppen auf unseren Instagram-Kanal

          </p>
          <p className="leading-[1.7] md:text-right">Drops kommen ohne Vorwarnung.
Folge uns oder abonniere @seitopia_event
          </p>
        </div>
      </div>
    </section>);

}

/* ---------- LOCATION ---------- */
function Location() {
  return (
    <section id="location" className="relative bg-black overflow-hidden">
      {/* faint water atmosphere edge */}
      <div className="absolute inset-0 pointer-events-none">
        <img src={window.__resources?.waterNight || "assets/water-night.jpeg"} alt=""
        className="absolute inset-0 w-full h-full object-cover opacity-30"
        style={{ filter: 'brightness(0.5) contrast(1.05)' }} />
        <div className="absolute inset-0" style={{
          background: 'radial-gradient(ellipse at 50% 50%, rgba(0,0,0,0.85) 35%, rgba(0,0,0,0.6) 70%, rgba(0,0,0,0) 100%)'
        }} />
      </div>

      <div className="relative px-6 md:px-10 py-24 md:py-32">
        <div className="max-w-[1500px] mx-auto">
          {/* section header */}
          <div className="reveal flex items-baseline justify-between mb-10 md:mb-16">
            <div className="font-mono text-[10px] md:text-[11px] tracking-[0.4em] text-bone/55">
              02 / LOCATION
            </div>
            <div className="font-mono text-[10px] tracking-[0.35em] text-bone/40 hidden md:block">
              LAKE SEI · ILZ
            </div>
          </div>

          {/* MAP — the centerpiece */}
          <div className="reveal relative mx-auto max-w-[1200px] mb-12 md:mb-16">
            {/* corner ticks */}
            <div className="absolute -top-2 -left-2 w-6 h-6 border-t border-l border-bone/40 z-10" />
            <div className="absolute -top-2 -right-2 w-6 h-6 border-t border-r border-bone/40 z-10" />
            <div className="absolute -bottom-2 -left-2 w-6 h-6 border-b border-l border-bone/40 z-10" />
            <div className="absolute -bottom-2 -right-2 w-6 h-6 border-b border-r border-bone/40 z-10" />

            <a
              href="https://www.google.com/maps?q=47.0993611,15.9036389"
              target="_blank"
              rel="noopener noreferrer"
              className="block relative border border-bone/15 overflow-hidden bg-black group cursor-pointer"
              aria-label="In Google Maps öffnen">
              <img
                src={window.__resources?.locationMap || "assets/location-map.png"}
                alt="Eventplan — Camping, Gehweg, Eventarea"
                className="block w-full h-auto transition-transform duration-[1400ms] ease-out group-hover:scale-[1.02]" />
              
              {/* hover prompt */}
              <div className="absolute inset-0 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-500 bg-black/30 pointer-events-none z-10">
                <div className="font-mono text-[11px] md:text-[13px] tracking-[0.4em] text-bone uppercase border border-bone/60 px-6 py-3 bg-black/50">
                  Auf Google Maps öffnen ↗
                </div>
              </div>
              
              {/* very subtle film/vignette to blend with site */}
              <div className="absolute inset-0 pointer-events-none" style={{
                background: 'radial-gradient(ellipse at 50% 50%, transparent 60%, rgba(0,0,0,0.4) 100%)'
              }} />

              {/* map legend overlay */}
              <div className="absolute bottom-3 right-3 md:bottom-5 md:right-5 font-mono text-[9px] md:text-[10px] tracking-[0.3em] text-bone/70 bg-black/60 backdrop-blur-sm px-3 py-2 border border-bone/15">EVENTPLAN

              </div>
            </a>

            {/* caption row */}
            <div className="flex flex-wrap items-center justify-between gap-x-8 gap-y-3 mt-5 font-mono text-[10px] tracking-[0.3em] text-bone/55">
              <div className="flex items-center gap-3">
                <span className="inline-block w-4 h-4 border border-blue-400/70 bg-blue-400/20" />
                <span>CAMPING &amp; PARKPLATZ</span>
              </div>
              <div className="flex items-center gap-3">
                <span className="inline-block w-6 h-[2px] bg-orange-400" />
                <span>GEHWEG · CA. 5 MIN</span>
              </div>
              <div className="flex items-center gap-3">
                <span className="inline-block w-4 h-4 rounded-full bg-bone/80" />
                <span>EVENTAREA</span>
              </div>
            </div>
          </div>

          {/* fact bar */}
          <div className="reveal grid grid-cols-2 md:grid-cols-5 gap-y-6 gap-x-6 md:gap-x-12 border-t border-bone/15 pt-8 md:pt-10 font-mono text-[11px] md:text-[12px] tracking-[0.3em] text-bone/70">
            <div>
              <div className="text-bone/35 text-[9px] mb-2 tracking-[0.35em]">KAPAZITÄT</div>
              <div>300</div>
            </div>
            <div>
              <div className="text-bone/35 text-[9px] mb-2 tracking-[0.35em]">ZEIT</div>
              <div>18:00 — ??:00</div>
            </div>
            <div>
              <div className="text-bone/35 text-[9px] mb-2 tracking-[0.35em]">EINLASS</div>
              <div>18:00</div>
            </div>
            <div>
              <div className="text-bone/35 text-[9px] mb-2 tracking-[0.35em]">ALTER</div>
              <div>18+</div>
            </div>
            <div className="col-span-2 md:col-span-1 md:text-right">
              <div className="text-bone/35 text-[9px] mb-2 tracking-[0.35em]">KOORDINATEN</div>
              <div className="leading-[1.5]">47°05&apos;57.7&quot; N<br />15°54&apos;13.1&quot; E</div>
            </div>
          </div>
        </div>
      </div>
    </section>);

}

/* ---------- TEAM ---------- */
const TEAM = [
{ name: 'Felix Seifried', role: 'Obmann', img: window.__resources?.teamFelix || 'assets/team-felix.png' },
{ name: 'Moritz Maier', role: 'Obmann Stv.', img: window.__resources?.teamMoritz || 'assets/team-moritz.png' },
{ name: 'Clemens Seifried', role: 'Kassier', img: window.__resources?.teamClemens || 'assets/team-clemens.png' },
{ name: 'Julian Fabian', role: 'Schriftführer', img: window.__resources?.teamJulian || 'assets/team-julian.png' }];


function Team() {
  return (
    <section id="team" className="relative px-6 md:px-10 py-28 md:py-40 bg-black">
      <div className="max-w-[1500px] mx-auto">
        <div className="reveal flex items-baseline justify-between mb-12 md:mb-20">
          <div className="font-mono text-[10px] md:text-[11px] tracking-[0.4em] text-bone/55">
            03 / TEAM
          </div>
          <div className="font-mono text-[10px] tracking-[0.35em] text-bone/40 hidden md:block">
            VIER MENSCHEN. EINE NACHT.
          </div>
        </div>

        <h2 className="reveal font-serif font-light text-[14vw] md:text-[7.5vw] leading-[0.9] tracking-tight mb-16 md:mb-24 max-w-[1300px]">
          Das Team hinter <span className="italic text-bone/70">Seitopia</span>.
        </h2>

        <div className="grid grid-cols-2 md:grid-cols-4 gap-3 md:gap-5">
          {TEAM.map((p, i) =>
          <article
            key={p.name}
            className="reveal portrait relative aspect-[3/4] overflow-hidden group"
            style={{ transitionDelay: `${i * 80}ms` }}>
            
              {/* portrait image */}
              <img
              src={p.img}
              alt={p.name}
              className="absolute inset-0 w-full h-full object-cover transition-all duration-[1200ms] grayscale group-hover:grayscale-0 scale-[1.02] group-hover:scale-[1.06]"
              style={{ filter: 'brightness(0.85) contrast(1.05)' }} />
            
              {/* darkening overlay */}
              <div className="absolute inset-0" style={{ background: "linear-gradient(rgba(0, 0, 0, 0.25) 0%, rgba(0, 0, 0, 0) 35%, rgba(0, 0, 0, 0) 55%, rgba(0, 0, 0, 0.85) 100%) center center"

            }} />

              {/* meta overlay */}
              <div className="absolute inset-x-0 bottom-0 p-4 md:p-5 flex items-end justify-between z-10">
                <div>
                  <div className="font-serif text-[5vw] md:text-[1.5vw] leading-[1] text-bone">{p.name}</div>
                  <div className="font-mono text-[9px] md:text-[10px] tracking-[0.3em] text-bone/65 mt-2 uppercase">{p.role}</div>
                </div>
              </div>

              {/* index */}
              <div className="absolute top-3 left-3 md:top-4 md:left-4 font-mono text-[9px] tracking-[0.3em] text-bone/70 z-10">
                {String(i + 1).padStart(2, '0')} / 04
              </div>
            </article>
          )}
        </div>
      </div>
    </section>);

}

/* ---------- FOOTER ---------- */
function Footer({ onTickets }) {
  return (
    <footer className="relative bg-black border-t border-bone/10 px-6 md:px-10 py-20 md:py-28">
      <div className="max-w-[1500px] mx-auto flex flex-col gap-14">
        <div className="reveal flex flex-col items-center text-center gap-10 py-10 md:py-16 border-b border-bone/10">
          <div className="font-mono text-[10px] tracking-[0.4em] text-bone/55">25 . 07 . 2026</div>
          <h3 className="font-serif font-light italic text-[16vw] md:text-[8vw] leading-[0.9] tracking-tight">SEI Dabei.

          </h3>
          <button onClick={onTickets} className="btn-ghost px-10 py-4 font-mono uppercase text-[11px] tracking-[0.32em] text-bone">
            Tickets sichern
          </button>
        </div>
        <div className="flex flex-col md:flex-row items-start md:items-end justify-between gap-8">
          <h3 className="font-serif font-light text-[10vw] md:text-[3vw] leading-[1] tracking-tight text-bone/70">
            seitopia.
          </h3>
          <div className="font-mono text-[10px] tracking-[0.35em] text-bone/55 max-w-[320px] md:text-right leading-[1.8]">

          </div>
        </div>

        <div className="grid grid-cols-2 md:grid-cols-4 gap-y-8 gap-x-6 font-mono text-[10px] tracking-[0.3em] text-bone/55">
          <div>
            <div className="text-bone/35 text-[9px] mb-3">KONTAKT</div>
            <div>info@seitopia.com</div>
            <div className="text-bone/40"></div>
          </div>
          <div>
            <div className="text-bone/35 text-[9px] mb-3">FOLGEN</div>
            <div><a href="https://www.instagram.com/seitopia_event/" target="_blank" rel="noopener noreferrer" className="hover:text-bone transition">Instagram</a></div>
            <div></div>
            <div></div>
          </div>
          <div>
            <div className="text-bone/35 text-[9px] mb-3">RECHTLICH</div>
            <div>Impressum</div>
            <div>Datenschutz</div>
            <div>Awareness</div>
          </div>
          <div>
            <div className="text-bone/35 text-[9px] mb-3">NEXT</div>
            <div>SEITOPIA / 27</div>
            <div className="text-bone/40">Save the date — 25.07.26.</div>
          </div>
        </div>

        <div className="flex items-end justify-between border-t border-bone/10 pt-6">
          <div className="font-mono text-[9px] tracking-[0.35em] text-bone/35">
            © SEITOPIA COLLECTIVE / MMXXVI
          </div>
          <div className="font-mono text-[9px] tracking-[0.35em] text-bone/35">

          </div>
        </div>
      </div>
    </footer>);

}

/* ---------- TICKETS OVERLAY ---------- */
function TicketsOverlay({ open, onClose }) {
  useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    const prev = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      document.removeEventListener('keydown', onKey);
      document.body.style.overflow = prev;
    };
  }, [open, onClose]);

  return (
    <div
      onClick={onClose}
      className={`fixed inset-0 z-[200] bg-black transition-opacity duration-700 ${open ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'}`}>
      <div className="absolute inset-0 opacity-30 pointer-events-none">
        <div className="blob b1" />
        <div className="blob b2" />
      </div>

      <button
        onClick={(e) => { e.stopPropagation(); onClose(); }}
        className="absolute top-5 right-6 md:top-7 md:right-10 z-10 font-mono text-[10px] md:text-[11px] tracking-[0.4em] text-bone/70 hover:text-bone transition">
        CLOSE
      </button>

      <div className="absolute top-5 left-6 md:top-7 md:left-10 z-10 flex items-center gap-3">
        <div className="w-2 h-2 rounded-full bg-bone/80 animate-pulse" />
        <div className="font-mono text-[10px] tracking-[0.4em] text-bone/70">SEITOPIA</div>
      </div>

      <div
        onClick={(e) => e.stopPropagation()}
        className="relative h-full flex flex-col items-center justify-center px-6 text-center">
        <div className="font-mono text-[10px] md:text-[11px] tracking-[0.5em] text-bone/55 mb-6 md:mb-8">
          01 / TICKETS
        </div>
        <h2 className="font-serif font-light italic text-[14vw] md:text-[8vw] leading-[0.95] tracking-tight text-bone hero-title-shadow max-w-[1200px]">
          Tickets soon<br />available.
        </h2>
        <div className="mt-8 md:mt-12 font-mono text-[10px] md:text-[11px] tracking-[0.4em] text-bone/65 uppercase">
          Stay tuned · <a href="https://www.instagram.com/seitopia_event/" target="_blank" rel="noopener noreferrer" onClick={(e) => e.stopPropagation()} className="underline underline-offset-4 decoration-bone/30 hover:text-bone hover:decoration-bone transition">@seitopia_event</a>
        </div>
        <div className="mt-10 md:mt-14 font-mono text-[10px] tracking-[0.35em] text-bone/40">
          25.07.2026 / SEITOPIA
        </div>
      </div>
    </div>);

}

/* ---------- APP ---------- */
function App() {
  useReveal();
  const progress = useScrollProgress();
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [ticketsOpen, setTicketsOpen] = useState(false);
  useEffect(() => {
    document.documentElement.style.setProperty('--grain-opacity', t.grainOpacity);
    document.documentElement.style.setProperty('--strobe-opacity', t.strobeIntensity);
    document.documentElement.style.setProperty('--off-highlights', `${t.offsetHighlights}px`);
    document.documentElement.style.setProperty('--off-location', `${t.offsetLocation}px`);
    document.documentElement.style.setProperty('--off-team', `${t.offsetTeam}px`);
  }, [t.grainOpacity, t.strobeIntensity, t.offsetHighlights, t.offsetLocation, t.offsetTeam]);

  const goTickets = () => setTicketsOpen(true);

  return (
    <>
      <Loader />
      <CinemaCursor />
      <Nav progress={progress} onTickets={goTickets} />
      <main>
        <Hero tweaks={t} onTickets={goTickets} />
        <Marquee />
        <Highlights />
        <Location />
        <Team />
        <Footer onTickets={goTickets} />
      </main>
      <TicketsOverlay open={ticketsOpen} onClose={() => setTicketsOpen(false)} />

      {/* tweaks panel */}
      <TweaksPanel title="Tweaks">
        <TweakSection label="Atmosphere">
          <TweakSlider label="Film grain"
          value={t.grainOpacity} min={0} max={0.4} step={0.01}
          onChange={(v) => setTweak('grainOpacity', v)} />
          <TweakSlider label="Strobe intensity"
          value={t.strobeIntensity} min={0} max={0.6} step={0.01}
          onChange={(v) => setTweak('strobeIntensity', v)} />
          <TweakToggle label="Strobe flashes"
          value={t.showStrobe} onChange={(v) => setTweak('showStrobe', v)} />
        </TweakSection>
        <TweakSection label="Hero">
          <TweakText label="CTA label" value={t.ctaLabel}
          onChange={(v) => setTweak('ctaLabel', v)} />
          <TweakText label="Event date" value={t.eventDate}
          onChange={(v) => setTweak('eventDate', v)} />
        </TweakSection>
        <TweakSection label="Navigation">
          <TweakSlider label="Highlights landing"
          value={t.offsetHighlights} min={-400} max={200} step={4} unit="px"
          onChange={(v) => setTweak('offsetHighlights', v)} />
          <TweakSlider label="Location landing"
          value={t.offsetLocation} min={-400} max={200} step={4} unit="px"
          onChange={(v) => setTweak('offsetLocation', v)} />
          <TweakSlider label="Team landing"
          value={t.offsetTeam} min={-400} max={200} step={4} unit="px"
          onChange={(v) => setTweak('offsetTeam', v)} />
        </TweakSection>
      </TweaksPanel>
    </>);

}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);