/* global React, ReactDOM, window */
// Root app — orchestrates intro → picker → site, and manages style + lang state.

const { useState, useEffect, useRef } = React;

function StyleDropdown({ style, lang, copy, onPick, onOpenFull }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    function onDoc(e) {
      if (ref.current && !ref.current.contains(e.target)) setOpen(false);
    }
    if (open) document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [open]);

  const items = [
    { id: 'glass',     name: copy.picker.cards.glass.name,     sub: copy.picker.cards.glass.desc },
    { id: 'organic',   name: copy.picker.cards.organic.name,   sub: copy.picker.cards.organic.desc },
    { id: 'water',     name: copy.picker.cards.water.name,     sub: copy.picker.cards.water.desc },
    { id: 'editorial', name: copy.picker.cards.editorial.name, sub: copy.picker.cards.editorial.desc },
  ];

  return (
    <div className="style-pill-wrap" ref={ref}>
      <button className={`style-pill ${open ? 'open' : ''}`} onClick={() => setOpen(o => !o)}>
        <span className="swatch" />
        <span>{lang === 'he' ? 'בחרי סגנון' : 'Choose a style'}</span>
        <svg className="caret" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
          <path d="M6 9l6 6 6-6"/>
        </svg>
      </button>

      <div className={`style-dropdown ${open ? 'open' : ''}`}>
        <div className="style-dropdown-head">{lang === 'he' ? 'בחרי חוויה' : 'Choose your experience'}</div>
        {items.map(it => (
          <button
            key={it.id}
            className={`style-dropdown-item ${style === it.id ? 'active' : ''}`}
            data-id={it.id}
            onClick={() => { onPick(it.id); setOpen(false); }}>
            <div className="ds-swatch" />
            <div className="ds-info">
              <div className="ds-name">{it.name}</div>
              <div className="ds-sub">{it.sub}</div>
            </div>
            <svg className="ds-check" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M5 13l4 4L19 7"/></svg>
          </button>
        ))}
        <div className="style-dropdown-divider" />
        <button className="ds-full-button" onClick={() => { setOpen(false); onOpenFull(); }}>
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M3 10.5 12 3l9 7.5"/><path d="M5 9.5V20h14V9.5"/></svg>
          {lang === 'he' ? 'חזרה לדף הבית' : 'Back to homepage'}
        </button>
      </div>
    </div>
  );
}

function Splash({ onFinish, lang }) {
  const videoRef = useRef(null);
  const audioRef = useRef(null);
  const [fading, setFading] = React.useState(false);
  // Pick the mobile-friendly opener when the viewport is narrow.
  // Evaluated once on mount so a rotation mid-splash doesn't swap sources.
  const [isMobile] = React.useState(() =>
    typeof window !== 'undefined' && window.matchMedia('(max-width: 760px)').matches
  );
  const videoSrc = isMobile ? 'assets/mobileopening.mp4' : 'assets/3d coverlogo.mp4';

  const finish = () => {
    if (fading) return;
    // Soft-fade the music alongside the visual fade so it doesn't snap off
    const a = audioRef.current;
    if (a && !a.paused) {
      const startVol = a.volume;
      const steps = 12;
      let i = 0;
      const t = setInterval(() => {
        i++;
        a.volume = Math.max(0, startVol * (1 - i / steps));
        if (i >= steps) { clearInterval(t); a.pause(); }
      }, 40);
    }
    setFading(true);
    setTimeout(onFinish, 550);
  };

  useEffect(() => {
    const v = videoRef.current;
    if (v) v.play().catch(() => {});
    const a = audioRef.current;
    if (a) {
      a.volume = 0.7;
      // Browser autoplay policy may block unmuted audio without a user gesture.
      // If it does, the .catch keeps the splash working (just silent for that visit).
      a.play().catch(() => {});
    }
    // Safety: auto-advance after 8s in case video fails to fire 'ended'
    const safety = setTimeout(finish, 8000);
    return () => clearTimeout(safety);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return (
    <div className={`splash${fading ? ' splash-fade' : ''}`}>
      <video
        ref={videoRef}
        className="splash-video"
        src={videoSrc}
        muted
        playsInline
        autoPlay
        preload="auto"
        onEnded={finish}
      />
      {/* Reveal-music scored to the unveiling — fades out with the visual */}
      <audio
        ref={audioRef}
        src="assets/A Revealing Logo Opener.mp3"
        preload="auto"
      />
      <button className="splash-skip" onClick={finish}>
        {lang === 'he' ? "בואי נתחיל את המסע" : "Let's start the journey"}
        <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
          <path d="M5 12h14M13 5l7 7-7 7"/>
        </svg>
      </button>
    </div>
  );
}

const STYLE_CYCLE = ['glass', 'organic', 'water', 'editorial'];
const STYLE_LABELS = {
  en: { glass: 'Liquid Glass', organic: 'Tropical', water: 'Bubbles', editorial: 'Editorial' },
  he: { glass: 'זכוכית', organic: 'טרופי', water: 'בועות', editorial: 'עיתון' },
};

function nextUnseen(currentStyle, seenStyles) {
  const idx = STYLE_CYCLE.indexOf(currentStyle);
  for (let i = 1; i <= STYLE_CYCLE.length; i++) {
    const cand = STYLE_CYCLE[(idx + i) % STYLE_CYCLE.length];
    if (!seenStyles.includes(cand)) return cand;
  }
  return null;
}

function TourProgress({ seenStyles, currentStyle, lang }) {
  return (
    <div
      className="tour-progress"
      title={lang === 'he' ? `${seenStyles.length} מתוך 4 סגנונות` : `${seenStyles.length} of 4 styles seen`}
      aria-label={`${seenStyles.length} of 4 styles seen`}
    >
      {STYLE_CYCLE.map((s) => {
        const seen = seenStyles.includes(s);
        const current = s === currentStyle;
        return (
          <span
            key={s}
            className={`tp-dot tp-${s}${seen ? ' seen' : ''}${current ? ' current' : ''}`}
            aria-hidden="true"
          />
        );
      })}
    </div>
  );
}

function WelcomeNotice({ lang, currentStyle, onDismiss }) {
  return (
    <div className="welcome-notice-backdrop">
    <div className="welcome-notice welcome-notice-interactive" role="dialog" aria-modal="true" aria-labelledby="welcome-notice-title">
      <h2 className="welcome-notice-title" id="welcome-notice-title">
        {lang === 'he' ? 'היי!' : 'Hey!'}
      </h2>
      <p className="welcome-notice-body">
        {lang === 'he' ? (
          <>באתר הזה יש <strong className="welcome-bold">4 סגנונות שונים</strong>. פשוט גללי, והאתר ישתנה לפניך.</>
        ) : (
          <>This site has <strong className="welcome-bold">4 different styles</strong>. Just keep scrolling, and the site will transform as you go.</>
        )}
      </p>
      <p className="welcome-notice-signoff">
        {lang === 'he' ? '✨ תהני מהמסע!' : '✨ Enjoy the journey!'}
      </p>
      <button className="welcome-notice-cta" onClick={onDismiss}>
        {lang === 'he' ? 'בואי נמשיך' : "Let's continue"}
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
          <path d="M5 12h14M13 5l7 7-7 7"/>
        </svg>
      </button>
    </div>
    </div>
  );
}

function DemoEndNotice({ lang, onDismiss, onContact }) {
  return (
    <div className="demo-end-notice" role="dialog" aria-modal="true" aria-labelledby="end-notice-title">
      <div className="demo-end-card">
        <div className="demo-end-eyebrow" id="end-notice-title">
          {lang === 'he' ? 'ראית את כל ארבעת העולמות!' : "You've experienced all 4 worlds!"}
        </div>
        <div className="demo-end-divider" aria-hidden="true">
          <span className="ltc-dot" /><span className="ltc-dot" /><span className="ltc-dot" /><span className="ltc-dot" />
        </div>
        <p className="demo-end-body">
          {lang === 'he' ? (
            <>תוכלי לחזור ולחקור כל סגנון דרך תפריט <strong className="demo-end-choose">"בחרי סגנון"</strong> <strong className="demo-end-or">או</strong> שנתחיל לבנות את העולם היצירתי שלך.</>
          ) : (
            <>You can now revisit all styles through the <strong className="demo-end-choose">"Choose a style"</strong> menu <strong className="demo-end-or">OR</strong> we can start building your own creative world.</>
          )}
        </p>
        <div className="demo-end-actions">
          <button
            className="demo-end-cta demo-end-cta-primary"
            onClick={() => {
              // Open WhatsApp chat in a new tab with a short pre-filled intro.
              const greeting = lang === 'he'
                ? 'היי מיכל! ראיתי את האתר ואשמח לדבר על פרויקט.'
                : "Hi Michal! I saw your site and I'd love to talk about a project.";
              window.open('https://wa.me/972523833028?text=' + encodeURIComponent(greeting), '_blank', 'noopener');
            }}
          >
            {lang === 'he' ? 'בואי נדבר' : "Let's talk"}
            {/* WhatsApp glyph (filled) */}
            <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
              <path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347zM12.05 21.785h-.004a9.87 9.87 0 0 1-5.031-1.378l-.36-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 0 1-1.51-5.26c0-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 0 1 2.893 6.994c-.003 5.45-4.437 9.884-9.886 9.884zm8.413-18.297A11.815 11.815 0 0 0 12.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 0 0 5.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 0 0-3.48-8.413z"/>
            </svg>
          </button>
          <button className="demo-end-cta demo-end-cta-secondary" onClick={onDismiss}>
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" style={{ marginInlineEnd: 6 }}>
              <path d="M19 12H5M12 19l-7-7 7-7"/>
            </svg>
            {lang === 'he' ? 'חזרה' : 'Go back'}
          </button>
        </div>
      </div>
    </div>
  );
}

function DemoChip({ lang, step, total, currentStyle, onSkip, onTakeTour }) {
  const L = STYLE_LABELS[lang] || STYLE_LABELS.en;
  return (
    <div className="demo-chip" role="region" aria-label="Auto demo cycle">
      <div className="demo-chip-progress">
        {STYLE_CYCLE.map((s, i) => (
          <span
            key={s}
            className={`demo-dot demo-dot-${s}${i <= step ? ' seen' : ''}${i === step ? ' current' : ''}`}
            aria-hidden="true"
          />
        ))}
      </div>
      <div className="demo-chip-text">
        <span className="demo-chip-eyebrow">
          {lang === 'he' ? `מציגה כעת · ${step + 1} מתוך ${total}` : `Now showing · ${step + 1} of ${total}`}
        </span>
        <span className="demo-chip-title">{L[currentStyle]} design</span>
      </div>
      <button className="demo-chip-action demo-chip-tour" onClick={onTakeTour}>
        {lang === 'he' ? 'קחי אותי בסיור' : 'Take the tour'}
      </button>
      <button className="demo-chip-action demo-chip-skip" onClick={onSkip}>
        {lang === 'he' ? 'דלגי' : 'Stop demo'}
      </button>
    </div>
  );
}

function TourWalkthrough({ lang, currentStyle, seenStyles, onNext, onContact, onExit }) {
  const L = STYLE_LABELS[lang] || STYLE_LABELS.en;
  const stepIdx = STYLE_CYCLE.indexOf(currentStyle);
  const stepNum = stepIdx + 1;
  const allSeen = STYLE_CYCLE.every((s) => seenStyles.includes(s));
  const next = allSeen ? null : nextUnseen(currentStyle, seenStyles);

  return (
    <div className="tour-walk" role="region" aria-label="Style walkthrough">
      <button className="tour-walk-exit" onClick={onExit} aria-label={lang === 'he' ? 'יציאה מהסיור' : 'Exit tour'}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M18 6L6 18M6 6l12 12"/></svg>
      </button>

      <div className="tour-walk-progress">
        {STYLE_CYCLE.map((s, i) => {
          const seen = seenStyles.includes(s);
          const current = s === currentStyle;
          return (
            <span
              key={s}
              className={`twp-step morph-sw-${s}${seen ? ' seen' : ''}${current ? ' current' : ''}`}
              aria-label={`Step ${i + 1} — ${L[s]}${current ? ' (current)' : ''}`}
            />
          );
        })}
      </div>

      <div className="tour-walk-text">
        <div className="tour-walk-eyebrow">
          {lang === 'he' ? `שלב ${stepNum} מתוך 4` : `Step ${stepNum} of 4`}
        </div>
        <div className="tour-walk-title">
          {L[currentStyle]}
        </div>
      </div>

      {allSeen ? (
        <button className="tour-walk-cta tour-walk-cta-done" onClick={onContact}>
          {lang === 'he' ? 'בואי נדבר' : "Let's talk"}
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 5l7 7-7 7"/></svg>
        </button>
      ) : (
        <button className="tour-walk-cta" onClick={() => onNext(next)}>
          {lang === 'he' ? `הבא: עיצוב ${L[next]}` : `Next: ${L[next]} design`}
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 5l7 7-7 7"/></svg>
        </button>
      )}
    </div>
  );
}

function TourBanner({ lang, currentStyle, seenStyles, onMorph, onContact }) {
  const allSeen = STYLE_CYCLE.every((s) => seenStyles.includes(s));
  const next = allSeen ? null : nextUnseen(currentStyle, seenStyles);
  const L = STYLE_LABELS[lang] || STYLE_LABELS.en;

  if (allSeen) {
    return (
      <section className="tour-banner tour-banner-done">
        <div className="tour-banner-text">
          <div className="tour-banner-eyebrow">
            {lang === 'he' ? 'ראית את כל הארבעה' : "You've seen all four moods"}
          </div>
          <div className="tour-banner-title">
            {lang === 'he' ? 'בוא נעצב את שלך' : "Let's design yours"}
          </div>
        </div>
        <button className="tour-banner-cta" onClick={onContact}>
          {lang === 'he' ? 'בואי נדבר' : 'Get in touch'}
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 5l7 7-7 7"/></svg>
        </button>
      </section>
    );
  }

  return (
    <section className="tour-banner">
      <div className="tour-banner-text">
        <div className="tour-banner-eyebrow">
          {lang === 'he' ? `אתה רואה את האתר במצב ${L[currentStyle]}` : `You're viewing this in ${L[currentStyle]}`}
        </div>
        <div className="tour-banner-title">
          {lang === 'he' ? 'אותו תוכן, מצב רוח אחר' : 'Same content, different mood'}
        </div>
      </div>
      <button className="tour-banner-cta" onClick={() => onMorph(next)} data-next={next}>
        <span className={`tour-banner-swatch morph-sw-${next}`} aria-hidden="true" />
        {lang === 'he' ? `נסה ${L[next]}` : `See it in ${L[next]}`}
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 5l7 7-7 7"/></svg>
      </button>
    </section>
  );
}

function MorphChip({ lang, currentStyle, seenStyles, onMorph, onContact }) {
  const [scrolled, setScrolled] = React.useState(false);
  const [pulse, setPulse] = React.useState(false);

  useEffect(() => {
    function onScroll() { setScrolled(window.scrollY > 600); }
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  // Pulse the chip briefly each time the current style changes
  useEffect(() => {
    setPulse(true);
    const t = setTimeout(() => setPulse(false), 1200);
    return () => clearTimeout(t);
  }, [currentStyle]);

  const cycle = ['glass', 'organic', 'water', 'editorial'];
  const labels = {
    glass:     lang === 'he' ? 'זכוכית'  : 'Liquid Glass',
    organic:   lang === 'he' ? 'טרופי'   : 'Tropical',
    water:     lang === 'he' ? 'בועות'   : 'Bubbles',
    editorial: lang === 'he' ? 'עיתון'   : 'Editorial',
  };
  const allSeen = cycle.every((s) => seenStyles.includes(s));
  const next = (() => {
    if (allSeen) return null;
    const idx = cycle.indexOf(currentStyle);
    for (let i = 1; i <= cycle.length; i++) {
      const cand = cycle[(idx + i) % cycle.length];
      if (!seenStyles.includes(cand)) return cand;
    }
    return null;
  })();

  if (!scrolled) return null;

  if (allSeen) {
    return (
      <button className={`morph-chip morph-chip-done${pulse ? ' pulse' : ''}`} onClick={onContact}>
        <span className="morph-chip-eyebrow">
          {lang === 'he' ? 'ראית את כל הארבעה' : "You've seen all four"}
        </span>
        <span className="morph-chip-action">
          {lang === 'he' ? 'בואי נדבר' : "Let's talk"}
          <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 5l7 7-7 7"/></svg>
        </span>
      </button>
    );
  }

  return (
    <button
      className={`morph-chip${pulse ? ' pulse' : ''}`}
      data-next={next}
      onClick={() => onMorph(next)}
    >
      <span className={`morph-chip-swatch morph-sw-${next}`} aria-hidden="true" />
      <span className="morph-chip-text">
        <span className="morph-chip-eyebrow">
          {lang === 'he' ? 'אותו תוכן, מצב רוח אחר' : 'Same content, different mood'}
        </span>
        <span className="morph-chip-action">
          {lang === 'he' ? `נסה ${labels[next]}` : `Try ${labels[next]}`}
          <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.6" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 5l7 7-7 7"/></svg>
        </span>
      </span>
    </button>
  );
}

function App() {
  // Splash plays on every page load
  const [stage, setStage] = useState('splash'); // splash | intro | picker | site
  const [style, setStyle] = useState(null);     // glass | organic | water | editorial
  const [seenStyles, setSeenStyles] = useState([]);
  const [tourMode, setTourMode] = useState(false);
  const [demoActive, setDemoActive] = useState(false);
  const [demoStep, setDemoStep] = useState(0);
  const [welcomeNotice, setWelcomeNotice] = useState(false);
  const [noticeShown, setNoticeShown] = useState(false);
  const [endNotice, setEndNotice] = useState(false);
  const [lang, setLang] = useState('en');
  const [activeSec, setActiveSec] = useState('home');
  const [showPicker, setShowPicker] = useState(false);
  const [scrolled, setScrolled] = useState(false);
  const [showBackToTop, setShowBackToTop] = useState(false);
  const cursorRef = useRef(null);

  // Back-to-top button visibility — fires after visitor scrolls past ~1.5 viewport heights
  useEffect(() => {
    if (stage !== 'site') return;
    function onScroll() {
      setShowBackToTop(window.scrollY > window.innerHeight * 1.2);
    }
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, [stage]);

  function finishSplash() {
    // Skip the welcome page — go straight to the site in Liquid Glass.
    // The welcome notice will appear later, when the visitor reaches About.
    setStyle('glass');
    setStage('site');
    setDemoStep(0);
  }

  function dismissWelcomeNotice() {
    setWelcomeNotice(false);
    setDemoActive(true); // kick off the scroll-based demo once visitor clicks "Let's continue"
  }

  function stopDemo() {
    setDemoActive(false);
  }

  const copy = window.COPY[lang];

  // Apply document attrs
  useEffect(() => {
    document.documentElement.dir = copy.dir;
    document.body.setAttribute('dir', copy.dir);
    document.documentElement.lang = lang;
  }, [lang, copy.dir]);

  useEffect(() => {
    if (style) {
      document.body.setAttribute('data-style', style);
      setSeenStyles((prev) => prev.includes(style) ? prev : [...prev, style]);
    } else {
      document.body.removeAttribute('data-style');
    }
  }, [style]);

  // Morph to a new style with an elegant cross-fade + blur,
  // keeping the visitor at the same scroll position they were viewing.
  function morphToStyle(nextStyle) {
    if (!style || nextStyle === style) return;
    const shell = document.querySelector('.app-shell');
    const targetSec = activeSec;
    const sectionEl = document.getElementById(targetSec);
    const sectionTop = sectionEl ? sectionEl.offsetTop : 0;
    const offsetWithinSection = window.scrollY - sectionTop;
    // Tropical (organic) gets a longer, more atmospheric transition
    const isOrganic = nextStyle === 'organic';
    const fadeDelay = isOrganic ? 480 : 280;
    if (shell) {
      shell.classList.add('style-morphing');
      if (isOrganic) shell.classList.add('style-morphing--organic');
    }
    setTimeout(() => {
      setStyle(nextStyle);
      requestAnimationFrame(() => {
        requestAnimationFrame(() => {
          const newSectionEl = document.getElementById(targetSec);
          const newSectionTop = newSectionEl ? newSectionEl.offsetTop : 0;
          const restoredY = newSectionTop + offsetWithinSection;
          window.scrollTo({ top: restoredY, behavior: 'auto' });
          setTimeout(() => {
            if (shell) {
              shell.classList.remove('style-morphing');
              shell.classList.remove('style-morphing--organic');
            }
          }, isOrganic ? 400 : 200);
        });
      });
    }, fadeDelay);
  }

  // Cursor blob (only when site is active)
  useEffect(() => {
    if (stage !== 'site') return;
    let raf;
    let tx = window.innerWidth / 2, ty = window.innerHeight / 2;
    let cx = tx, cy = ty;
    function onMove(e) { tx = e.clientX; ty = e.clientY; }
    function loop() {
      cx += (tx - cx) * 0.12;
      cy += (ty - cy) * 0.12;
      if (cursorRef.current) {
        cursorRef.current.style.transform = `translate(${cx}px, ${cy}px) translate(-50%,-50%)`;
      }
      raf = requestAnimationFrame(loop);
    }
    window.addEventListener('mousemove', onMove);
    loop();
    return () => { window.removeEventListener('mousemove', onMove); cancelAnimationFrame(raf); };
  }, [stage]);

  // Welcome notice — pops up ONLY when in Liquid Glass and visitor reaches
  // the About section for the first time. Stays until the visitor clicks
  // "Let's continue" — then the scroll-based demo morphs begin.
  useEffect(() => {
    if (stage !== 'site') return;
    if (noticeShown) return;
    if (style !== 'glass') return; // notice only shows during Liquid Glass
    if (activeSec !== 'about') return;
    setWelcomeNotice(true);
    setNoticeShown(true);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [activeSec, stage, noticeShown, style]);

  // Scroll-based demo — each section gets its own style; morph only happens
  // when entering a new section (not in the middle), so it's never confusing.
  // Mapping: Home/About = Glass, Services = Tropical, Works = Bubbles, Contact = Editorial.
  useEffect(() => {
    if (!demoActive) return;
    if (stage !== 'site') return;
    const SECTION_TO_STYLE = {
      home:     'glass',
      about:    'glass',
      services: 'organic',
      works:    'water',
      contact:  'editorial',
    };
    const targetStyle = SECTION_TO_STYLE[activeSec];
    if (!targetStyle) return;
    if (targetStyle === style) return;
    morphToStyle(targetStyle);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [activeSec, demoActive, stage, style]);

  // End-of-journey trigger — once Editorial is active, watch for the visitor
  // to stop scrolling. The notice pops 2 seconds after their last scroll.
  // Each scroll event resets the timer, so they can browse freely.
  useEffect(() => {
    if (!demoActive) return;
    if (stage !== 'site') return;
    if (style !== 'editorial') return;
    let timer = null;
    function scheduleNotice() {
      if (timer) clearTimeout(timer);
      timer = setTimeout(() => {
        setDemoActive(false);
        setEndNotice(true);
      }, 1000); // 1s of scroll-idle in editorial → notice
    }
    window.addEventListener('scroll', scheduleNotice, { passive: true });
    // Start the timer as soon as editorial activates, so the notice still
    // arrives even if the visitor doesn't scroll further.
    scheduleNotice();
    return () => {
      if (timer) clearTimeout(timer);
      window.removeEventListener('scroll', scheduleNotice);
    };
  }, [demoActive, stage, style]);

  // Derive the demo step from the current style for the floating chip
  const demoStepDerived = ['glass', 'organic', 'water', 'editorial'].indexOf(style);

  // Scrollspy + topbar-scrolled state
  useEffect(() => {
    if (stage !== 'site') return;
    const ids = ['home','about','services','works','contact'];
    function onScroll() {
      const y = window.scrollY + window.innerHeight * 0.4;
      let cur = ids[0];
      for (const id of ids) {
        const el = document.getElementById(id);
        if (el && el.offsetTop <= y) cur = id;
      }
      setActiveSec(cur);
      setScrolled(window.scrollY > 40);
    }
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, [stage]);

  function jumpTo(id) {
    const el = document.getElementById(id);
    if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
  }

  function pickStyle(s) {
    setStyle(s);
    setStage('site');
    setShowPicker(false);
    setTourMode(false); // a manual pick from the homepage is not a tour
    setDemoActive(false); // stop auto-cycle if user manually picks
    // smooth scroll back to top
    window.scrollTo({ top: 0, behavior: 'instant' in window ? 'instant' : 'auto' });
  }

  function startTour() {
    setSeenStyles([]);
    setTourMode(true);
    setStyle('glass');
    setStage('site');
    setShowPicker(false);
    window.scrollTo({ top: 0, behavior: 'instant' in window ? 'instant' : 'auto' });
  }

  return (
    <>
      {/* Background per style */}
      {stage === 'site' && style && <window.StyleBackground style={style} />}

      {/* Cursor blob */}
      {stage === 'site' && <div ref={cursorRef} className="cursor-blob" />}

      {/* Top bar (always present once site is up) */}
      {stage === 'site' && (
        <div className={`topbar${scrolled ? ' topbar-scrolled' : ''}`}>
          <div
            className="brand-mark"
            onClick={() => {
              // Replay the full intro from the logo unveiling
              setStyle(null);
              setStage('splash');
              setNoticeShown(false);
              setDemoActive(false);
              setDemoStep(0);
              setSeenStyles([]);
              setTourMode(false);
              window.scrollTo(0, 0);
            }}
            role="link"
            aria-label="Back to homepage"
            style={{ cursor: 'pointer' }}
          >
            <window.Logo variant={style} size={210} />
          </div>
          <div className="top-controls">
            {tourMode && <TourProgress seenStyles={seenStyles} currentStyle={style} lang={lang} />}
            <StyleDropdown
              style={style}
              lang={lang}
              copy={copy}
              onPick={(s) => {
                // Capture exact scroll position relative to the current section
                const targetSec = activeSec;
                const sectionEl = document.getElementById(targetSec);
                const sectionTop = sectionEl ? sectionEl.offsetTop : 0;
                const offsetWithinSection = window.scrollY - sectionTop;
                setStyle(s);
                setDemoActive(false); // manual style change interrupts demo
                requestAnimationFrame(() => {
                  requestAnimationFrame(() => {
                    const newSectionEl = document.getElementById(targetSec);
                    const newSectionTop = newSectionEl ? newSectionEl.offsetTop : 0;
                    window.scrollTo({ top: newSectionTop + offsetWithinSection, behavior: 'auto' });
                  });
                });
              }}
              onOpenFull={() => {
                // Replay the full intro: 3D logo unveiling splash → site in Glass
                // → welcome notice → auto-cycle demo. Reset all related state.
                setStyle(null);
                setStage('splash');
                setNoticeShown(false);
                setDemoActive(false);
                setDemoStep(0);
                setSeenStyles([]);
                setTourMode(false);
                window.scrollTo(0, 0);
              }}
            />
            <div className="lang-toggle">
              <button className={lang === 'en' ? 'active' : ''} onClick={() => setLang('en')}>EN</button>
              <button className={lang === 'he' ? 'active' : ''} onClick={() => setLang('he')}>עב</button>
            </div>
          </div>
        </div>
      )}

      {/* Stage nav */}
      {stage === 'site' && (
        <window.StageNav copy={copy} active={activeSec} onJump={jumpTo} />
      )}

      {/* Morph chip (Option C — disabled while testing Option A)
      {stage === 'site' && style && (
        <MorphChip
          lang={lang}
          currentStyle={style}
          seenStyles={seenStyles}
          onMorph={morphToStyle}
          onContact={() => jumpTo('contact')}
        />
      )}
      */}

      {/* Skip link — keyboard-only users jump past the topbar to main content */}
      {stage === 'site' && (
        <a className="skip-to-content" href="#main-content">
          {lang === 'he' ? 'דלגי לתוכן' : 'Skip to content'}
        </a>
      )}

      {/* Back-to-top button — appears after scrolling past ~1.2 viewports */}
      {stage === 'site' && (
        <button
          type="button"
          className={`back-to-top${showBackToTop ? ' back-to-top--visible' : ''}`}
          onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
          aria-label={lang === 'he' ? 'חזרה למעלה' : 'Back to top'}
        >
          <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
            <path d="M12 19V5M5 12l7-7 7 7"/>
          </svg>
        </button>
      )}

      {/* Site sections */}
      {stage === 'site' && style && (
        <main className="app-shell" id="main-content">
          <window.Hero copy={copy} style={style} lang={lang} onCTA={(id) => jumpTo(id)} />
          <window.About copy={copy} style={style} />
          <window.Services copy={copy} style={style} />
          <window.Works copy={copy} style={style} />
          <window.Testimonials copy={copy} lang={lang} />
          <window.Contact copy={copy} style={style} />
          <window.Footer copy={copy} />
        </main>
      )}

      {/* Welcome notice — shown once on About in Liquid Glass; dismissed by button */}
      {stage === 'site' && style && welcomeNotice && (
        <WelcomeNotice
          lang={lang}
          currentStyle={style}
          onDismiss={dismissWelcomeNotice}
        />
      )}

      {/* End-of-demo notice — Michal's signature message after cycle completes */}
      {stage === 'site' && style && endNotice && (
        <DemoEndNotice
          lang={lang}
          onDismiss={() => setEndNotice(false)}
          onContact={() => { setEndNotice(false); jumpTo('contact'); }}
        />
      )}

      {/* Demo cycle chip removed — the scroll-based morphs speak for themselves */}

      {/* Tour walkthrough — appears once visitor reaches Services and onward */}
      {stage === 'site' && style && tourMode &&
       (activeSec === 'services' || activeSec === 'works' || activeSec === 'contact') && (
        <TourWalkthrough
          lang={lang}
          currentStyle={style}
          seenStyles={seenStyles}
          onNext={morphToStyle}
          onContact={() => jumpTo('contact')}
          onExit={() => setTourMode(false)}
        />
      )}

      {/* Full-screen style picker (in-site overlay, opened from style dropdown) */}
      {showPicker && (
        <window.StylePicker
          copy={copy}
          visible={true}
          onPick={pickStyle}
          onSkip={() => setShowPicker(false)}
        />
      )}


      {/* Splash — 3D logo unveiling on first visit */}
      {stage === 'splash' && (
        <Splash lang={lang} onFinish={finishSplash} />
      )}

      {/* Landing screen — logo + slogan + 3 style cards */}
      {stage === 'intro' && (
        <window.LandingScreen
          copy={copy}
          lang={lang}
          onPick={pickStyle}
          onStartTour={startTour}
        />
      )}

      {/* Tweaks panel */}
      {stage === 'site' && style && (
        <window.MichalTweaks
          style={style}
          setStyle={setStyle}
          lang={lang}
          setLang={setLang}
          copy={copy}
          onShowPicker={() => setShowPicker(true)}
        />
      )}

      {/* Lang toggle on landing screen */}
      {stage === 'intro' && (
        <div style={{ position: 'fixed', top: 22, right: 22, zIndex: 200 }}>
          <div className="lang-toggle" style={{
            background: 'rgba(255,255,255,0.12)',
            border: '1px solid rgba(255,255,255,0.18)',
            backdropFilter: 'blur(8px)',
          }}>
            <button
              style={{ color: lang === 'en' ? '#fff' : 'rgba(255,255,255,0.45)', background: lang === 'en' ? 'rgba(255,255,255,0.18)' : 'transparent' }}
              onClick={() => setLang('en')}>EN</button>
            <button
              style={{ color: lang === 'he' ? '#fff' : 'rgba(255,255,255,0.45)', background: lang === 'he' ? 'rgba(255,255,255,0.18)' : 'transparent' }}
              onClick={() => setLang('he')}>עב</button>
          </div>
        </div>
      )}
    </>
  );
}

// Wait for all window globals to be set by the other Babel scripts before rendering,
// because Babel standalone compiles external scripts asynchronously (no guaranteed order).
const REQUIRED_GLOBALS = [
  'LandingScreen', 'StylePicker',
  'StyleBackground', 'Logo',
  'StageNav', 'Hero', 'About', 'Services', 'Works', 'Contact', 'Footer', 'LeafDivider',
  'MichalTweaks',
];

function mountWhenReady() {
  if (REQUIRED_GLOBALS.every(k => typeof window[k] === 'function')) {
    ReactDOM.createRoot(document.getElementById('root')).render(<App />);
  } else {
    requestAnimationFrame(mountWhenReady);
  }
}
mountWhenReady();
