/* Studio 76 — app shell, tweaks, motion orchestration. */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#C2552B",
  "displayFont": "Archivo",
  "heroImage": "noir-a",
  "heroLayout": "split",
  "heroDark": true,
  "grain": true
}/*EDITMODE-END*/;

const DISPLAY_FONTS = {
  'Archivo':              { family: "'Archivo', sans-serif",              weight: 900, tracking: '-0.02em' },
  'Big Shoulders Display':{ family: "'Big Shoulders Display', sans-serif",weight: 800, tracking: '0.005em' },
  'Anton':                { family: "'Anton', sans-serif",               weight: 400, tracking: '0.005em' },
};

function useScrollReveal(dep) {
  React.useEffect(() => {
    // Enable the entrance only if the rendering timeline is actually live.
    // A throttled/offscreen iframe freezes WAAPI, so .finished never resolves
    // and we leave content fully visible (no opacity:0 trap).
    let cancelled = false;
    try {
      const probe = document.createElement('div');
      probe.style.cssText = 'position:fixed;width:1px;height:1px;opacity:0;pointer-events:none;left:-9px;top:-9px';
      document.body.appendChild(probe);
      const anim = probe.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 30 });
      anim.finished.then(() => {
        if (!cancelled) document.documentElement.classList.add('reveal-on');
        probe.remove();
        check();
      }).catch(() => probe.remove());
    } catch (e) { /* no WAAPI → stay visible */ }

    let raf = 0;
    function check() {
      raf = 0;
      const vh = window.innerHeight;
      document.querySelectorAll('.reveal:not(.in)').forEach((el) => {
        const r = el.getBoundingClientRect();
        if (r.top < vh * 0.9 && r.bottom > 0) el.classList.add('in');
      });
    }
    const onScroll = () => { if (!raf) raf = requestAnimationFrame(check); };
    check();
    const t1 = setTimeout(check, 200);
    const t2 = setTimeout(check, 800);
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    return () => {
      cancelled = true;
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
      clearTimeout(t1); clearTimeout(t2); if (raf) cancelAnimationFrame(raf);
    };
  }, [dep]);
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  // apply theme tweaks to :root
  React.useEffect(() => {
    const r = document.documentElement.style;
    r.setProperty('--accent', t.accent);
    const df = DISPLAY_FONTS[t.displayFont] || DISPLAY_FONTS['Archivo'];
    r.setProperty('--font-display', df.family);
    r.setProperty('--display-weight', df.weight);
    r.setProperty('--display-tracking', df.tracking);
  }, [t.accent, t.displayFont]);

  useScrollReveal(JSON.stringify([t.heroLayout, t.heroImage, t.heroDark]));

  // ?hero=ivory|noir-a|noir-b — shareable hero-variant preview, overrides the tweak
  const heroPick = React.useMemo(() => {
    const q = new URLSearchParams(window.location.search).get('hero');
    return ['noir-a', 'noir-b', 'ivory'].indexOf(q) >= 0 ? q : t.heroImage;
  }, [t.heroImage]);

  const begin = React.useCallback(() => {
    const el = document.getElementById('studio');
    if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 70, behavior: 'smooth' });
  }, []);

  return (
    <React.Fragment>
      {t.grain && <div className="grain"></div>}
      <Nav accent={t.accent} onBegin={begin} light={heroPick === 'ivory'} />
      <main>
        <Hero t={{...t, heroImage: heroPick}} onBegin={begin} />
        <Marquee />
        <Inspiration onBegin={begin} />
        <Imaginarium onBegin={begin} />
        <BenchPromo />
        <LatestSets />
        <HowItWorks />
        <Studio accent={t.accent} />
        <Gallery onBegin={begin} />
        <Compare />
        <Story />
        <Process />
        <Jewellers />
        <CTA />
      </main>
      <Footer />

      <MobileBar onBegin={begin} />

      <TweaksPanel title="Tweaks">
        <TweakSection label="Brand accent" />
        <TweakColor label="Accent / CTAs" value={t.accent}
          options={['#C2552B', '#E8732B', '#9E2B2B', '#1E6F5B']}
          onChange={(v) => setTweak('accent', v)} />
        <TweakSection label="Display type" />
        <TweakSelect label="Headline font" value={t.displayFont}
          options={['Archivo', 'Big Shoulders Display', 'Anton']}
          onChange={(v) => setTweak('displayFont', v)} />
        <TweakSection label="Hero" />
        <TweakRadio label="Campaign shot" value={t.heroImage}
          options={['noir-a', 'noir-b', 'ivory']}
          onChange={(v) => setTweak('heroImage', v)} />
        <TweakSection label="Texture" />
        <TweakToggle label="Film grain" value={t.grain}
          onChange={(v) => setTweak('grain', v)} />
      </TweaksPanel>
    </React.Fragment>
  );
}

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