/* IC website — single-page React prototype */
const { useState, useEffect, useRef, useCallback } = React;

/* ====== Logo (official IC mark — uploaded by user) ====== */
const Logo = ({ size = 28, className = "" }) =>
<img src="assets/ic-symbol.png?v=2" alt="IC" className={className}
style={{ height: size, width: "auto", display: "block" }} />;


const LogoLarge = ({ className = "" }) =>
<img src="assets/ic-symbol.png?v=2" alt="" className={className} aria-hidden="true" />;


/* Symbol + "Infinite Challenge" wordmark composed inline so the text matches
   the site's typography exactly (no baked-in font in the image). */
const Banner = ({ size = 26, className = "" }) =>
<span className={"brand " + className} style={{ display: "inline-flex", alignItems: "center", gap: 12 }}>
    <img src="assets/ic-symbol.png?v=2" alt="" aria-hidden="true"
  style={{ height: size, width: "auto", display: "block" }} />
    <span className="brand__word" style={{ fontSize: Math.round(size * 0.58) }}>Infinite Challenge</span>
  </span>;


/* ====== Reveal-on-scroll hook ====== */
function useReveal() {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;

    const nodes = Array.from(el.querySelectorAll(".reveal"));

    // Immediately reveal anything already in (or near) the viewport.
    const revealIfVisible = (n) => {
      const r = n.getBoundingClientRect();
      const vh = window.innerHeight || document.documentElement.clientHeight;
      if (r.top < vh * 1.1 && r.bottom > -100) n.classList.add("is-in");
    };
    nodes.forEach(revealIfVisible);

    // IntersectionObserver for the rest as you scroll.
    let io;
    if ("IntersectionObserver" in window) {
      io = new IntersectionObserver(
        (entries) => {
          entries.forEach((e) => {
            if (e.isIntersecting) {
              e.target.classList.add("is-in");
              io.unobserve(e.target);
            }
          });
        },
        { rootMargin: "0px 0px -10% 0px", threshold: 0.05 }
      );
      nodes.forEach((n) => {if (!n.classList.contains("is-in")) io.observe(n);});
    }

    // Safety net: if anything is still hidden after a beat, reveal it.
    const fallback = setTimeout(() => {
      nodes.forEach((n) => n.classList.add("is-in"));
    }, 1200);

    const onScroll = () => nodes.forEach(revealIfVisible);
    window.addEventListener("scroll", onScroll, { passive: true });

    return () => {
      clearTimeout(fallback);
      window.removeEventListener("scroll", onScroll);
      if (io) io.disconnect();
    };
  }, []);
  return ref;
}

/* ====== Icons ====== */
const ArrowRight = ({ size = 16 }) =>
<svg className="arr" width={size} height={size} viewBox="0 0 16 16" fill="none">
    <path d="M2 8H14M14 8L9 3M14 8L9 13" stroke="currentColor" strokeWidth="1.5" strokeLinecap="square" strokeLinejoin="miter" />
  </svg>;

const ArrowL = () =>
<svg width="18" height="14" viewBox="0 0 18 14" fill="none">
    <path d="M16 7H2M2 7L7 2M2 7L7 12" stroke="currentColor" strokeWidth="1.4" strokeLinecap="square" />
  </svg>;

const ArrowR = () =>
<svg width="18" height="14" viewBox="0 0 18 14" fill="none">
    <path d="M2 7H16M16 7L11 2M16 7L11 12" stroke="currentColor" strokeWidth="1.4" strokeLinecap="square" />
  </svg>;

const PlayIcon = () =>
<svg width="11" height="12" viewBox="0 0 11 12" fill="none">
    <path d="M1 1L10 6L1 11V1Z" stroke="currentColor" strokeWidth="1.4" strokeLinejoin="miter" fill="none" />
  </svg>;


/* ====== Placeholder image — striped + caption ====== */
const Placeholder = ({ label }) =>
<div className="ph"><span>{label}</span></div>;


/* ====== Top Nav ====== */
function Nav() {
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 40);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return (
    <nav className={"nav" + (scrolled ? " is-scrolled" : "")} data-screen-label="Nav">
      <a href="#top" className="nav__brand">
        <Banner size={28} />
      </a>
      <div className="nav__links">
        <a href="#about">About</a>
        <a href="#challenges">Challenges</a>
        <a href="#projects">Projects</a>
        <a href="#magazine">Magazine</a>
        <a href="#join">Join</a>
      </div>
      <a href="#join" className="btn btn--blue btn--sm">
        JOIN IC <ArrowRight size={14} />
      </a>
    </nav>);

}

/* ====== Hero ====== */
function Hero() {
  return (
    <header className="hero" id="top" data-screen-label="Hero">
      <LogoLarge className="hero__watermark" />
      <div className="hero__meta mono">— EST. 2024 &nbsp;/&nbsp; PENN STATE &nbsp;/&nbsp; 30+ MEMBERS</div>

      <div className="container hero__inner">
        <h1 className="hero__title reveal">
          Challenge<br />
          Everything,<br />
          <span className="blue">Fear Nothing.</span>
        </h1>
        <p className="hero__sub reveal">
          해볼 수 있는 건 다 해보자. 펜스테이트에서 시작된 무한도전,<br />
          실행으로 증명하는 커뮤니티 스타트업.
        </p>
        <div className="hero__ctas reveal">
          <a href="#join" className="btn btn--blue">우리와 함께하기 <ArrowRight /></a>
          <a href="#about" className="btn btn--ghost"><PlayIcon /> IC 소개 영상</a>
        </div>
      </div>

      <div className="hero__scroll">
        <div className="mono">SCROLL</div>
        <div className="hero__scroll-line" />
      </div>
    </header>);

}

/* ====== Stats ====== */
function Stats() {
  return (
    <section className="container" id="about" data-screen-label="About">
      <div className="stats reveal">
        <div>
          <div className="eyebrow stats__label">— WHO WE ARE</div>
          <h2 className="stats__title">실행이 곧<br />증명이다.</h2>
        </div>
        <div className="stats__grid">
          <div>
            <div className="stat__num">30+</div>
            <div className="stat__label mono">PROJECTS</div>
          </div>
          <div>
            <div className="stat__num">20+</div>
            <div className="stat__label mono">Challenges</div>
          </div>
          <div>
            <div className="stat__num">∞</div>
            <div className="stat__label mono">Possibilities</div>
          </div>
        </div>
      </div>
    </section>);

}

/* ====== Card rail (Challenges + Projects share this) ====== */
function CardRail({ items, idPrefix }) {
  const trackRef = useRef(null);
  const [page, setPage] = useState(0);
  const [pageCount, setPageCount] = useState(1);
  const [atStart, setAtStart] = useState(true);
  const [atEnd, setAtEnd] = useState(false);

  const recompute = useCallback(() => {
    const el = trackRef.current;
    if (!el) return;
    const card = el.querySelector(".card");
    if (!card) return;
    const cardW = card.getBoundingClientRect().width;
    const gap = parseFloat(getComputedStyle(el).gap) || 24;
    const perView = Math.max(1, Math.round((el.clientWidth + gap) / (cardW + gap)));
    const pages = Math.max(1, Math.ceil(items.length / perView));
    setPageCount(pages);
    const p = Math.round(el.scrollLeft / (el.clientWidth - 1));
    const cur = Math.min(pages - 1, Math.max(0, p));
    setPage(cur);
    setAtStart(el.scrollLeft <= 4);
    setAtEnd(el.scrollLeft + el.clientWidth >= el.scrollWidth - 4);
  }, [items.length]);

  useEffect(() => {
    recompute();
    const el = trackRef.current;
    if (!el) return;
    el.addEventListener("scroll", recompute, { passive: true });
    window.addEventListener("resize", recompute);
    return () => {
      el.removeEventListener("scroll", recompute);
      window.removeEventListener("resize", recompute);
    };
  }, [recompute]);

  const scrollByPage = (dir) => {
    const el = trackRef.current;
    if (!el) return;
    el.scrollBy({ left: dir * el.clientWidth, behavior: "smooth" });
  };

  return (
    <>
      <div className="rail">
        <div className="rail__track" ref={trackRef}>
          {items.map((it, i) =>
          <article className="card" key={idPrefix + i}>
              <div className={"card__media" + (it.appIcon ? " card__media--app" : "") + (it.coverImage ? " card__media--cover" : "")}>
                {it.appIcon ? (
                  <div className="card__app-wrap">
                    <img className="card__app-icon" src={it.appIcon} alt={it.title} loading="lazy" />
                    <div className="card__app-caption">KEYGLO · 키글로</div>
                  </div>
                ) : it.coverImage ? (
                  <img className="card__cover-img" src={it.coverImage} alt={it.title} loading="lazy" />
                ) : it.photo ? <Photo photoKey={it.photo} alt={it.title} /> : <Placeholder label={it.placeholder} />}
                <div className="card__num">{String(i + 1).padStart(2, "0")}</div>
                {it.live ?
              <div className="tag tag--live"><span className="dot" /> LIVE</div> :

              <div className="tag">{it.tag}</div>
              }
                <LogoLarge className="card__wm" />
              </div>
              <div className="card__body">
                <div className="card__cat">{it.cat}</div>
                <h3 className="card__title">{it.title}</h3>
                <div className="card__meta">{it.meta}</div>
              </div>
            </article>
          )}
        </div>
      </div>

      <div className="progress">
        <div className="progress__count">
          {String(page + 1).padStart(2, "0")} / {String(pageCount).padStart(2, "0")}
        </div>
        <div className="progress__track">
          {Array.from({ length: pageCount }).map((_, i) =>
          <span key={i} className={"progress__seg" + (i <= page ? " is-on" : "")} />
          )}
        </div>
        <div className="progress__total">
          {items.length}+ {idPrefix === "ch" ? "CHALLENGES COMPLETED" : "PROJECTS SHIPPING"}
        </div>
      </div>

      {/* Floating arrows for this rail — handled by parent via context-less prop. We render in parent. */}
      <RailArrowsBridge atStart={atStart} atEnd={atEnd} onPrev={() => scrollByPage(-1)} onNext={() => scrollByPage(1)} idPrefix={idPrefix} />
    </>);

}

/* Bridges arrow state to a sibling component via a custom event — simpler than lifting state. */
function RailArrowsBridge({ atStart, atEnd, onPrev, onNext, idPrefix }) {
  useEffect(() => {
    window.dispatchEvent(new CustomEvent("rail-" + idPrefix, { detail: { atStart, atEnd, onPrev, onNext } }));
  });
  return null;
}

function RailArrows({ idPrefix }) {
  const [state, setState] = useState({ atStart: true, atEnd: false, onPrev: () => {}, onNext: () => {} });
  useEffect(() => {
    const h = (e) => setState(e.detail);
    window.addEventListener("rail-" + idPrefix, h);
    return () => window.removeEventListener("rail-" + idPrefix, h);
  }, [idPrefix]);
  return (
    <div className="arrows">
      <button
        className={"arrow-btn" + (state.atStart ? "" : " arrow-btn--blue")}
        onClick={state.onPrev}
        disabled={state.atStart}
        aria-label="Previous"><ArrowL /></button>
      <button
        className={"arrow-btn" + (state.atEnd ? "" : " arrow-btn--blue")}
        onClick={state.onNext}
        disabled={state.atEnd}
        aria-label="Next"><ArrowR /></button>
    </div>);

}

/* ====== Photo helper — uses window.IC_PHOTOS (base64 data URLs) ====== */
const photoSrc = (key) =>
  (typeof window !== "undefined" && window.IC_PHOTOS && window.IC_PHOTOS[key]) || null;

const Photo = ({ photoKey, alt = "" }) => {
  const src = photoSrc(photoKey);
  if (!src) return null;
  return (
    <>
      <img className="photo" src={src} alt={alt} loading="lazy" />
      <div className="photo__veil" aria-hidden="true" />
    </>);

};

/* ====== Challenges ====== */
const CHALLENGES = [
{ title: "무면허운전", cat: "Sky", meta: "2026 · 4km · PULLED OVER", tag: "EXTREME", placeholder: "// SKYDIVE\n14,000FT", photo: "ch01" },
{ title: "GO-KARTING Race", cat: "Compete", meta: "2025 · 8 stations · Endurance", tag: "PHYSICAL", placeholder: "// HYROX\n8 STATIONS", photo: "ch02" },
{ title: "OFF-ROAD Driving", cat: "Snow", meta: "2025 · Everest Mountain", tag: "WINTER", placeholder: "// SNOW\nPOCONO", photo: "ch03" },
{ title: "CLIFF DIVING", cat: "Safety", meta: "2025 · 300ft · Injured  ", tag: "LICENSE", placeholder: "// LICENSE\nFIREARMS", photo: "ch04" },
{ title: "Bodyprofile", cat: "Fitness", meta: "2025 · 바디프로필 촬영", tag: "PHYSICAL", placeholder: "// BODY\nPROFILE" },
{ title: "Bouldering & Climbing", cat: "Sport", meta: "2025 · 실내 클라이밍", tag: "PHYSICAL", placeholder: "// CLIMB\nBOULDER" },
{ title: "Go-Kart Race", cat: "Speed", meta: "2025 · 고카트 대회", tag: "COMPETE", placeholder: "// KART\nSPEED" },
{ title: "Scuba Diving", cat: "Water", meta: "2025 · 스쿠버다이빙", tag: "EXTREME", placeholder: "// SCUBA\nDIVE" }];


function ChallengesSection() {
  return (
    <section className="section" id="challenges" data-screen-label="Challenges">
      <div className="container">
        <div className="s-header reveal">
          <div>
            <div className="eyebrow">01 — CHALLENGES</div>
            <h2 className="s-header__title">우리의<br />{"\u00A0\u00A0\u00A0\u00A0도전들"}</h2>
          </div>
          <div className="s-header__right">
            <p className="s-header__sub">
              육체의 한계, 두려움의 경계 —<br />
              우리는 직접 부딪힌다.
            </p>
            <RailArrows idPrefix="ch" />
          </div>
        </div>
        <div className="reveal">
          <CardRail items={CHALLENGES} idPrefix="ch" />
        </div>
      </div>
    </section>);

}

/* ====== Projects ====== */
const PROJECTS = [
{ title: "KEYGLO KEYBOARD", cat: "App", meta: "2026 · 키글로 · 한↔영 키보드", live: true, placeholder: "// IC.APP\nv1.0", appIcon: "assets/keyglo-icon.png" },
{ title: "Drone Manufacturing", cat: "Build", meta: "2025 · 자체 제작 · FPV", tag: "HARDWARE", placeholder: "// DRONE\nFPV", coverImage: "assets/drone.jpg" },
{ title: "RC Car Build & Sell", cat: "Product", meta: "2025 · 제작 · 판매 진행 중", live: true, placeholder: "// RC.CAR\nBUILD/SELL" },
{ title: "Content Channel", cat: "Content", meta: "2025 · 유튜브 · 인스타", tag: "MEDIA", placeholder: "// MEDIA\nYT / IG", coverImage: "assets/content-channel.jpg" },
{ title: "Movie Filming", cat: "Film", meta: "2026 · 단편 영상 제작", tag: "CINEMA", placeholder: "// FILM\nCINEMA", coverImage: "assets/movie-filming.jpg" },
{ title: "Drone Pilot License", cat: "Education", meta: "2025 · 촬영·레이싱 드론 자격증", tag: "LICENSE", placeholder: "// PILOT\nLICENSE" }];


function ProjectsSection() {
  return (
    <section className="section" id="projects" data-screen-label="Projects" style={{ borderTop: "1px solid var(--hairline)" }}>
      <div className="container">
        <div className="s-header reveal">
          <div>
            <div className="eyebrow">02 — PROJECTS</div>
            <h2 className="s-header__title">우리가<br />만드는 것들.</h2>
          </div>
          <div className="s-header__right">
            <p className="s-header__sub">
              앱 · 콘텐츠 · 제품 —<br />
              실행이 결과물로 남는다.
            </p>
            <RailArrows idPrefix="pj" />
          </div>
        </div>
        <div className="reveal">
          <CardRail items={PROJECTS} idPrefix="pj" />
        </div>
      </div>
    </section>);

}

/* ====== Magazine grid ====== */
const MAG_TILES = [
{ mod: "big", label: "// IC — 001\nDRONE SHOT", photo: "m01" },
{ mod: "", label: "// IC — 002\nGROUP", photo: "m02" },
{ mod: "tall", label: "// IC — 003\nACTION", photo: "m03" },
{ mod: "", label: "// IC — 004\nBTS", photo: "m04" },
{ mod: "wide", label: "// IC — 005\nLANDSCAPE", photo: "m05" },
{ mod: "", label: "// IC — 006\nPORTRAIT", photo: "m06" },
{ mod: "tall", label: "// IC — 007\nVERTICAL", photo: "m07" },
{ mod: "", label: "// IC — 008\nDETAIL", photo: "m08" },
{ mod: "wide", label: "// IC — 009\nWIDE", photo: "m09" },
{ mod: "", label: "// IC — 010\nMOMENT" },
{ mod: "", label: "// IC — 011\nFILM" }];


function MagazineSection() {
  return (
    <section className="section" id="magazine" data-screen-label="Magazine" style={{ borderTop: "1px solid var(--hairline)" }}>
      <div className="container">
        <div className="s-header reveal">
          <div>
            <div className="eyebrow">03 — THE MAGAZINE</div>
            <h2 className="s-header__title">현장의<br />기록.</h2>
          </div>
          <div className="s-header__right">
            <p className="s-header__sub">
              우리가 살아낸 순간들,<br />
              흑백 매거진 큐레이션.
            </p>
            <a href="#" className="btn btn--ghost btn--sm">전체 보기 <ArrowRight size={14} /></a>
          </div>
        </div>

        <div className="mag-grid reveal">
          {MAG_TILES.map((t, i) =>
          <div key={i} className={"mag-tile " + (t.mod ? "mag-tile--" + t.mod : "")}>
              {t.photo ? <Photo photoKey={t.photo} alt={t.label} /> : <Placeholder label={t.label} />}
              {i % 3 === 0 && <LogoLarge className="mag-tile__wm" />}
              <div className="mag-tile__code">{t.label.split("\n")[0].replace("// ", "")}</div>
            </div>
          )}
        </div>
      </div>
    </section>);

}

/* ====== Motto ====== */
function Motto() {
  return (
    <section className="section--motto motto" data-screen-label="Motto">
      <LogoLarge className="motto__wm" />
      <div className="container motto__inner">
        <div className="eyebrow reveal">— OUR MOTTO</div>

        <blockquote className="motto__quote reveal">
          <span className="motto__line">DO THE IMPOSSIBLE.</span>
        </blockquote>

        <div className="motto__sub reveal" style={{ fontSize: "28px" }}>
          <span className="motto__sub-line">끝없이 도전하라.</span>
          <span className="motto__sub-line">끝없이 살아가라.</span>
        </div>

        <div className="motto__caption mono reveal">INFINITE CHALLENGE · I.C</div>
      </div>
    </section>);

}

/* ====== Footer ====== */
function Footer() {
  return (
    <footer className="footer" id="join" data-screen-label="Footer">
      <div className="container">
        <div className="footer__grid">
          <div>
            <div className="footer__brand">
              <Banner size={32} />
            </div>
            <div className="footer__tag">
              Challenge Everything,<br />
              <span className="blue">Fear Nothing.</span>
            </div>
          </div>
          <div>
            <h4>Explore</h4>
            <ul className="footer__list">
              <li><a href="#challenges">Challenges</a></li>
              <li><a href="#projects">Projects</a></li>
              <li><a href="#magazine">Magazine</a></li>
            </ul>
          </div>
          <div>
            <h4>Join</h4>
            <ul className="footer__list">
              <li><a href="#">Apply</a></li>
              <li><a href="#">Members</a></li>
              <li><a href="#">Contact</a></li>
            </ul>
          </div>
          <div>
            <h4>Follow</h4>
            <ul className="footer__list">
              <li><a href="https://www.instagram.com/psu_i.c/" target="_blank" rel="noopener noreferrer">Instagram <span className="footer__handle">@psu_i.c</span></a></li>
              <li><a href="https://www.youtube.com/@TEAM_IC_OFFICIAL" target="_blank" rel="noopener noreferrer">YouTube <span className="footer__handle">@TEAM_IC_OFFICIAL</span></a></li>
              <li><a href="#">IC App</a></li>
            </ul>
          </div>
        </div>
        <div className="footer__bottom mono">
          <span>© 2026 INFINITE CHALLENGE — ALL RIGHTS RESERVED</span>
          <span>PENN STATE — ESTABLISHED 2024</span>
        </div>
      </div>
    </footer>);

}

/* ====== App root ====== */
function App() {
  const ref = useReveal();
  return (
    <div ref={ref}>
      <Nav />
      <Hero />
      <Stats />
      <ChallengesSection />
      <ProjectsSection />
      <MagazineSection />
      <Motto />
      <Footer />
    </div>);

}

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