/* global React */
const { useState, useRef, useEffect, useContext, createContext, useMemo, useCallback } = React;

/* ===================== EDIT MODE ===================== */
// Click any wrapped <E id="...">text</E> to edit it inline. Changes persist
// in localStorage on this device. Toggle from the floating "Edit" button.
const EDIT_LS_PREFIX = "wcg:edit:";
const EditCtx = createContext({ editing: false, setEditing: () => {} });

function EditModeProvider({ children }) {
  const [editing, setEditing] = useState(false);
  useEffect(() => {
    document.body.dataset.editMode = editing ? "on" : "off";
  }, [editing]);
  const value = useMemo(() => ({ editing, setEditing }), [editing]);
  return <EditCtx.Provider value={value}>{children}</EditCtx.Provider>;
}

function useEditMode() { return useContext(EditCtx); }

// Editable text. Wrap any plain string: <E id="hero.tag">Some text</E>
function E({ id, children, as: As = "span", className = "", style }) {
  const { editing } = useEditMode();
  const initial = typeof children === "string" ? children : (Array.isArray(children) ? children.join("") : String(children ?? ""));
  const [val, setVal] = useState(() => {
    try {
      const v = localStorage.getItem(EDIT_LS_PREFIX + id);
      return v !== null ? v : initial;
    } catch { return initial; }
  });
  // If the source default changes (e.g. tweak panel), pick it up if user hasn't overridden.
  useEffect(() => {
    try {
      const stored = localStorage.getItem(EDIT_LS_PREFIX + id);
      if (stored === null) setVal(initial);
    } catch {}
  }, [initial, id]);

  const onBlur = (e) => {
    const text = e.currentTarget.innerText;
    setVal(text);
    try { localStorage.setItem(EDIT_LS_PREFIX + id, text); } catch {}
  };
  const onKeyDown = (e) => {
    if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); e.currentTarget.blur(); }
    if (e.key === "Escape") { e.currentTarget.blur(); }
  };

  return (
    <As
      className={`wcg-e ${editing ? "is-editing" : ""} ${className}`}
      style={style}
      contentEditable={editing}
      suppressContentEditableWarning
      spellCheck={false}
      onBlur={editing ? onBlur : undefined}
      onKeyDown={editing ? onKeyDown : undefined}
      data-edit-id={id}>
      {val}
    </As>
  );
}

function EditModeToggle() {
  const { editing, setEditing } = useEditMode();
  const reset = (e) => {
    e.stopPropagation();
    if (!confirm("Reset all your text edits on this device?")) return;
    try {
      Object.keys(localStorage).forEach((k) => { if (k.startsWith(EDIT_LS_PREFIX)) localStorage.removeItem(k); });
    } catch {}
    location.reload();
  };
  return (
    <div className="wcg-edit-toggle-wrap">
      {editing && (
        <button className="wcg-edit-toggle wcg-edit-toggle-reset" onClick={reset} title="Reset all edits on this device">Reset</button>
      )}
      <button
        className={`wcg-edit-toggle ${editing ? "is-on" : ""}`}
        onClick={() => setEditing(!editing)}
        title={editing ? "Click to stop editing" : "Click to edit text on this page"}>
        {editing ? "Done editing" : "Edit text"}
      </button>
    </div>
  );
}

Object.assign(window, { EditModeProvider, EditModeToggle, E, useEditMode });


/* ===================== UTILITIES ===================== */

// Blur-in word-by-word reveal, IntersectionObserver-triggered.
// Renders a parent <p> as flex-wrap so words wrap naturally;
// each word is a span animated via CSS transition with staggered delay.
function BlurText({ text, className = "", as: As = "h1", baseDelay = 0, stepMs = 90, style }) {
  const ref = useRef(null);
  const [show, setShow] = useState(false);
  useEffect(() => {
    const el = ref.current;if (!el) return;
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) {setShow(true);io.disconnect();}
    }, { threshold: 0.1 });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  const words = text.split(" ");
  return (
    <As ref={ref} className={`wcg-blurtext ${className}`} style={style}>
      {words.map((w, i) =>
      <span
        key={i}
        className="wcg-blurtext-word"
        style={{
          transitionDelay: `${baseDelay + i * stepMs}ms`,
          transform: show ? "translateY(0)" : "translateY(40px)",
          filter: show ? "blur(0px)" : "blur(10px)",
          opacity: show ? 1 : 0
        }}
        dangerouslySetInnerHTML={{ __html: w === "" ? "&nbsp;" : w }} />

      )}
    </As>);

}

// Simple fade/slide-in on scroll.
function Reveal({ children, delay = 0, y = 24, as: As = "div", className = "", style }) {
  const ref = useRef(null);
  const [show, setShow] = useState(false);
  useEffect(() => {
    const el = ref.current;if (!el) return;
    const io = new IntersectionObserver(([e]) => {
      if (e.isIntersecting) {setShow(true);io.disconnect();}
    }, { threshold: 0.15 });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return (
    <As
      ref={ref}
      className={className}
      style={{
        ...style,
        transition: "opacity 900ms cubic-bezier(0.2,0.7,0.2,1), transform 900ms cubic-bezier(0.2,0.7,0.2,1)",
        transitionDelay: `${delay}ms`,
        transform: show ? "translateY(0)" : `translateY(${y}px)`,
        opacity: show ? 1 : 0
      }}>
      
      {children}
    </As>);

}

/* ===================== EMBEDDED LOGO PLAYER =====================
   Chrome-less playback of the WCG logo intro animation. Plays the
   scene from 0 → SCENE_DURATION once on mount, then holds on the
   final frame. No scrubber, no keyboard hooks, no persistence —
   meant to be dropped inline as a brand mark, not a video player. */
function WCGLogoPlayer({ size, width, height, holdDimAfter = true, onComplete, replayKey = 0 }) {
  // Backwards-compat: old `size` prop = square
  const W = width || size || 280;
  const H = height || size || 280;
  const [time, setTime] = useState(0);
  const rafRef = useRef(null);
  const completedRef = useRef(false);
  const duration = (typeof window !== "undefined" && window.SCENE_DURATION) || 6.0;
  const SceneComp = (typeof window !== "undefined" && window.Scene) || null;
  const Ctx = (typeof window !== "undefined" && window.TimelineContext) || null;

  useEffect(() => {
    let cancelled = false;
    const start = performance.now();
    completedRef.current = false;
    setTime(0);
    const step = (ts) => {
      if (cancelled) return;
      const t = Math.min(duration, (ts - start) / 1000);
      setTime(t);
      if (t < duration) {
        rafRef.current = requestAnimationFrame(step);
      } else if (!completedRef.current) {
        completedRef.current = true;
        if (onComplete) onComplete();
      }
    };
    rafRef.current = requestAnimationFrame(step);
    return () => {
      cancelled = true;
      if (rafRef.current) cancelAnimationFrame(rafRef.current);
    };
  }, [duration, onComplete, replayKey]);

  if (!SceneComp || !Ctx) {
    return (
      <div style={{ width: W, height: H, display: "grid", placeItems: "center" }}>
        <img src="assets/Logos/wcg_logo.png" alt="WCG" style={{ height: H * 0.9, width: "auto", opacity: 0.9 }} />
      </div>
    );
  }

  // The scene is 1920×1080 with the logo centered, occupying a vertical band
  // from y=0.10*LOGO_SIZE to y=0.86*LOGO_SIZE (LOGO_SIZE=760, centered).
  // The visible logo bbox in stage coords:
  //   logoTop = (1080-760)/2 + 0.10*760 = 160 + 76 = 236
  //   logoBot = (1080-760)/2 + 0.86*760 = 160 + 654 = 814
  //   logoH = 578
  //   logoW ≈ 760 (full LOGO_SIZE)
  const LOGO_BBOX_H = 578;
  const LOGO_BBOX_W = 760;
  // Scale so the logo bbox height fills H (or width fills W, whichever
  // constrains first).
  const scale = Math.min(H / LOGO_BBOX_H, W / LOGO_BBOX_W);
  const done = time >= duration - 0.05;
  const dim = holdDimAfter && done ? 0.78 : 1;

  return (
    <div
      className="wcg-logo-player"
      style={{
        width: W,
        height: H,
        position: "relative",
        overflow: "hidden",
        opacity: dim,
        transition: "opacity 600ms ease"
      }}
      aria-hidden="true">
      <div style={{
        position: "absolute",
        width: 1920,
        height: 1080,
        left: "50%",
        top: "50%",
        transform: `translate(-50%, -50%) scale(${scale})`,
        transformOrigin: "center"
      }}>
        <Ctx.Provider value={{ time, duration, playing: !done, setTime: () => {}, setPlaying: () => {} }}>
          <SceneComp />
        </Ctx.Provider>
      </div>
    </div>);
}
Object.assign(window, { WCGLogoPlayer });

/* ===================== ICONS ===================== */
function Icon({ name, size = 18, stroke = 1.5 }) {
  const props = { width: size, height: size, stroke: "currentColor", strokeWidth: stroke, fill: "none", viewBox: "0 0 24 24", strokeLinecap: "round", strokeLinejoin: "round" };
  if (name === "in") return <svg {...props}><path d="M16 8a6 6 0 016 6v7h-4v-7a2 2 0 10-4 0v7h-4v-7a6 6 0 016-6z" /><rect x="2" y="9" width="4" height="12" /><circle cx="4" cy="4" r="2" /></svg>;
  if (name === "ig") return <svg {...props}><rect x="2" y="2" width="20" height="20" rx="5" /><circle cx="12" cy="12" r="4" /><circle cx="17.5" cy="6.5" r="1" fill="currentColor" /></svg>;
  if (name === "tiktok") return <svg {...props}><path d="M14 4v9.5a3.5 3.5 0 11-3.5-3.5" /><path d="M14 4c0 2.5 2 4.5 4.5 4.5" /></svg>;
  if (name === "youtube") return <svg {...props}><rect x="2" y="5" width="20" height="14" rx="3" /><polygon points="10,9 16,12 10,15" fill="currentColor" stroke="none" /></svg>;
  if (name === "mail") return <svg {...props}><rect x="2" y="4" width="20" height="16" rx="2" /><polyline points="2,6 12,13 22,6" /></svg>;
  if (name === "down") return <svg {...props}><polyline points="6,9 12,15 18,9" /></svg>;
  if (name === "right") return <svg {...props}><line x1="5" y1="12" x2="19" y2="12" /><polyline points="13,6 19,12 13,18" /></svg>;
  if (name === "arrow-ne") return <svg {...props}><line x1="7" y1="17" x2="17" y2="7" /><polyline points="9,7 17,7 17,15" /></svg>;
  if (name === "left") return <svg {...props}><line x1="19" y1="12" x2="5" y2="12" /><polyline points="11,18 5,12 11,6" /></svg>;
  if (name === "x") return <svg {...props}><line x1="6" y1="6" x2="18" y2="18" /><line x1="6" y1="18" x2="18" y2="6" /></svg>;
  if (name === "play") return <svg width={size} height={size} viewBox="0 0 24 24" fill="currentColor"><polygon points="6,4 20,12 6,20" /></svg>;
  if (name === "grid") return <svg {...props}><rect x="3" y="3" width="7" height="7" /><rect x="14" y="3" width="7" height="7" /><rect x="3" y="14" width="7" height="7" /><rect x="14" y="14" width="7" height="7" /></svg>;
  if (name === "list") return <svg {...props}><line x1="8" y1="6" x2="21" y2="6" /><line x1="8" y1="12" x2="21" y2="12" /><line x1="8" y1="18" x2="21" y2="18" /><circle cx="4" cy="6" r="0.5" fill="currentColor" /><circle cx="4" cy="12" r="0.5" fill="currentColor" /><circle cx="4" cy="18" r="0.5" fill="currentColor" /></svg>;
  if (name === "camera") return <svg {...props}><path d="M3 7h4l2-3h6l2 3h4v13H3z" /><circle cx="12" cy="13" r="4" /></svg>;
  if (name === "film") return <svg {...props}><rect x="2" y="2" width="20" height="20" rx="2" /><line x1="7" y1="2" x2="7" y2="22" /><line x1="17" y1="2" x2="17" y2="22" /><line x1="2" y1="12" x2="22" y2="12" /><line x1="2" y1="7" x2="7" y2="7" /><line x1="2" y1="17" x2="7" y2="17" /><line x1="17" y1="17" x2="22" y2="17" /><line x1="17" y1="7" x2="22" y2="7" /></svg>;
  if (name === "pen") return <svg {...props}><path d="M12 19l7-7 3 3-7 7-3-3z" /><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18z" /><line x1="2" y1="2" x2="9.586" y2="9.586" /><circle cx="11" cy="11" r="2" /></svg>;
  return null;
}

/* ===================== NAV (liquid-glass) ===================== */
function Nav({ route, setRoute }) {
  const [scrolled, setScrolled] = useState(false);
  const [replay, setReplay] = useState(0);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 60);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  const link = (k, label) =>
  <a onClick={() => setRoute(k)} className={route === k ? "is-active" : ""}>{label}</a>;

  return (
    <nav className={`wcg-nav ${scrolled ? "is-scrolled" : ""}`}>
      <div className="wcg-nav-pill liquid-glass">
        <div
          className="wcg-nav-mark wcg-nav-mark--anim"
          onClick={() => setRoute("home")}
          onMouseEnter={() => setReplay((n) => n + 1)}
          title="Home"
          role="button"
          aria-label="WCG — Home">
          <WCGLogoPlayer width={140} height={32} holdDimAfter={false} replayKey={replay} />
        </div>
        <span className="wcg-nav-divider" />
        <div className="wcg-nav-links">
          {link("home", "Home")}
          {link("work", "Work")}
          {link("about", "About")}
          {link("contact", "Contact")}
        </div>
        <span className="wcg-nav-divider" />
        <button className="wcg-nav-cta" onClick={() => setRoute("contact")}>
          Book the Studio <Icon name="arrow-ne" size={14} stroke={2} />
        </button>
      </div>
    </nav>);

}

/* ===================== HERO (cinematic, video bg) ===================== */
function Hero({
  onSeeWork,
  onGoContact,
  headline = "PREMIUM CREATIVE FOR PREMIUM TALENT",
  subhead = "Photo, video, and brand management built around the athlete. Cincinnati-based. Cinematic by default.",
  eyebrow = "",
  eyebrowDot = true,
  ctaPrimary = "Get in touch",
  ctaSecondary = "Selected Work",
  italicWords = [2, 5],
  accentItalicWord = 5
}) {
  // Re-key BlurText so animation re-runs when headline changes.
  const heroKey = headline + "|" + italicWords.join(",") + "|" + accentItalicWord;

  // Inline style overrides for italic word indices.
  const italicCss = italicWords.map((i) =>
  `.wcg-hero-cine-headline .wcg-blurtext-word:nth-child(${i}){font-family:"Instrument Serif","Times New Roman",serif;font-style:italic;font-weight:400;letter-spacing:-0.02em;color:${i === accentItalicWord ? "var(--wcg-red)" : "#fff"};}`
  ).join("\n");
  // Reset others (cap at first 12 words) so toggling off works.
  const resetCss = Array.from({ length: 12 }, (_, k) => k + 1).
  filter((i) => !italicWords.includes(i)).
  map((i) => `.wcg-hero-cine-headline .wcg-blurtext-word:nth-child(${i}){font-family:var(--font-display);font-style:normal;font-weight:900;letter-spacing:-0.04em;color:#fff;}`).
  join("\n");

  return (
    <section className="wcg-hero-cine" data-screen-label="01 Hero">
      <div className="wcg-hero-hud">
        <div className="group">
          <span><i className="hud-online" /> Studio</span>
          <span className="sep" />
          <span>Cincinnati <span className="val">— OH</span></span>
        </div>
        <div className="group">
          <span>Est. <span className="val">2025</span></span>
        </div>
      </div>
      <div className="wcg-hero-ticks"><i /><b /></div>

      <div className="wcg-hero-cine-inner wcg-hero-cine-inner--text-only">
        <style>{italicCss + "\n" + resetCss}</style>
        {eyebrow && eyebrow.trim() !== "" && (
          <Reveal delay={150}>
            <div className="wcg-hero-eyebrow">{eyebrowDot && <span className="wcg-pulse" />}{eyebrow}</div>
          </Reveal>
        )}

        <BlurText
          key={heroKey}
          as="h1"
          className="wcg-hero-cine-headline"
          baseDelay={350}
          stepMs={110}
          text={headline} />


        <Reveal delay={1200} y={16}>
          <p className="wcg-hero-cine-sub">
            {subhead}
          </p>
        </Reveal>

        <Reveal delay={1450} y={16}>
          <div className="wcg-hero-cine-ctas">
            <button className="wcg-cta-glass liquid-glass-strong" onClick={onGoContact}>
              {ctaPrimary} <Icon name="arrow-ne" size={14} stroke={2} />
            </button>
            <button className="wcg-cta-text" onClick={onSeeWork}>
              {ctaSecondary} <Icon name="arrow-ne" size={16} stroke={2} />
            </button>
          </div>
        </Reveal>
      </div>

      <Reveal delay={1700} y={0}>
        <div className="wcg-hero-cine-scroll">
          <span>SCROLL</span>
          <span className="wcg-scroll-line"><i /></span>
        </div>
      </Reveal>
    </section>);

}

/* ===================== MARQUEE ===================== */
function Marquee({ items = [], onItemClick }) {
  // items can be a string[] or {label, projectId}[]; normalize.
  const normalized = items.map((it) =>
  typeof it === "string" ? { label: it, projectId: null } : it
  );
  const row =
  <>
      {normalized.map((it, i) =>
    <React.Fragment key={i}>
          {it.projectId ?
      <button
        type="button"
        className="wcg-marquee-item is-link"
        onClick={() => onItemClick && onItemClick(it.projectId)}
        title={`View ${it.label} →`}>
        
              {it.label}
            </button> :

      <span className="wcg-marquee-item">{it.label}</span>
      }
          <span className="dot">●</span>
        </React.Fragment>
    )}
    </>;

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

}

/* ===================== CAPABILITIES ===================== */
function Capabilities() {
  const cards = [
  {
    icon: "camera",
    title: "PHOTO",
    tags: ["Editorial", "Brand", "Lifestyle", "Product"],
    body: "Stills built for the moment — campaign, editorial, and brand work shot on location and in studio."
  },
  {
    icon: "film",
    title: "VIDEO",
    tags: ["Direction", "DP", "Edit", "Color"],
    body: "Long and short-form motion. From launch films and social cuts to long-form post for talk and sport."
  },
  {
    icon: "pen",
    title: "DESIGN",
    tags: ["Identity", "Social", "Broadcast", "Packaging"],
    body: "Marks and motion systems that travel — from gameday graphics to apparel imprints."
  }];

  return (
    <section className="wcg-cap" data-screen-label="03 Capabilities">
      <div className="wcg-section-head">
        <Reveal>
          <div>
            <div className="wcg-section-eyebrow"><E id="cap.eyebrow">Capabilities</E></div>
            <h2 className="wcg-section-title"><E id="cap.title.a">Built </E><em><E id="cap.title.b">three</E></em><E id="cap.title.c"> ways</E><span className="dot">.</span></h2>
          </div>
        </Reveal>
      </div>

      <div className="wcg-cap-grid">
        {cards.map((c, i) =>
        <Reveal key={c.title} delay={i * 120}>
            <article className="wcg-cap-card">
              <span className="hud-corner tl" /><span className="hud-corner tr" />
              <span className="hud-corner bl" /><span className="hud-corner br" />
              <div className="wcg-cap-card-top">
                <div className="wcg-cap-icon"><Icon name={c.icon} size={22} stroke={1.5} /></div>
                <div className="wcg-cap-tags">
                  {c.tags.map((t, ti) => <span key={t} className="wcg-cap-tag"><E id={`cap.${i}.tag.${ti}`}>{t}</E></span>)}
                </div>
              </div>
              <div className="wcg-cap-card-bottom">
                <h3 className="wcg-cap-title"><E id={`cap.${i}.title`}>{c.title}</E></h3>
                <p className="wcg-cap-body"><E id={`cap.${i}.body`}>{c.body}</E></p>
                <div className="wcg-cap-meta">
                  <span>0{i + 1} / 03</span>
                  <span><Icon name="arrow-ne" size={16} stroke={2} /></span>
                </div>
              </div>
            </article>
          </Reveal>
        )}
      </div>
    </section>);

}

/* ===================== PROJECTS — switcher ===================== */
function ProjectsSection({ projects, onOpen }) {
  const [view, setView] = useState("grid");
  return (
    <section data-screen-label="02 Selected Work">
      <div className="wcg-section-head">
        <Reveal>
          <div>
            <div className="wcg-section-eyebrow"><E id="work.eyebrow">Selected Work · 2024–25</E></div>
            <h2 className="wcg-section-title"><E id="work.title.a">The </E><em><E id="work.title.b">Roster</E></em><span className="dot">.</span></h2>
          </div>
        </Reveal>
        <Reveal>
          <div className="wcg-view-switch" role="tablist">
            <button className={view === "grid" ? "is-active" : ""} onClick={() => setView("grid")}>
              <Icon name="grid" size={14} stroke={2} /> Grid
            </button>
            <button className={view === "list" ? "is-active" : ""} onClick={() => setView("list")}>
              <Icon name="list" size={14} stroke={2} /> Index
            </button>
          </div>
        </Reveal>
      </div>
      {view === "grid" ?
      <ProjectGrid projects={projects} onOpen={onOpen} /> :
      <ProjectList projects={projects} onOpen={onOpen} />}
    </section>);

}

function ProjectGrid({ projects, onOpen }) {
  return (
    <div className="wcg-work-grid">
      {projects.map((p, i) =>
      <Reveal key={p.id} delay={i * 60}>
        <div className="wcg-work-tile" onClick={() => onOpen(p)}>
          <ProjectTilePlaceholder project={p} />
          <div className="wcg-work-tile-meta">
            <span className="t"><E id={`project.${p.id}.client.tile`}>{p.client}</E></span>
            <span>{p.year}</span>
          </div>
        </div>
      </Reveal>
      )}
    </div>
  );
}

function ProjectScroller({ projects, onOpen }) {
  const ref = useRef(null);
  const [pct, setPct] = useState(0);
  const [atStart, setAtStart] = useState(true);
  const [atEnd, setAtEnd] = useState(false);

  useEffect(() => {
    const el = ref.current;if (!el) return;
    const onScroll = () => {
      const max = el.scrollWidth - el.clientWidth;
      const p = max > 0 ? el.scrollLeft / max * 100 : 0;
      setPct(p);
      setAtStart(el.scrollLeft <= 4);
      setAtEnd(el.scrollLeft >= max - 4);
    };
    onScroll();
    el.addEventListener("scroll", onScroll, { passive: true });
    return () => el.removeEventListener("scroll", onScroll);
  }, []);

  // Scroll-through parallax: update each card's --scroll-pct based on
  // its center vs the scroller's center. Range roughly -1..1.
  const cardRefs = useRef([]);
  useEffect(() => {
    const el = ref.current;if (!el) return;
    let raf = 0;
    const update = () => {
      raf = 0;
      const rect = el.getBoundingClientRect();
      const center = rect.left + rect.width / 2;
      cardRefs.current.forEach((c) => {
        if (!c) return;
        const cr = c.getBoundingClientRect();
        const cc = cr.left + cr.width / 2;
        const pct = Math.max(-1.4, Math.min(1.4, (cc - center) / (rect.width / 2)));
        c.style.setProperty("--scroll-pct", pct.toFixed(3));
      });
    };
    const onScroll = () => {if (!raf) raf = requestAnimationFrame(update);};
    update();
    el.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    return () => {
      el.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      if (raf) cancelAnimationFrame(raf);
    };
  }, [projects.length]);

  const nudge = (dir) => {
    const el = ref.current;if (!el) return;
    el.scrollBy({ left: dir * 500, behavior: "smooth" });
  };

  const shapes = ["is-tall", "is-wide", "", "is-square"];

  return (
    <div className="wcg-scroller-wrap">
      <div className="wcg-scroller" ref={ref}>
        {projects.map((p, i) =>
        <button
          key={p.id}
          ref={(el) => {cardRefs.current[i] = el;}}
          className={`wcg-scard ${shapes[i % shapes.length]}`}
          onClick={() => onOpen(p)}
          style={{ "--scroll-pct": 0 }}>
          
            <div className="wcg-scard-frame">
              <ProjectTilePlaceholder project={p} />
              <div className="wcg-scard-cta"><Icon name="arrow-ne" size={20} stroke={2} /></div>
            </div>
            <div>
              <h3 className="wcg-scard-title" style={{ marginTop: 10 }}><E id={`project.${p.id}.client`}>{p.client}</E></h3>
            </div>
          </button>
        )}
      </div>
      <div className="wcg-scroll-controls">
        <div className="progress"><i style={{ width: `${Math.max(8, pct)}%` }} /></div>
        <button className="wcg-scroll-btn liquid-glass" onClick={() => nudge(-1)} disabled={atStart}><Icon name="left" stroke={2} /></button>
        <button className="wcg-scroll-btn liquid-glass" onClick={() => nudge(1)} disabled={atEnd}><Icon name="right" stroke={2} /></button>
      </div>
    </div>);

}

function ProjectList({ projects, onOpen }) {
  return (
    <div className="wcg-list">
      {projects.map((p, i) =>
      <div key={p.id} className="wcg-list-row" onClick={() => onOpen(p)}>
          <div className="wcg-list-num">{String(i + 1).padStart(2, "0")}</div>
          <div className="wcg-list-title">
            {p.title.split(" ").map((w, j, arr) => j === arr.length - 1 ?
          <em key={j}>{w}</em> :
          <React.Fragment key={j}>{w} </React.Fragment>)}
          </div>
          <div className="wcg-list-client">{p.client} · {p.discipline}</div>
          <div className="wcg-list-year">{p.year}</div>
          <div className="wcg-list-arrow"><Icon name="arrow-ne" size={22} stroke={1.5} /></div>
          <div className="peek"><ProjectTilePlaceholder project={p} /></div>
        </div>
      )}
    </div>);

}

/* ===================== VERTICAL VIDEO CAROUSEL ===================== */
function VerticalVideoCarousel({ videos }) {
  const ref = useRef(null);
  const [active, setActive] = useState(null); // YouTube id currently playing
  const [pct, setPct] = useState(0);
  const [atStart, setAtStart] = useState(true);
  const [atEnd, setAtEnd] = useState(false);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const onScroll = () => {
      const max = el.scrollWidth - el.clientWidth;
      const p = max > 0 ? (el.scrollLeft / max) * 100 : 0;
      setPct(p);
      setAtStart(el.scrollLeft <= 4);
      setAtEnd(el.scrollLeft >= max - 4);
    };
    onScroll();
    el.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    return () => {
      el.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
    };
  }, [videos.length]);

  const nudge = (dir) => {
    const el = ref.current;
    if (!el) return;
    el.scrollBy({ left: dir * 480, behavior: "smooth" });
  };

  const isLocal = (s) => typeof s === "string" && (s.endsWith(".mp4") || s.endsWith(".webm") || s.endsWith(".mov") || s.includes("/"));

  return (
    <div className="wcg-vvc-wrap">
      <div className="wcg-vvc" ref={ref}>
        {videos.map((id, i) => {
          // Local MP4 — render native HTML5 video, no iframe, no chrome
          if (isLocal(id)) {
            return (
              <div key={id} className="wcg-vvc-tile is-active is-local">
                <video
                  className="wcg-vvc-iframe"
                  src={id}
                  controls
                  preload="metadata"
                  playsInline
                  controlsList="nodownload"
                />
                <span className="wcg-vvc-num is-static">{String(i + 1).padStart(2, "0")}</span>
              </div>
            );
          }

          // YouTube — existing click-to-play poster pattern
          const isActive = active === id;
          return (
            <div key={id} className={`wcg-vvc-tile ${isActive ? "is-active" : ""}`}>
              {isActive ?
              <>
                  <iframe
                  className="wcg-vvc-iframe"
                  src={`https://www.youtube-nocookie.com/embed/${id}?autoplay=1&modestbranding=1&rel=0&playsinline=1&iv_load_policy=3&controls=1&disablekb=1&fs=0&color=white`}
                  title=""
                  frameBorder="0"
                  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
                  allowFullScreen={false} />

                  <button
                  className="wcg-vvc-close"
                  onClick={(e) => {e.stopPropagation();setActive(null);}}
                  aria-label="Close video">
                    <Icon name="x" size={18} stroke={2} />
                  </button>
                </> :

              <button
                className="wcg-vvc-poster"
                onClick={() => setActive(id)}
                aria-label={`Play video ${i + 1}`}>

                  <img
                  src={`https://i.ytimg.com/vi/${id}/maxresdefault.jpg`}
                  onError={(e) => {e.currentTarget.src = `https://i.ytimg.com/vi/${id}/hqdefault.jpg`;}}
                  alt=""
                  className="wcg-vvc-thumb" />

                  <span className="wcg-vvc-grain" aria-hidden="true" />
                  <span className="wcg-vvc-num">{String(i + 1).padStart(2, "0")}</span>
                  <span className="wcg-vvc-play" aria-hidden="true">
                    <Icon name="play" size={22} />
                  </span>
                </button>
              }
            </div>);

        })}
      </div>
      <div className="wcg-vvc-controls">
        <div className="progress"><i style={{ width: `${Math.max(8, pct)}%` }} /></div>
        <button className="wcg-scroll-btn liquid-glass" onClick={() => nudge(-1)} disabled={atStart}><Icon name="left" stroke={2} /></button>
        <button className="wcg-scroll-btn liquid-glass" onClick={() => nudge(1)} disabled={atEnd}><Icon name="right" stroke={2} /></button>
      </div>
    </div>);

}
Object.assign(window, { VerticalVideoCarousel });

/* ===================== PROJECT PAGE ===================== */
function ProjectPage({ project, onClose, onNext }) {
  return (
    <div className="wcg-project">
      <button className="wcg-project-close" onClick={onClose} aria-label="Back to all work">
        <Icon name="left" size={16} stroke={2} />
        <span>Back</span>
      </button>
      <div className={`wcg-project-hero ${project.heroVideo || project.hero || project.cover ? "" : "wcg-project-hero-ph"}`}
        style={(project.heroBg || project.coverBg) ? { background: project.heroBg || project.coverBg } : undefined}>
        {project.heroVideo && project.heroVideo.kind === "vimeo" ?
        <ProjectBanner banner={project.heroVideo} fullBleed /> :
        project.hero || project.cover ?
        <img className="wcg-project-hero-img" src={project.hero || project.cover} alt={project.client || project.title} style={(() => {
          const fit = project.heroFit || project.coverFit;
          const pos = project.heroPosition;
          if (!fit && !pos) return undefined;
          const s = {};
          if (fit) s.objectFit = fit;
          if (pos) s.objectPosition = pos;
          return s;
        })()} /> :

        <div className="wcg-tile-ph wcg-tile-ph-full">
            <div className="wcg-tile-ph-grid" />
            <div className="wcg-tile-ph-meta"><span>HERO · {project.id.toUpperCase()}</span></div>
          </div>
        }
        <div className="wcg-project-meta">
          <div className="wcg-project-eyebrow"><E id={`project.${project.id}.eyebrow.client`}>{project.client}</E> · <E id={`project.${project.id}.eyebrow.year`}>{project.year}</E></div>
          <h2 className="wcg-project-title"><E id={`project.${project.id}.title`}>{project.title}</E></h2>
        </div>
      </div>
      <div className="wcg-project-credits">
        <div><div className="label">Discipline</div><div className="value"><E id={`project.${project.id}.discipline`}>{project.discipline}</E></div></div>
        <div className="summary"><div className="label">About</div><div className="value"><E id={`project.${project.id}.summary`}>{project.summary}</E></div></div>
      </div>
      <div className="wcg-project-credits" style={{ borderBottom: "none", paddingTop: 0 }}>
        <div><div className="label">Role</div><div className="value"><E id={`project.${project.id}.role`}>{project.role}</E></div></div>
        <div><div className="label">Year</div><div className="value"><E id={`project.${project.id}.year`}>{project.year}</E></div></div>
        <div><div className="label">Client</div><div className="value"><E id={`project.${project.id}.client.full`}>{project.client}</E></div></div>
        <div><div className="label">Status</div><div className="value"><E id={`project.${project.id}.status`}>Delivered</E></div></div>
      </div>
      {project.metrics && project.metrics.length > 0 &&
        <div className="wcg-project-metrics">
          {project.metrics.map((m, i) =>
            <Reveal key={i} delay={i * 80} className="wcg-project-metric">
              <div className="value">{m.value}</div>
              <div className="label">{m.label}</div>
            </Reveal>
          )}
        </div>
      }
      {(project.videos && project.videos.length > 0) || (project.instagramReels && project.instagramReels.length > 0) ?
      <>
          {project.links && project.links.items && project.links.items.length > 0 &&
        <div className="wcg-project-links">
              <div className="wcg-project-links-label">{project.links.label || "See more"}</div>
              <div className="wcg-project-links-row">
                {project.links.items.map((l, i) =>
            <a
              key={i}
              href={l.href}
              target="_blank"
              rel="noopener noreferrer"
              className="wcg-project-link"
              aria-label={l.label}
              title={l.label}>

                    <Icon name={l.kind} size={20} stroke={1.5} />
                    <span>{l.label}</span>
                  </a>
            )}
              </div>
            </div>
        }
          {project.instagramReels && project.instagramReels.length > 0 ?
            <InstagramReels ids={project.instagramReels} /> :
            <VerticalVideoCarousel videos={project.videos} />
          }
        </> :
      project.gallery && project.gallery.length > 0 ?
      <>
          {project.videoBefore && <ProjectInlineVideo video={project.videoBefore} />}
          {project.linkedinPosts && project.linkedinPosts.length > 0 &&
            <LinkedInPosts ids={project.linkedinPosts} label={project.linkedinLabel || "Spots"} />}
          <PhotoGallery images={project.gallery} projectId={project.id} style={project.galleryStyle} />
          {project.gallerySections && project.gallerySections.map((s, si) =>
            <div key={si} className="wcg-gallery-section">
              <div className="wcg-gallery-section-head">
                <div className="wcg-section-eyebrow">{s.label}</div>
              </div>
              <PhotoGallery images={s.images} projectId={`${project.id}.s${si}`} style={s.style || project.galleryStyle} />
            </div>
          )}
        </> :

      <div className="wcg-project-stills">
          {project.stills.map((_, i) =>
        <div key={i} className="wcg-tile-ph">
              <div className="wcg-tile-ph-grid" />
              <div className="wcg-tile-ph-meta"><span>STILL {String(i + 1).padStart(2, "0")}</span><span>{project.id.toUpperCase()}</span></div>
            </div>
        )}
        </div>
      }
      <button className="wcg-project-next" onClick={onNext}>Next Project <Icon name="right" stroke={2} /></button>
    </div>);

}

/* ===================== LINKEDIN POSTS GRID ===================== */
function LinkedInPosts({ ids, label = "Spots" }) {
  return (
    <div className="wcg-li-posts-section">
      <div className="wcg-li-posts-head">
        <div className="wcg-section-eyebrow">{label}</div>
      </div>
      <div className="wcg-li-posts">
        {ids.map((id, i) =>
          <Reveal key={id} delay={(i % 3) * 80} className="wcg-li-post-card">
            <iframe
              src={`https://www.linkedin.com/embed/feed/update/urn:li:ugcPost:${id}?compact=1`}
              frameBorder="0"
              allowFullScreen
              title=""
              loading="lazy" />
          </Reveal>
        )}
      </div>
    </div>
  );
}
Object.assign(window, { LinkedInPosts });

/* ===================== INSTAGRAM REELS GRID ===================== */
function InstagramReels({ ids }) {
  useEffect(() => {
    const ensureScript = () => new Promise((resolve) => {
      if (document.querySelector('script[src*="instagram.com/embed.js"]')) {
        resolve();
        return;
      }
      const s = document.createElement("script");
      s.src = "https://www.instagram.com/embed.js";
      s.async = true;
      s.onload = () => resolve();
      document.body.appendChild(s);
    });
    let cancelled = false;
    ensureScript().then(() => {
      if (cancelled) return;
      // Tiny tick so React has finished mounting the blockquotes
      setTimeout(() => {
        if (window.instgrm && window.instgrm.Embeds && typeof window.instgrm.Embeds.process === "function") {
          window.instgrm.Embeds.process();
        }
      }, 50);
    });
    return () => { cancelled = true; };
  }, [ids.join(",")]);

  return (
    <div className="wcg-ig-reels-section">
      <div className="wcg-ig-reels-head">
        <div className="wcg-section-eyebrow">Reels</div>
      </div>
      <div className="wcg-ig-reels">
        {ids.map((id, i) =>
          <Reveal key={id} delay={(i % 3) * 80} className="wcg-ig-reel-card">
            <blockquote
              className="instagram-media"
              data-instgrm-permalink={`https://www.instagram.com/reel/${id}/?utm_source=ig_embed&utm_campaign=loading`}
              data-instgrm-version="14">
              <div style={{ padding: "16px" }}>
                <a href={`https://www.instagram.com/reel/${id}/`} target="_blank" rel="noopener noreferrer">View Reel</a>
              </div>
            </blockquote>
          </Reveal>
        )}
      </div>
    </div>
  );
}
Object.assign(window, { InstagramReels });

/* ===================== PROJECT INLINE VIDEO (click-to-play) ===================== */
function ProjectInlineVideo({ video }) {
  if (!video || !video.id) return null;
  const aspect = video.aspect || "16/9";
  let src = "";
  let isYouTube = false;
  if (video.kind === "youtube") {
    src = `https://www.youtube-nocookie.com/embed/${video.id}?rel=0&modestbranding=1&iv_load_policy=3&playsinline=1&disablekb=1&color=white`;
    isYouTube = true;
  } else if (video.kind === "vimeo") {
    src = `https://player.vimeo.com/video/${video.id}?title=0&byline=0&portrait=0`;
  } else {
    return null;
  }
  return (
    <div className="wcg-project-inline-video">
      <div className="wcg-project-inline-video-frame" style={{ aspectRatio: aspect }}>
        <iframe
          src={src}
          title={video.title || ""}
          frameBorder="0"
          allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
          referrerPolicy="strict-origin-when-cross-origin"
          allowFullScreen
          loading="lazy"
          className="wcg-project-inline-video-iframe" />
      </div>
    </div>);
}

/* ===================== PROJECT BANNER (looping vimeo) ===================== */
function ProjectBanner({ banner, fullBleed = false }) {
  if (!banner || banner.kind !== "vimeo" || !banner.id) return null;
  // background=1 → fully chromeless, autoplay, muted, looped (no controls, no title)
  const src = `https://player.vimeo.com/video/${banner.id}?background=1&autoplay=1&loop=1&muted=1&autopause=0&playsinline=1&dnt=1&app_id=58479`;
  if (fullBleed) {
    return (
      <div className="wcg-project-hero-video">
        <iframe
          src={src}
          title=""
          frameBorder="0"
          allow="autoplay; fullscreen; picture-in-picture"
          loading="lazy"
          className="wcg-project-hero-video-iframe" />
      </div>);
  }
  const aspect = banner.aspect || "16/9";
  return (
    <div className="wcg-project-banner" style={{ aspectRatio: aspect }}>
      <iframe
        src={src}
        title=""
        frameBorder="0"
        allow="autoplay; fullscreen; picture-in-picture"
        loading="lazy"
        className="wcg-project-banner-iframe" />
    </div>);

}

/* ===================== PHOTO GALLERY (lightbox) ===================== */
function PhotoGallery({ images, projectId, style }) {
  const [active, setActive] = useState(null);
  useEffect(() => {
    if (active === null) return;
    const onKey = (e) => {
      if (e.key === "Escape") setActive(null);
      if (e.key === "ArrowRight") setActive((i) => Math.min(images.length - 1, (i ?? 0) + 1));
      if (e.key === "ArrowLeft") setActive((i) => Math.max(0, (i ?? 0) - 1));
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [active, images.length]);

  // Aspect-rhythm pattern — repeats so any number of images flows naturally
  const shapes = ["is-tall", "is-wide", "is-square", "is-tall", "is-wide", "is-square", "is-portrait"];
  const isMasonry = style === "masonry";

  return (
    <>
      <div className={isMasonry ? "wcg-gallery-masonry" : "wcg-gallery"}>
        {images.map((src, i) =>
        isMasonry ?
        <button
          key={i}
          className="wcg-gallery-mtile"
          onClick={() => setActive(i)}
          aria-label={`Open image ${i + 1}`}>
            <img src={src} alt="" loading={i < 4 ? "eager" : "lazy"} />
            <span className="wcg-gallery-num">{String(i + 1).padStart(2, "0")}</span>
          </button> :
        <button
          key={i}
          className={`wcg-gallery-tile ${shapes[i % shapes.length]}`}
          onClick={() => setActive(i)}
          aria-label={`Open image ${i + 1}`}>

            <img src={src} alt="" loading={i < 4 ? "eager" : "lazy"} />
            <span className="wcg-gallery-num">{String(i + 1).padStart(2, "0")}</span>
          </button>
        )}
      </div>
      {active !== null &&
      <div className="wcg-lightbox" onClick={() => setActive(null)} role="dialog" aria-modal="true">
          <button
          className="wcg-lightbox-close"
          onClick={(e) => {e.stopPropagation();setActive(null);}}
          aria-label="Close">
            <Icon name="x" size={22} stroke={2} />
          </button>
          <button
          className="wcg-lightbox-nav wcg-lightbox-prev"
          onClick={(e) => {e.stopPropagation();setActive((i) => Math.max(0, i - 1));}}
          disabled={active === 0}
          aria-label="Previous">
            <Icon name="left" size={26} stroke={2} />
          </button>
          <img
          src={images[active]}
          alt=""
          className="wcg-lightbox-img"
          onClick={(e) => e.stopPropagation()} />
          <button
          className="wcg-lightbox-nav wcg-lightbox-next"
          onClick={(e) => {e.stopPropagation();setActive((i) => Math.min(images.length - 1, i + 1));}}
          disabled={active === images.length - 1}
          aria-label="Next">
            <Icon name="right" size={26} stroke={2} />
          </button>
          <div className="wcg-lightbox-counter">
            {String(active + 1).padStart(2, "0")} / {String(images.length).padStart(2, "0")}
          </div>
        </div>
      }
    </>);

}

/* ===================== ABOUT / CONTACT / FOOTER ===================== */
function AboutBlock({ onGoContact }) {
  return (
    <section className="wcg-about">
      <Reveal>
        <div className="wcg-about-img">
          <img src="assets/about/about-01.jpg" alt="Jackson Weller behind the scenes" />
          <div className="wcg-about-img-thumbs">
            <img src="assets/about/about-02.jpg" alt="" />
            <img src="assets/about/about-03.jpg" alt="" />
          </div>
        </div>
      </Reveal>
      <div>
        <Reveal>
          <div className="wcg-section-eyebrow"><E id="about.eyebrow">About</E></div>
        </Reveal>
        <BlurText
          as="h2"
          className="wcg-section-title wcg-about-title"
          text="Built around the client."
          baseDelay={150} />

        <Reveal delay={500}>
          <p style={{ font: "400 20px/1.55 var(--font-sans)", color: "var(--fg-2)", maxWidth: 540, margin: 0 }}>
            <E id="about.body">Weller Creative Group is a small, premium production team led by Jackson Weller. We work with athletes, agencies, and consumer brands on photo, video, and design — from the field to the final cut.</E>
          </p>
        </Reveal>

        {onGoContact && (
          <Reveal delay={650}>
            <div style={{ marginTop: 32 }}>
              <button className="wcg-btn-primary" onClick={onGoContact}>
                <E id="about.cta">Get in touch</E> <Icon name="right" size={14} stroke={2} />
              </button>
            </div>
          </Reveal>
        )}
      </div>
    </section>);

}

function ContactBlock() {
  const [status, setStatus] = useState("idle"); // idle | sending | sent | error
  const [errorMsg, setErrorMsg] = useState("");

  const onSubmit = async (e) => {
    e.preventDefault();
    setStatus("sending");
    setErrorMsg("");
    const form = e.currentTarget;
    const data = new FormData(form);
    const payload = {
      name: data.get("name"),
      email: data.get("email"),
      message: data.get("message"),
      _subject: "New inquiry — Weller Creative Group",
      _captcha: "false",
      _template: "table"
    };
    try {
      const res = await fetch("https://formsubmit.co/ajax/wellercreativegroup@gmail.com", {
        method: "POST",
        headers: { "Content-Type": "application/json", "Accept": "application/json" },
        body: JSON.stringify(payload)
      });
      if (!res.ok) throw new Error("Submission failed");
      const json = await res.json().catch(() => ({}));
      if (json && json.success === "false") throw new Error(json.message || "Submission failed");
      setStatus("sent");
    } catch (err) {
      setStatus("error");
      setErrorMsg(err && err.message ? err.message : "Something went wrong. Please email wellercreativegroup@gmail.com directly.");
    }
  };

  return (
    <section className="wcg-contact">
      <div className="wcg-section-eyebrow"><E id="contact.eyebrow">Contact</E></div>
      <BlurText
        as="h2"
        className="wcg-section-title wcg-contact-title"
        text="Let's make something." />

      {status === "sent" ?
      <p style={{ font: "400 20px/1.55 var(--font-sans)", color: "var(--fg-2)", marginTop: 48 }}><E id="contact.thanks">Got it — we'll be in touch.</E></p> :

      <form className="wcg-form" onSubmit={onSubmit}>
          <div className="wcg-field"><label><E id="contact.label.name">Name</E></label><input name="name" placeholder="Your name" required /></div>
          <div className="wcg-field"><label><E id="contact.label.email">Email</E></label><input name="email" type="email" placeholder="you@studio.com" required /></div>
          <div className="wcg-field" style={{ gridColumn: "1 / -1" }}><label><E id="contact.label.project">Project</E></label><textarea name="message" placeholder="A line or two about it…" required /></div>
          <div style={{ gridColumn: "1 / -1", marginTop: 16, display: "flex", gap: 16, alignItems: "center", flexWrap: "wrap" }}>
            <button className="wcg-btn-primary" type="submit" disabled={status === "sending"}>
              <E id="contact.cta">{status === "sending" ? "Sending…" : "Get in touch"}</E> <Icon name="right" size={14} stroke={2} />
            </button>
            {status === "error" && (
              <span style={{ font: "400 14px/1.4 var(--font-sans)", color: "var(--wcg-red, #C8102E)" }}>{errorMsg}</span>
            )}
          </div>
        </form>
      }
    </section>);

}

function Footer() {
  return (
    <footer className="wcg-footer">
      <div className="wcg-footer-meta"><E id="footer.meta">© 2025 Weller Creative Group · Cincinnati, OH</E></div>
      <div className="wcg-footer-mark"><img src="assets/Logos/wcg_logo.png" alt="WCG" /></div>
      <div className="wcg-footer-social">
        <a href="https://www.linkedin.com/in/jackson-weller/" target="_blank" rel="noopener noreferrer" aria-label="LinkedIn"><Icon name="in" /></a>
        <a href="https://www.instagram.com/jacksonweller12/" target="_blank" rel="noopener noreferrer" aria-label="Instagram"><Icon name="ig" /></a>
        <a href="mailto:wellercreativegroup@gmail.com" aria-label="Email"><Icon name="mail" /></a>
      </div>
    </footer>);

}

/* ===================== LOGO INTRO OVERLAY =====================
   Full-bleed black overlay that plays the WCG logo reveal once per
   session, then fades away to expose the page. Sits above the nav
   on first paint; on subsequent navigations within the session it
   doesn't re-mount. The page underneath is fully laid out — the
   overlay is purely decorative. */
function LogoIntro() {
  const PLAYED_KEY = "wcg:intro:played:v2";
  const [phase, setPhase] = useState("playing"); // playing | fading | done
  // Skip on subsequent loads in the same session.
  useEffect(() => {
    try {
      if (sessionStorage.getItem(PLAYED_KEY) === "1") {
        setPhase("done");
      }
    } catch {}
  }, []);
  // Allow click-to-skip
  const skip = () => {
    if (phase === "done") return;
    try { sessionStorage.setItem(PLAYED_KEY, "1"); } catch {}
    setPhase("fading");
    window.setTimeout(() => setPhase("done"), 500);
  };
  // Auto-fade after the scene completes (with a half-second hold).
  const onComplete = React.useCallback(() => {
    try { sessionStorage.setItem(PLAYED_KEY, "1"); } catch {}
    window.setTimeout(() => setPhase("fading"), 700);
    window.setTimeout(() => setPhase("done"), 1200);
  }, []);

  if (phase === "done") return null;

  return (
    <div
      className="wcg-logo-intro"
      data-phase={phase}
      onClick={skip}
      style={{
        position: "fixed",
        inset: 0,
        zIndex: 9999,
        background: "#0a0a0c",
        display: "grid",
        placeItems: "center",
        cursor: "pointer",
        opacity: phase === "fading" ? 0 : 1,
        transition: "opacity 500ms ease",
        pointerEvents: phase === "fading" ? "none" : "auto"
      }}>

      <WCGLogoPlayer size={Math.min(720, window.innerHeight * 0.7)} holdDimAfter={false} onComplete={onComplete} />
      <button
        onClick={(e) => { e.stopPropagation(); skip(); }}
        className="wcg-logo-intro-skip"
        style={{
          position: "absolute",
          right: 24, bottom: 22,
          background: "transparent",
          border: "1px solid rgba(255,255,255,0.18)",
          color: "rgba(255,255,255,0.6)",
          padding: "8px 14px",
          font: "500 11px/1 var(--font-mono, monospace)",
          letterSpacing: "0.18em",
          textTransform: "uppercase",
          borderRadius: 999,
          cursor: "pointer"
        }}>
        Skip
      </button>
    </div>);

}
Object.assign(window, { LogoIntro });

/* ===================== HOME ===================== */
function Home({ onGoWork, onGoAbout, onGoContact, onOpenProject, projects }) {
  const recent = projects.slice(0, 4);
  return (
    <div className="wcg-home" data-screen-label="00 Home">
      <section className="wcg-home-boot">
        <div className="hud-grid-bg" />
        <div className="wcg-home-topbar">
          <div className="group">
            <span><i className="hud-online" /> Weller Creative Group</span>
            <span className="sep" />
            <span>Cincinnati, OH</span>
          </div>
          <div className="group">
            <span>Est. <span className="val">2025</span></span>
            <span className="sep" />
            <span>Now booking</span>
          </div>
        </div>

        <div className="wcg-home-stage wcg-home-stage--solo">
          <div className="wcg-home-stage-inner">
            <Reveal delay={120}>
              <div className="wcg-home-eyebrow">Weller Creative Group</div>
            </Reveal>
            <BlurText
              as="h1"
              className="wcg-home-headline"
              text="Content that preforms."
              baseDelay={300}
              stepMs={100} />
            
            <Reveal delay={1100} y={16}>
              <p className="wcg-home-sub">
                Photo, video, and brand work for athletes, agencies, and consumer brands. Cincinnati-based. Cinematic by default.
              </p>
            </Reveal>
            <Reveal delay={1300} y={16}>
              <div className="wcg-home-cta-row">
                <button className="wcg-cta-glass liquid-glass-strong" onClick={onGoWork}>
                  Selected Work <Icon name="right" size={14} stroke={2} />
                </button>
                <button className="wcg-cta-text" onClick={onGoContact}>
                  Get in touch <Icon name="arrow-ne" size={16} stroke={2} />
                </button>
              </div>
            </Reveal>
          </div>
        </div>
      </section>

      <section className="wcg-home-portals">
        {[
        { num: "01", title: "Selected Work", desc: "Photo, video, and design across athletes, agencies, and brands.", action: onGoWork, foot: "View work" },
        { num: "02", title: "About", desc: "A small studio led by Jackson Weller, built around the client.", action: onGoAbout, foot: "Read more" },
        { num: "03", title: "Get in touch", desc: "Tell us about the project. Booking is open for Q3 / Q4.", action: onGoContact, foot: "Say hello" }].
        map((p, i) =>
        <Reveal key={p.num} delay={i * 120}>
            <button className="wcg-home-portal" onClick={p.action}>
              <div>
                <div className="wcg-home-portal-num">{p.num} / 03</div>
                <h3 className="wcg-home-portal-title">{p.title}</h3>
                <p className="wcg-home-portal-desc">{p.desc}</p>
              </div>
              <div className="wcg-home-portal-foot">
                <span>{p.foot}</span>
                <Icon name="arrow-ne" size={18} stroke={2} />
              </div>
            </button>
          </Reveal>
        )}
      </section>

      <section className="wcg-home-recent">
        <div className="wcg-home-recent-head">
          <Reveal>
            <div>
              <div className="wcg-section-eyebrow">Recent</div>
              <h2 className="wcg-section-title" style={{ margin: "var(--stack-2) 0 0" }}>Selected <em>work</em><span className="dot">.</span></h2>
            </div>
          </Reveal>
          <Reveal>
            <button className="wcg-cta-text" onClick={onGoWork} style={{ paddingRight: 0 }}>
              View all <Icon name="arrow-ne" size={16} stroke={2} />
            </button>
          </Reveal>
        </div>
        <div className="wcg-home-recent-grid">
          {recent.map((p, i) =>
          <Reveal key={p.id} delay={i * 100}>
              <div className="wcg-home-recent-tile" onClick={() => onOpenProject(p)}>
                <ProjectTilePlaceholder project={p} />
                <div className="wcg-home-recent-tile-meta">
                  <span className="t">{p.client}</span>
                  <span>{p.year}</span>
                </div>
              </div>
            </Reveal>
          )}
        </div>
      </section>

      <section className="wcg-home-strip">
        <h3 className="wcg-home-strip-title">Get in <em>touch</em></h3>
        <button className="wcg-btn-primary" onClick={onGoContact}>Get in touch <Icon name="right" size={14} stroke={2} /></button>
      </section>
    </div>);

}
Object.assign(window, { Home });

function ProjectTilePlaceholder({ project }) {
  if (project && project.cover) {
    const fit = project.coverFit || "cover";
    const bg = project.coverBg || "#000";
    return (
      <div className="wcg-tile-ph wcg-tile-ph--cover" style={{ background: bg }}>
        <img src={project.cover} alt={project.client || project.title || ""} className="wcg-tile-ph-img" style={{ objectFit: fit }} />
      </div>);
  }
  return (
    <div className="wcg-tile-ph">
      <div className="wcg-tile-ph-grid" />
    </div>);

}
Object.assign(window, { ProjectTilePlaceholder });