// ===== Shared visual components and small primitives =====

const { useState, useEffect, useRef, useMemo, useCallback } = React;

// -------- Icons (custom inline SVG, no external lib) --------
const Icon = {
  Plane: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5"
         strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M2 14l8-2 6-8 2 .5-3 9 5 2 .5 2-4-1-5 7-2 .5 1-6-7 2-1.5L2 14z"/>
    </svg>
  ),
  PlaneTilt: (p) => (
    <svg viewBox="0 0 24 24" fill="currentColor" {...p}>
      <path d="M21 4.6c.2-.2.5-.1.5.2v1.6c0 .3-.1.7-.4.9l-7 5.4 1.5 6c.1.3-.1.6-.4.7l-.8.2c-.2 0-.4 0-.5-.2L10 14l-3 2.3-.2 1.6c0 .2-.2.4-.4.5l-.5.2c-.3.1-.6 0-.7-.3L4 16.8l-1.5-1.1c-.3-.2-.3-.6 0-.8l.4-.3c.2-.1.4-.2.6-.2l1.6.1L7.4 12 4 7.2c-.1-.2-.1-.4 0-.6l.4-.6c.1-.2.4-.3.6-.2l5.9 1.7L21 4.6z"/>
    </svg>
  ),
  Compass: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4"
         strokeLinecap="round" strokeLinejoin="round" {...p}>
      <circle cx="12" cy="12" r="9.5"/>
      <path d="M15 9l-1.5 4.5L9 15l1.5-4.5L15 9z" fill="currentColor"/>
    </svg>
  ),
  Globe: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4"
         strokeLinecap="round" strokeLinejoin="round" {...p}>
      <circle cx="12" cy="12" r="9.5"/>
      <ellipse cx="12" cy="12" rx="4" ry="9.5"/>
      <path d="M2.5 12h19M3.5 7.5h17M3.5 16.5h17"/>
    </svg>
  ),
  Clock: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4"
         strokeLinecap="round" strokeLinejoin="round" {...p}>
      <circle cx="12" cy="12" r="9.5"/>
      <path d="M12 6.5v6l4 2.5"/>
    </svg>
  ),
  Star: (p) => (
    <svg viewBox="0 0 24 24" fill="currentColor" {...p}>
      <path d="M12 2l2.7 6.6L22 9.3l-5.3 4.7L18.3 22 12 18l-6.3 4 1.6-8L2 9.3l7.3-.7L12 2z"/>
    </svg>
  ),
  Ticket: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4"
         strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M3 7a2 2 0 012-2h14a2 2 0 012 2v3a2 2 0 000 4v3a2 2 0 01-2 2H5a2 2 0 01-2-2v-3a2 2 0 000-4V7z"/>
      <path d="M12 5v14" strokeDasharray="2 3"/>
    </svg>
  ),
  Camera: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.4"
         strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M3 8.5A2.5 2.5 0 015.5 6H8l1.5-2h5L16 6h2.5A2.5 2.5 0 0121 8.5v9A2.5 2.5 0 0118.5 20h-13A2.5 2.5 0 013 17.5v-9z"/>
      <circle cx="12" cy="13" r="3.5"/>
    </svg>
  ),
  ArrowEast: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"
         strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M4 12h15M14 7l5 5-5 5"/>
    </svg>
  ),
  ArrowWest: (p) => (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6"
         strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M20 12H5M10 7l-5 5 5 5"/>
    </svg>
  ),
  Heart: (p) => (
    <svg viewBox="0 0 24 24" fill="currentColor" {...p}>
      <path d="M12 21s-7.5-4.6-9.5-9.5C1 7.6 4.2 4 7.8 4c2 0 3.4 1.1 4.2 2.3C12.8 5.1 14.2 4 16.2 4 19.8 4 23 7.6 21.5 11.5 19.5 16.4 12 21 12 21z"/>
    </svg>
  ),
};

// -------- Animated number counter --------
function useInView(ref, threshold = 0.2) {
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    if (!ref.current || seen) return;
    const obs = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) { setSeen(true); obs.disconnect(); }
      });
    }, { threshold });
    obs.observe(ref.current);
    return () => obs.disconnect();
  }, [ref, threshold, seen]);
  return seen;
}

function Counter({ to, suffix = "", decimals = 0, duration = 1800, className }) {
  const ref = useRef(null);
  const seen = useInView(ref, 0.25);
  const [val, setVal] = useState(0);
  useEffect(() => {
    if (!seen) return;
    const start = performance.now();
    let raf;
    const tick = (t) => {
      const p = Math.min(1, (t - start) / duration);
      // easeOutCubic
      const e = 1 - Math.pow(1 - p, 3);
      setVal(to * e);
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [seen, to, duration]);
  const formatted = useMemo(() => {
    if (decimals > 0) return val.toLocaleString("de-DE", { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
    return Math.round(val).toLocaleString("de-DE");
  }, [val, decimals]);
  return (
    <span ref={ref} className={className}>
      {formatted}
      {suffix}
    </span>
  );
}

// -------- Reveal wrapper --------
function Reveal({ as: As = "div", delay = 0, className = "", children, ...rest }) {
  const ref = useRef(null);
  const seen = useInView(ref, 0.15);
  const delayClass = delay ? `reveal-delay-${delay}` : "";
  return (
    <As
      ref={ref}
      className={`reveal ${delayClass} ${seen ? "in" : ""} ${className}`}
      {...rest}
    >
      {children}
    </As>
  );
}

// -------- Section shell --------
function Section({ id, eyebrow, kicker, title, intro, dark = false, children, className = "" }) {
  const surface = dark
    ? "starry text-cream"
    : "paper-soft text-night";
  return (
    <section id={id} className={`${surface} ${className} relative overflow-hidden`}>
      <div className="mx-auto max-w-7xl px-6 md:px-10 py-20 md:py-28">
        <Reveal className="flex items-baseline gap-4 mb-6">
          <span className={`font-mono text-[11px] tracking-[0.25em] uppercase ${dark ? "text-amber" : "text-amber-deep"}`}>
            {kicker}
          </span>
          <span className={`font-mono text-[11px] tracking-[0.25em] uppercase ${dark ? "text-cream/40" : "text-night/40"}`}>
            {eyebrow}
          </span>
        </Reveal>
        <Reveal delay={1}>
          <h2 className={`font-display text-4xl md:text-6xl leading-[1.05] tracking-tight ${dark ? "text-cream" : "text-night"}`}>
            {title}
          </h2>
          {intro && (
            <p className={`mt-5 max-w-2xl text-base md:text-lg leading-relaxed ${dark ? "text-cream/80" : "text-night/70"}`}>
              {intro}
            </p>
          )}
        </Reveal>
        <div className="mt-10 md:mt-14">{children}</div>
      </div>
    </section>
  );
}

// -------- Photo placeholder (clearly marked, with code-like comment) --------
function Photo({ note, ratio = "4/3", className = "", code = "" }) {
  return (
    <div
      className={`relative w-full overflow-hidden bg-cream-soft border border-night/10 ${className}`}
      style={{ aspectRatio: ratio }}
    >
      <div
        className="absolute inset-0 opacity-60"
        style={{
          backgroundImage:
            "repeating-linear-gradient(135deg, rgba(5,22,77,.08) 0 1px, transparent 1px 14px)",
        }}
      />
      <div className="absolute inset-0 flex flex-col p-4 justify-between">
        <div className="flex items-center gap-2 text-night/50 font-mono text-[10px] uppercase tracking-widest">
          <Icon.Camera width="14" height="14" />
          <span>Foto‑Platzhalter</span>
        </div>
        <div className="text-night/55 font-mono text-[11px] leading-relaxed">
          {code && <div className="text-amber-deep">{`// ${code}`}</div>}
          <div>{note}</div>
        </div>
      </div>
    </div>
  );
}

// -------- Stat block (counter + label) --------
function Stat({ value, label, suffix = "", note, decimals = 0, big = false, dark = false }) {
  const numColor = dark ? "text-amber" : "text-night";
  const labelColor = dark ? "text-cream/80" : "text-night/70";
  const noteColor = dark ? "text-cream/50" : "text-night/45";
  return (
    <div className="flex flex-col gap-2">
      <div className={`font-display ${big ? "text-6xl md:text-7xl" : "text-5xl md:text-6xl"} leading-none ${numColor}`}>
        <Counter to={value} suffix={suffix} decimals={decimals} />
      </div>
      <div className="stat-rule" />
      <div className={`font-sans uppercase tracking-[0.18em] text-[11px] ${labelColor}`}>{label}</div>
      {note && <div className={`text-sm font-display italic ${noteColor}`}>{note}</div>}
    </div>
  );
}

// -------- Tiny pill / chip --------
function Pill({ children, tone = "amber", className = "" }) {
  const tones = {
    amber: "bg-amber/15 text-amber-deep border-amber/40",
    night: "bg-night/5 text-night border-night/15",
    inv:   "bg-cream/10 text-cream border-cream/25",
  };
  return (
    <span className={`inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full border font-mono uppercase tracking-[0.18em] text-[10px] ${tones[tone]} ${className}`}>
      {children}
    </span>
  );
}

// -------- Boarding-card-like header strip --------
function Stub({ left, right, dark = false, className = "" }) {
  const bg = dark ? "bg-night text-cream" : "bg-cream-soft text-night";
  return (
    <div className={`${bg} flex items-stretch gap-0 border ${dark ? "border-cream/15" : "border-night/15"} ${className}`}>
      <div className="flex-1 px-5 py-3">{left}</div>
      <div className={`perf-v ${dark ? "text-cream/30" : "text-night/30"}`} />
      <div className="px-5 py-3">{right}</div>
    </div>
  );
}

Object.assign(window, {
  Icon, Counter, Reveal, Section, Photo, Stat, Pill, Stub, useInView
});
