/* global React */

const { useEffect, useRef, useState } = React;

/* ---------- Nav ---------- */
function Nav() {
  const { t } = useLang();
  return (
    <nav className="nav">
      <a href="#top" className="mark" aria-label="Wine Exchange">
        <img className="mark-icon" src="images/wine-exchange-mark.svg" alt="" />
        <span className="mark-word">Wine Exchange</span>
      </a>
      <div className="nav-right">
        <div className="links">
          <a href="#about" className="is-active">{t.nav.initiative}</a>
          <a href="#paths">{t.nav.openCall}</a>
          <a href="mailto:hello@winedesign.exchange">{t.nav.contact}</a>
        </div>
        <LangSwitcher />
        <a href="mailto:hello@winedesign.exchange?subject=Hosting%20an%20Exchange" className="nav-apply">{t.nav.apply}</a>
      </div>
    </nav>);

}

/* ---------- Hero (parallax landscape) ---------- */
function Hero() {
  const { t } = useLang();
  const sceneRef = useRef(null);

  useEffect(() => {
    const scene = sceneRef.current;
    if (!scene) return;
    const field = scene.querySelector(".px-layer--vineyard");
    if (!field) return;
    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    let raf = 0;
    let mx = 0, my = 0, tmx = 0, tmy = 0;

    // Only the field (vineyard) animates — it drifts and scales from its centre.
    const apply = () => {
      mx += (tmx - mx) * 0.08;
      my += (tmy - my) * 0.08;
      const sc = window.scrollY || window.pageYOffset || 0;
      const scrollShift = sc * 0.1;
      const grow = Math.min(sc, 600) / 600 * 0.06;
      const mxShift = mx * 22;
      const myShift = my * 10;
      field.style.transform =
        `translate3d(${mxShift.toFixed(1)}px, ${(myShift - scrollShift).toFixed(1)}px, 0) scale(${(1.08 + grow).toFixed(3)})`;
      const settling = Math.abs(tmx - mx) > 0.001 || Math.abs(tmy - my) > 0.001;
      raf = settling ? requestAnimationFrame(apply) : 0;
    };
    const kick = () => { if (!raf) raf = requestAnimationFrame(apply); };
    const onScroll = () => kick();
    const onMove = (e) => {
      if (reduce) return;
      const r = scene.getBoundingClientRect();
      tmx = (e.clientX - r.left) / r.width - 0.5;
      tmy = (e.clientY - r.top) / r.height - 0.5;
      kick();
    };
    apply();
    requestAnimationFrame(() => scene.classList.add("is-in"));
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    if (!reduce) window.addEventListener("mousemove", onMove);
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      window.removeEventListener("mousemove", onMove);
      if (raf) cancelAnimationFrame(raf);
    };
  }, []);

  return (
    <section className="hero hero--parallax" id="top" ref={sceneRef}>
      <div className="px-scene">
        <img className="px-layer px-layer--vineyard" src="images/px-vineyard.png" alt="Vineyard landscape" />
        <img className="px-layer px-layer--figures" src="images/px-figures.png" alt="A studio looking out over the vineyard" />
        <div className="px-scrim"></div>
      </div>

      <div className="px-content">
        <h1 className="hero-headline px-headline" data-reveal>
          <span className="reveal-line">
            <span className="reveal-line__inner" style={{ transitionDelay: "150ms" }}>
              {t.hero.headPre}<span className="roman">{t.hero.headRoman}</span><span className="dot">.</span>
            </span>
          </span>
        </h1>
        <p className="px-lede">
          {t.hero.lede}
        </p>
        <a href="mailto:hello@winedesign.exchange?subject=Hosting%20an%20Exchange" className="cta px-cta">
          {t.hero.cta}
          <span className="arrow"></span>
        </a>
      </div>

      <a className="px-credit" href="https://kornelija-illu.squarespace.com" target="_blank" rel="noopener noreferrer">
        {t.hero.illusCredit}
      </a>
    </section>);

}

/* ---------- Marquee ---------- */
function Marquee() {
  const { t } = useLang();
  const items = t.marquee;

  const icons = [
  "images/icon-bottle.png",
  "images/icon-grapes.png",
  "images/icon-drop.png",
  "images/icon-glass.png"];

  const row =
  <>
      {items.map((w, i) =>
    <React.Fragment key={i}>
          <span>{w}</span>
          <img src={icons[i % icons.length]} alt="" className="marquee-icon" />
        </React.Fragment>
    )}
    </>;

  return (
    <div className="marquee">
      <div className="marquee-track">
        {row}{row}{row}
      </div>
    </div>);

}

/* ---------- Section header helper ---------- */
/* Splits heading children on <br/> into individually-masked lines */
function MaskLines({ children }) {
  const lines = [];
  let cur = [];
  React.Children.forEach(children, (ch) => {
    if (ch && ch.type === "br") {
      lines.push(cur);
      cur = [];
    } else {
      cur.push(ch);
    }
  });
  if (cur.length) lines.push(cur);
  return lines.map((line, i) =>
  <span className="reveal-line" key={i}>
      <span className="reveal-line__inner" style={{ transitionDelay: `${i * 75}ms` }}>
        {line}
      </span>
    </span>
  );
}

function SectionHead({ num, children }) {
  return (
    <div className="section-head">
      <span className="label-num num">{num}</span>
      <h2 data-reveal data-parallax="0.035"><MaskLines>{children}</MaskLines></h2>
    </div>);

}

/* ---------- About ---------- */
/* ---------- About + Week (merged section) ---------- */
const PROCESS = [
{ day: "Monday", title: "Immersion", desc: "We walk the vines at dawn, sit with the story, and work out who the wine is really for. ", loc: "Day one" },
{ day: "Tuesday", title: "Strategy", desc: "We settle on what the wine is and — more usefully — what it isn't. ", loc: "Day two" },
{ day: "Wednesday", title: "Identity", desc: "Logo and identity, drawn by hand, then built into type, grid and palette. A name turns up too, if you need one.", loc: "Day three" },
{ day: "Thursday", title: "Packaging", desc: "Label, capsule, neck, case. We mock the bottle up at full size and carry it through every light in the building.", loc: "Day four" },
{ day: "Friday", title: "Refinement", desc: "Edits made standing up. Proofs pulled, papers tested wet, the whole system written into a printed dossier left on your table.", loc: "Day five" },
{ day: "Sat / Sun", title: "Celebration", desc: "The work rests. We open a bottle of yours, mocked up at scale in its new dress, with the family and the harvest crew. A long table, a short speech.", loc: "Day six & seven", weekend: true }];


function ProcessCarousel() {
  const { t } = useLang();
  const PROCESS = t.week.cards;
  const trackRef = useRef(null);
  const scrollBy = (dir) => {
    const el = trackRef.current;
    if (!el) return;
    const step = el.clientWidth * 0.7;
    el.scrollBy({ left: dir * step, behavior: "smooth" });
  };
  return (
    <div className="process-carousel">
      <div className="process-carousel-head">
        <div>
          <span className="label-num">{t.week.eyebrowPrefix}{t.week.taglineB}</span>
          <h3 className="process-carousel-title" data-reveal>
            <span className="reveal-line">
              <span className="reveal-line__inner">{t.week.title}</span>
            </span>
          </h3>
        </div>
        <div className="carousel-controls">
          <button className="carousel-btn" aria-label="Previous" onClick={() => scrollBy(-1)}>
            <span className="arrow-l"></span>
          </button>
          <button className="carousel-btn" aria-label="Next" onClick={() => scrollBy(1)}>
            <span className="arrow-r"></span>
          </button>
        </div>
      </div>

      <div className="process-track" ref={trackRef}>
        {PROCESS.map((row, i) =>
        <div className={`process-card ${row.weekend ? "is-weekend" : ""}`} key={i}>
            <span className="day">{row.day}</span>
            <span className="title">{row.title}.</span>
            <span className="desc" style={{ color: "rgba(0, 0, 0, 0.91)", fontFamily: "Helvetica", fontWeight: "300", fontSize: "15px" }}>{row.desc}</span>
            <span className="meta">{row.loc}</span>
          </div>
        )}
        <div className="process-card process-card--end">
          <span className="day">{t.week.end.day}</span>
          <span className="title">{t.week.end.title}.</span>
          <span className="desc">{t.week.end.desc}</span>
          <span className="meta">{t.week.end.loc}</span>
        </div>
      </div>
      <div className="process-rail-hint">{t.week.hint}</div>
    </div>);

}

function About() {
  const { t } = useLang();
  return (
    <section className="block" id="about">
      <div className="frame" style={{ fontFamily: "\"Helvetica Neue\"" }}>
        <SectionHead num={t.about.num}>
          {brLines(t.about.heading)}
        </SectionHead>

        <div className="about-grid">
          <div className="about-lede">
            {t.about.ledeA}<em>{t.about.ledeEm}</em>{t.about.ledeB}
          </div>
          <div className="about-right">
            <p>{t.about.p1}</p>
            <p>{t.about.p2}</p>
            <p className="mono" style={{ color: "var(--fg-dim)", marginTop: 8 }}>
              {t.about.mono}
            </p>
          </div>
        </div>

        <ProcessCarousel />
      </div>
    </section>);

}

/* ---------- Philosophy ---------- */
function Philosophy() {
  const { t } = useLang();
  return (
    <section className="block philosophy" id="philosophy">
      <div className="frame">
        <blockquote className="reveal">
          {t.philosophy.l1a}<em>{t.philosophy.em1.replace(/ /g, "\u00a0")}</em>.
          <br />
          {t.philosophy.l2a}<em>{t.philosophy.em2.replace(/ /g, "\u00a0")}</em>.
        </blockquote>
        <div className="attrib">{t.philosophy.attrib}</div>
      </div>
      <img className="philosophy-vineyard" src="images/px-landscape-band.png" alt="" aria-hidden="true" />
    </section>);

}

/* ---------- Team ---------- */
function Team() {
  const { t } = useLang();
  return (
    <section className="block team" id="team">
      <div className="frame">
        <SectionHead num={t.team.num}>
          {brLines(t.team.heading)}
        </SectionHead>

        <div className="team-grid">
          <div className="team-copy">
            <p className="team-lede">
              {t.team.ledePre}
              <a href="https://byandstudio.com" target="_blank" rel="noopener noreferrer" className="team-link">andstudio</a>
              {t.team.ledePost1}<br />
              {t.team.ledePost2}
            </p>
            <p className="team-sub">
              {t.team.sub}
            </p>
          </div>
        </div>

        <figure className="team-photo reveal">
          <div className="team-photo-mask">
            <img src="images/team-andstudio.jpg" alt="The andstudio team" loading="lazy" />
          </div>
          <figcaption>{t.team.figcaption}</figcaption>
        </figure>
      </div>
    </section>);

}

/* ---------- Comparison (Wine Exchange vs Agency) ---------- */
function Comparison() {
  const { t } = useLang();
  const COMPARE = t.compare.rows;
  return (
    <section className="block comparison" id="compare">
      <div className="frame">
        <SectionHead num={t.compare.num}>
          {t.compare.heading.map((l, i) => <React.Fragment key={i}>{crossPrice(l)}{i < t.compare.heading.length - 1 ? <br /> : null}</React.Fragment>)}
        </SectionHead>

        <div className="compare-grid">
          <div className="compare-col compare-col--ours">
            <span className="compare-head">{t.compare.oursHead}</span>
            <ul>
              {COMPARE.map((r, i) =>
              <li key={i}>
                  <span className="cbadge cbadge--yes"></span>
                  <span className="ctext">{r.ours}</span>
                </li>
              )}
            </ul>
          </div>
          <div className="compare-col compare-col--theirs">
            <span className="compare-head">{t.compare.theirsHead}</span>
            <ul>
              {COMPARE.map((r, i) =>
              <li key={i}>
                  <span className="cbadge cbadge--no"></span>
                  <span className="ctext">{crossPrice(r.theirs)}</span>
                </li>
              )}
            </ul>
          </div>
        </div>
      </div>
    </section>);

}

function crossPrice(text) {
  const parts = String(text).split(/(€\s?15[.,]000\+?|15[.,]000\s?€\+?)/g);
  return parts.map((p, i) => /15[.,]000/.test(p) ? <s key={i}>{p}</s> : p);
}

/* ---------- Two Paths (winery / studio open call) ---------- */
function TwoPaths() {
  const { t } = useLang();
  return (
    <section className="block two-paths" id="paths">
      <div className="frame">
        <SectionHead num={t.paths.num}>
          {t.paths.heading}
        </SectionHead>

        <div className="paths-grid paths-grid--solo">
          <article className="path path--winery">
            <header>
              <span className="path-tag">{t.paths.tag}</span>
            </header>
            <p className="path-lede">
              {t.paths.lede}
            </p>
            <ul className="path-list">
              {t.paths.list.map((item, i) =>
              <li key={i}><span className="pl-num">{String(i + 1).padStart(2, "0")}</span><span>{crossPrice(item)}</span></li>
              )}
            </ul>
            <div className="path-foot">
              <span className="label-num">{t.paths.footLabel}</span>
              <span className="path-foot-line">{t.paths.footLine}</span>
              <a href="mailto:hello@winedesign.exchange?subject=Hosting%20an%20Exchange" className="cta cta--ink">
                {t.paths.cta}
                <span className="arrow"></span>
              </a>
            </div>
          </article>
        </div>
      </div>
    </section>);

}

/* ---------- CTA ---------- */
function CtaBlock() {
  const { t } = useLang();
  return (
    <section className="cta-block" id="contact">
      <div className="frame">
        <span className="eyebrow" style={{ color: "rgba(239,234,224,0.55)" }}>
          {t.cta.eyebrow}
        </span>
        <h2 style={{ marginTop: 28 }}>
          {t.cta.headPre}<span className="roman">{t.cta.headRoman}</span><br />
          {t.cta.headPost}<span className="dot">.</span>
        </h2>

        <div className="row">
          <div>
            <p>
              {t.cta.p}
            </p>
            <div className="small">{t.cta.small}</div>
          </div>
          <a href="mailto:hello@winedesign.exchange" className="cta">
            {t.cta.cta}
            <span className="arrow"></span>
          </a>
        </div>
      </div>
    </section>);

}

/* ---------- Footer ---------- */
function Footer() {
  const { t } = useLang();
  return (
    <footer>
      <div className="col">
        <h4>{t.footer.initBy}</h4>
        <a href="https://byandstudio.com" target="_blank" rel="noopener noreferrer" className="and-link">
          <img src="images/andstudio-logo.svg" alt="andstudio" className="and-logo" />
          <span className="arrow-inline"></span>
        </a>
        <p style={{ opacity: 0.55, marginTop: 12 }}>
          {brLines(t.footer.studioLine)}
        </p>
      </div>
      <div className="col">
        <h4>{t.footer.correspondence}</h4>
        <a href="mailto:hello@winedesign.exchange">hello@winedesign.exchange</a>
        <a href="https://winedesign.exchange" target="_blank" rel="noopener noreferrer">winedesign.exchange</a>
      </div>
      <div className="col">
        <h4>{t.footer.follow}</h4>
        <a
          href="https://www.instagram.com/byandstudio/"
          target="_blank"
          rel="noopener noreferrer"
          onClick={(e) => {
            e.preventDefault();
            window.open("https://www.instagram.com/byandstudio/", "_blank", "noopener,noreferrer");
          }}>Instagram 


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

}

/* ---------- Tweaks ---------- */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "light",
  "grain": 0.04
} /*EDITMODE-END*/;

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

  useEffect(() => {
    if (t.palette === "light") document.body.removeAttribute("data-palette");else
    document.body.setAttribute("data-palette", t.palette);
  }, [t.palette]);
  useEffect(() => {
    document.documentElement.style.setProperty("--grain", t.grain);
  }, [t.grain]);

  return (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Palette" />
      <TweakRadio
        label="Mood"
        value={t.palette}
        onChange={(v) => setTweak("palette", v)}
        options={[
        { value: "light", label: "Light" },
        { value: "black", label: "Black" },
        { value: "oxblood", label: "Oxblood" }]
        } />
      

      <TweakSection label="Texture" />
      <TweakSlider
        label="Grain"
        value={Math.round(t.grain * 100)}
        onChange={(v) => setTweak("grain", v / 100)}
        min={0} max={20} step={1} unit="%" />
      
    </TweaksPanel>);

}

/* ---------- Cookie / Privacy Banner ---------- */
function PrivacyBanner() {
  const { t } = useLang();
  const [dismissed, setDismissed] = useState(() => {
    try {
      return localStorage.getItem("we-privacy-ack") === "1";
    } catch (_) {
      return false;
    }
  });
  const [open, setOpen] = useState(false);

  if (dismissed) return null;

  const accept = () => {
    try {localStorage.setItem("we-privacy-ack", "1");} catch (_) {}
    setDismissed(true);
  };

  return (
    <div className="privacy-banner" role="dialog" aria-label="Privacy notice">
      <div className="privacy-inner">
        <p className="privacy-copy">
          {t.privacy.copy}
          <button
            type="button"
            className="privacy-more"
            onClick={() => setOpen((v) => !v)}
            aria-expanded={open}>
            {open ? t.privacy.less : t.privacy.more}
          </button>
        </p>
        {open &&
        <p className="privacy-detail">
            {t.privacy.detail}
            <a href="mailto:hello@winedesign.exchange">hello@winedesign.exchange</a>.
          </p>
        }
        <button type="button" className="privacy-accept" onClick={accept}>
          {t.privacy.accept}
        </button>
      </div>
    </div>);

}

/* ---------- App ---------- */
function App() {
  // Apply defaults on first mount
  useEffect(() => {
    if (TWEAK_DEFAULTS.palette !== "light") {
      document.body.setAttribute("data-palette", TWEAK_DEFAULTS.palette);
    }
    document.documentElement.style.setProperty("--grain", TWEAK_DEFAULTS.grain);
  }, []);

  // Scroll-driven reveals + title parallax (rAF; reliable across environments)
  useEffect(() => {
    const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    const fades = Array.from(document.querySelectorAll(".reveal"));
    const titles = Array.from(document.querySelectorAll("[data-reveal]"));
    const parallax = Array.from(document.querySelectorAll("[data-parallax]"));
    let raf = 0;

    const tick = () => {
      const vh = window.innerHeight;
      const trigger = vh * 0.88;
      fades.forEach((el) => {
        if (!el.classList.contains("in") && el.getBoundingClientRect().top < trigger) {
          el.classList.add("in");
        }
      });
      titles.forEach((el) => {
        if (!el.classList.contains("is-in") && el.getBoundingClientRect().top < trigger) {
          el.classList.add("is-in");
        }
      });
      if (!reduce) {
        parallax.forEach((n) => {
          const f = parseFloat(n.getAttribute("data-parallax")) || 0.04;
          const r = n.getBoundingClientRect();
          const center = r.top + r.height / 2;
          const off = (center - vh / 2) * -f;
          n.style.setProperty("--py", `${off.toFixed(1)}px`);
        });
      }
      raf = 0;
    };
    const onScroll = () => {
      if (!raf) raf = requestAnimationFrame(tick);
    };
    // Defer the first reveal pass two frames so on-load (above-the-fold)
    // titles paint their hidden state first, then animate in — otherwise the
    // class lands in the same frame as first paint and the transition is skipped.
    requestAnimationFrame(() => requestAnimationFrame(tick));
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    // Safety net: if rAF is throttled (e.g. tab not focused on load), make sure
    // titles never stay hidden — reveal everything after a short delay. When the
    // tab is active this still animates (adding the class triggers the transition).
    const safety = setTimeout(() => {
      document.querySelectorAll("[data-reveal]").forEach((el) => el.classList.add("is-in"));
      document.querySelectorAll(".reveal").forEach((el) => el.classList.add("in"));
    }, 1400);
    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      clearTimeout(safety);
      if (raf) cancelAnimationFrame(raf);
    };
  }, []);

  return (
    <>
      <div className="grain"></div>
      <Nav />
      <Hero />
      <About />
      <Comparison />
      <Philosophy />
      <Team />
      <TwoPaths />
      <Footer />
      <PrivacyBanner />
      <TweaksUI />
    </>);

}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<LangProvider><App /></LangProvider>);