/* =============================================================================
   비파트 인테리어 — 화면 본체
   -----------------------------------------------------------------------------
   글자는 전부 src/content.js, 시공 사례는 src/portfolio.js 에 있다.
   이 파일은 구조와 디자인만 담당한다.
   ========================================================================== */

const C = window.CONTENT;
const P = window.PORTFOLIO || [];
const { useState, useEffect, useRef, useCallback } = React;

// 주소 뒤에 ?shot=1 → 스크롤 애니메이션 없이 전부 바로 보이게 (스크린샷 검증용)
const SHOT = window.location.search.indexOf("shot=1") >= 0;

/* ── 공통 ─────────────────────────────────────────────────────────────── */

function useReveal(dep) {
  useEffect(() => {
    const els = document.querySelectorAll(".reveal:not(.in)");
    if (SHOT || !("IntersectionObserver" in window)) {
      els.forEach((el) => el.classList.add("in"));
      return;
    }
    const io = new IntersectionObserver(
      (entries) => entries.forEach((e) => {
        if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); }
      }),
      { rootMargin: "0px 0px -8% 0px" }
    );
    els.forEach((el) => io.observe(el));
    return () => io.disconnect();
  }, [dep]);
}

function Icon({ id, className = "w-5 h-5" }) {
  return <svg className={className} aria-hidden="true"><use href={"#i-" + id} /></svg>;
}

function Sprite() {
  return (
    <svg style={{ position: "absolute", width: 0, height: 0 }} aria-hidden="true">
      <defs>
        <symbol id="i-phone" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M5 4h4l2 5-2.5 1.5a11 11 0 0 0 5 5L15 13l5 2v4a2 2 0 0 1-2 2A16 16 0 0 1 3 6a2 2 0 0 1 2-2" /></symbol>
        <symbol id="i-chat" viewBox="0 0 24 24" fill="currentColor"><path d="M12 3C6.5 3 2 6.6 2 11c0 2.8 1.8 5.3 4.6 6.7l-1 3.6c-.1.4.3.7.6.5l4.3-2.8c.5.1 1 .1 1.5.1 5.5 0 10-3.6 10-8S17.5 3 12 3z" /></symbol>
        <symbol id="i-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 6l6 6-6 6" /></symbol>
        <symbol id="i-left" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M15 5l-7 7 7 7" /></symbol>
        <symbol id="i-right" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M9 5l7 7-7 7" /></symbol>
        <symbol id="i-close" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"><path d="M5 5l14 14M19 5L5 19" /></symbol>
        <symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"><path d="M3 7h18M3 12h18M3 17h18" /></symbol>
        <symbol id="i-pin" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M12 21s-7-6.2-7-11.5A7 7 0 0 1 19 9.5C19 14.8 12 21 12 21z" /><circle cx="12" cy="9.5" r="2.5" /></symbol>
        <symbol id="i-car" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M5 16V11l2-5h10l2 5v5M3 16h18v3h-3M6 19H3" /><circle cx="7.5" cy="13.5" r="1" /><circle cx="16.5" cy="13.5" r="1" /></symbol>
        <symbol id="i-area" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="9" /><path d="M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18" /></symbol>
        <symbol id="i-plus" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"><path d="M12 5v14M5 12h14" /></symbol>
      </defs>
    </svg>
  );
}

function Lines({ text }) {
  return text.split("\n").map((l, i, a) => <React.Fragment key={i}>{l}{i < a.length - 1 && <br />}</React.Fragment>);
}

function Eyebrow({ children, dark }) {
  return (
    <p className={"font-en text-[11px] md:text-xs tracking-[0.32em] uppercase mb-5 flex items-center gap-3 " + (dark ? "text-white/60" : "text-mute")}>
      <span className={"inline-block w-6 h-px " + (dark ? "bg-white/40" : "bg-mute/60")} />{children}
    </p>
  );
}

function Logo({ light, pcInk }) {
  return (
    <span className={"flex items-baseline gap-2 leading-none " + (light ? (pcInk ? "text-white md:text-ink" : "text-white") : "text-ink")}>
      <span className="font-en font-semibold text-[19px] md:text-[21px] tracking-[0.08em]">{C.brand.logoMain}</span>
      <span className="font-en font-light text-[10px] md:text-[11px] tracking-[0.42em] opacity-80">{C.brand.logoSub}</span>
    </span>
  );
}

/* ── 헤더 / 메뉴 ──────────────────────────────────────────────────────── */

function Header({ heroSplit }) {
  const [solid, setSolid] = useState(false);
  const [open, setOpen] = useState(false);
  useEffect(() => {
    const on = () => setSolid(window.scrollY > window.innerHeight * 0.75);
    on(); window.addEventListener("scroll", on, { passive: true });
    return () => window.removeEventListener("scroll", on);
  }, []);
  useEffect(() => { document.body.style.overflow = open ? "hidden" : ""; }, [open]);
  const light = !solid;
  // 최상단일 때: 1번(흰 분할)은 PC에서 검정, 2~5번(어두운 전체화면)은 흰색
  const navCol = light ? (heroSplit ? "text-white md:text-ink" : "text-white") : "text-ink";
  return (
    <>
      <header className={"fixed top-0 inset-x-0 z-40 transition-all duration-500 " + (solid ? "bg-paper/95 backdrop-blur border-b border-line" : "bg-gradient-to-b from-black/45 to-transparent" + (heroSplit ? " md:bg-none" : ""))}>
        <div className="max-w-8xl mx-auto px-5 md:px-10 h-16 md:h-[78px] flex items-center justify-between">
          <a href="#top" aria-label="비파트 인테리어 홈"><Logo light={light} pcInk={heroSplit} /></a>
          <nav className="hidden lg:flex items-center gap-11">
            {C.nav.map((n) => (
              <a key={n.id} href={"#" + n.id} className={"font-en text-[13px] tracking-[0.2em] transition-opacity hover:opacity-60 " + navCol}>{n.label}</a>
            ))}
          </nav>
          <div className="flex items-center gap-2">
            <a href={C.brand.phoneHref} className={"hidden lg:inline-flex items-center gap-2 font-en text-[13px] tracking-wider px-4 py-2 rounded-full border transition-colors " + (light ? (heroSplit ? "text-white md:text-ink border-white/50 md:border-ink/30 hover:bg-white hover:text-ink md:hover:bg-ink md:hover:text-white" : "text-white border-white/50 hover:bg-white hover:text-ink") : "text-ink border-ink/25 hover:bg-ink hover:text-white")}>
              <Icon id="phone" className="w-4 h-4" />{C.brand.phone}
            </a>
            <button onClick={() => setOpen(true)} className={"lg:hidden p-2 -mr-2 " + navCol} aria-label="메뉴 열기">
              <Icon id="menu" className="w-7 h-7" />
            </button>
          </div>
        </div>
      </header>

      {/* 모바일 전체화면 메뉴 */}
      <div className={"fixed inset-0 z-50 bg-char text-white transition-opacity duration-300 lg:hidden " + (open ? "opacity-100" : "opacity-0 pointer-events-none")}>
        <div className="px-5 h-16 flex items-center justify-between">
          <Logo light />
          <button onClick={() => setOpen(false)} className="p-2 -mr-2" aria-label="메뉴 닫기"><Icon id="close" className="w-7 h-7" /></button>
        </div>
        <nav className="px-7 pt-10 flex flex-col gap-6">
          {C.nav.map((n, i) => (
            <a key={n.id} href={"#" + n.id} onClick={() => setOpen(false)} className="font-en text-3xl tracking-[0.12em] font-light flex items-baseline gap-4">
              <span className="text-xs text-white/40 tracking-widest">0{i + 1}</span>{n.label}
            </a>
          ))}
        </nav>
        <div className="absolute bottom-0 inset-x-0 p-6 grid grid-cols-2 gap-3" style={{ paddingBottom: "max(1.5rem, env(safe-area-inset-bottom))" }}>
          <a href={C.brand.phoneHref} className="flex items-center justify-center gap-2 py-4 border border-white/30 text-sm"><Icon id="phone" className="w-4 h-4" />전화 상담</a>
          <a href={C.brand.kakao} target="_blank" rel="noreferrer noopener" className="flex items-center justify-center gap-2 py-4 bg-white text-ink text-sm"><Icon id="chat" className="w-4 h-4" />카카오톡 상담</a>
        </div>
      </div>
    </>
  );
}

/* ── 첫 화면 (아울디자인식 꽉 찬 사진 슬라이드) ─────────────────────────── */

function Hero({ onSlide }) {
  const s = C.hero.slides;
  const [cur, setCur] = useState(0);
  const timer = useRef(null);
  const go = useCallback((i) => setCur((i + s.length) % s.length), [s.length]);
  useEffect(() => {
    if (SHOT) return;
    timer.current = setTimeout(() => go(cur + 1), 6000);
    return () => clearTimeout(timer.current);
  }, [cur, go]);
  useEffect(() => { if (onSlide) onSlide(cur); }, [cur]);
  // 1번 사진만 PC 좌우 분할, 2~5번은 전체화면
  const split = cur === 0;
  // 손가락으로 넘기기
  const touch = useRef(null);
  return (
    <section id="top" className={"relative h-[100svh] min-h-[560px] w-full overflow-hidden bg-char " + (split ? "md:bg-paper" : "")} style={SHOT ? { height: window.innerHeight } : undefined}
      onTouchStart={(e) => (touch.current = e.touches[0].clientX)}
      onTouchEnd={(e) => { if (touch.current == null) return; const d = e.changedTouches[0].clientX - touch.current; if (Math.abs(d) > 50) go(cur + (d < 0 ? 1 : -1)); touch.current = null; }}>

      {/* 전체화면 사진 배경: 모바일=항상 / PC=2~5번(비분할)일 때 */}
      <div className={"absolute inset-0 " + (split ? "md:hidden" : "")}>
        {s.map((sl, i) => (
          <div key={i} className={"hero-slide absolute inset-0 " + (i === cur ? "on opacity-100" : "opacity-0")} aria-hidden={i !== cur}>
            <img src={sl.image} alt={sl.caption} className="w-full h-full object-cover" style={i === 0 ? { objectPosition: "50% 22%" } : undefined} loading={i === 0 ? "eager" : "lazy"} fetchpriority={i === 0 ? "high" : "auto"} />
          </div>
        ))}
        <div className="absolute inset-0 bg-black/30" />
        <div className="absolute inset-0 bg-gradient-to-t from-black/55 via-transparent to-transparent" />
      </div>

      {/* 콘텐츠: 모바일=오버레이 / PC=좌우 분할(사진 전체가 온전히 보임) */}
      <div className={"relative h-full max-w-8xl mx-auto px-5 md:px-10 grid grid-cols-1 md:grid-cols-12 md:gap-10 lg:gap-14 " + (split ? "md:items-stretch md:pt-[92px] md:pb-8" : "md:items-center")}>
        {/* 텍스트: 1번=검정/흰배경, 2~5번=흰색 오버레이 */}
        <div className={"md:col-span-4 pt-28 pb-24 md:py-0 min-h-[100svh] md:min-h-0 flex flex-col justify-start md:justify-center text-left text-white " + (split ? "md:text-ink" : "md:text-white")}>
          <p className={"font-en text-[10px] md:text-[11px] tracking-[0.36em] mb-4 md:mb-6 text-white/70 " + (split ? "md:text-mute" : "md:text-white/70")}>{C.hero.eyebrow}</p>
          <h1 className="text-[26px] leading-[1.4] md:text-[44px] md:leading-[1.28] font-semibold tracking-[-0.02em] break-keep"><Lines text={C.hero.title} /></h1>
          <p className={"mt-4 md:mt-7 text-[13px] md:text-[15px] max-w-md leading-relaxed md:leading-[1.9] text-white/80 " + (split ? "md:text-ink2" : "md:text-white/80")}>{C.hero.desc}</p>
          <div className="mt-7 md:mt-9 flex flex-col sm:flex-row flex-wrap items-start sm:items-center gap-2.5 whitespace-nowrap">
            <a href="#contact" className={"group inline-flex items-center gap-3 px-6 py-3 rounded-full border text-[14px] transition-colors border-white/80 hover:bg-white hover:text-ink " + (split ? "md:border-ink/30 md:hover:bg-ink md:hover:text-white" : "")}>
              {C.hero.ctaPrimary}<Icon id="arrow" className="w-4 h-4 transition-transform group-hover:translate-x-1" />
            </a>
            <div className="flex items-center gap-2.5">
              <a href={C.brand.phoneHref} className={"inline-flex items-center gap-2 px-4 py-3 rounded-full text-[13px] bg-white/10 backdrop-blur hover:bg-white/20 " + (split ? "md:bg-transparent md:border md:border-ink/20 md:hover:bg-ink/5" : "")}><Icon id="phone" className="w-4 h-4" />{C.brand.phone}</a>
              <a href={C.brand.kakao} target="_blank" rel="noreferrer noopener" className={"inline-flex items-center gap-2 px-4 py-3 rounded-full text-[13px] bg-white/10 backdrop-blur hover:bg-white/20 " + (split ? "md:bg-transparent md:border md:border-ink/20 md:hover:bg-ink/5" : "")}><Icon id="chat" className="w-4 h-4" />카톡 상담</a>
            </div>
          </div>
        </div>

        {/* PC 1번 사진만: 전체가 온전히 보이도록 (세로 4:5 = 사진 비율과 일치, 확대·잘림 없음) */}
        <figure className={"md:col-span-8 items-center justify-center " + (split ? "hidden md:flex" : "hidden")}>
          <div className="relative h-full w-full overflow-hidden bg-stone shadow-2xl">
            {s.map((sl, i) => (
              <div key={i} className={"hero-slide absolute inset-0 " + (i === cur ? "on opacity-100" : "opacity-0")} aria-hidden={i !== cur}>
                <img src={sl.image} alt={sl.caption} className="w-full h-full object-cover" style={i === 0 ? { objectPosition: "50% 40%" } : undefined} loading={i === 0 ? "eager" : "lazy"} />
              </div>
            ))}
            <div className="absolute bottom-0 inset-x-0 p-6 bg-gradient-to-t from-black/60 via-black/10 to-transparent">
              <div className="flex items-end justify-between gap-6 text-white">
                <div className="min-w-0">
                  <p className="font-en text-[11px] tracking-[0.2em] text-white/80 truncate">{s[cur].caption}</p>
                  <div className="mt-3 flex gap-2">
                    {s.map((_, i) => (
                      <button key={i} onClick={() => go(i)} aria-label={i + 1 + "번째 사진"} className={"hero-bar relative h-[2px] w-10 bg-white/30 overflow-hidden " + (i === cur ? "on" : "")}>
                        {i < cur && <span className="absolute inset-0 bg-white" />}
                      </button>
                    ))}
                  </div>
                </div>
                <div className="flex items-center gap-4 font-en text-sm shrink-0">
                  <span className="tabular-nums">{String(cur + 1).padStart(2, "0")} <span className="text-white/50">/ {String(s.length).padStart(2, "0")}</span></span>
                  <button onClick={() => go(cur - 1)} className="p-1 hover:opacity-60" aria-label="이전"><Icon id="left" /></button>
                  <button onClick={() => go(cur + 1)} className="p-1 hover:opacity-60" aria-label="다음"><Icon id="right" /></button>
                </div>
              </div>
            </div>
          </div>
        </figure>
      </div>

      {/* 하단 바(캡션·진행·화살표): 모바일=항상 / PC=2~5번(비분할) */}
      <div className={"absolute bottom-0 inset-x-0 pb-7 " + (split ? "md:hidden" : "")}>
        <div className="max-w-8xl mx-auto px-5 md:px-10 flex items-end justify-between gap-6 text-white">
          <div className="min-w-0">
            <p className="font-en text-[11px] tracking-[0.2em] text-white/70 truncate">{s[cur].caption}</p>
            <div className="mt-3 flex gap-2">
              {s.map((_, i) => (
                <button key={i} onClick={() => go(i)} aria-label={i + 1 + "번째 사진"} className={"hero-bar relative h-[2px] w-8 md:w-10 bg-white/30 overflow-hidden " + (i === cur ? "on" : "")}>
                  {i < cur && <span className="absolute inset-0 bg-white" />}
                </button>
              ))}
            </div>
          </div>
          <div className="flex items-center gap-4 font-en text-sm">
            <span className="tabular-nums">{String(cur + 1).padStart(2, "0")} <span className="text-white/50">/ {String(s.length).padStart(2, "0")}</span></span>
            <button onClick={() => go(cur - 1)} className="hidden md:inline-flex p-1 hover:opacity-60" aria-label="이전"><Icon id="left" /></button>
            <button onClick={() => go(cur + 1)} className="hidden md:inline-flex p-1 hover:opacity-60" aria-label="다음"><Icon id="right" /></button>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ── 회사 소개 ────────────────────────────────────────────────────────── */

function About() {
  const a = C.about;
  return (
    <section id="about" className="scroll-mt-16 py-24 md:py-36">
      <div className="max-w-8xl mx-auto px-5 md:px-10">
        <div className="grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-16 items-start">
          <div className="lg:col-span-5 reveal">
            <Eyebrow>{a.eyebrow}</Eyebrow>
            <h2 className="text-[28px] leading-[1.4] md:text-[40px] md:leading-[1.35] font-semibold tracking-[-0.02em]"><Lines text={a.title} /></h2>
            <p className="mt-7 text-[15px] md:text-base leading-[1.9] text-ink2">{a.lead}</p>
            <div className="mt-12 space-y-8">
              {a.strengths.map((s) => (
                <div key={s.no} className="border-t border-line pt-6 grid grid-cols-[48px_1fr] gap-2">
                  <span className="font-en text-sm text-mute tracking-widest pt-0.5">{s.no}</span>
                  <div>
                    <h3 className="text-[17px] md:text-lg font-semibold">{s.title}</h3>
                    <p className="mt-2 text-[14px] md:text-[15px] leading-[1.85] text-ink2">{s.text}</p>
                  </div>
                </div>
              ))}
            </div>
          </div>
          <figure className="lg:col-span-7 reveal">
            <div className="aspect-[4/5] md:aspect-[5/4] overflow-hidden bg-stone">
              <img src={a.image} alt={a.imageCaption} className="w-full h-full object-cover" loading="lazy" />
            </div>
            <figcaption className="mt-3 font-en text-[11px] tracking-[0.18em] text-mute">{a.imageCaption}</figcaption>
          </figure>
        </div>

        <div className="mt-20 md:mt-28 grid grid-cols-1 sm:grid-cols-3 border-y border-line divide-y sm:divide-y-0 sm:divide-x divide-line reveal">
          {a.stats.map((s, i) => (
            <div key={i} className="py-8 sm:py-10 sm:px-8 first:sm:pl-0 flex sm:block items-baseline gap-5">
              <p className="font-en font-light text-5xl md:text-6xl tracking-tight tabular-nums w-24 sm:w-auto shrink-0">{s.num === "AUTO" ? P.length + "+" : s.num}</p>
              <p className="sm:mt-3 text-[13px] md:text-sm text-mute">{s.label}</p>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ── 서비스 / 일하는 방식 / 진행 순서 ──────────────────────────────────── */

function Service() {
  const s = C.service;
  return (
    <section id="service" className="scroll-mt-16 bg-stone py-24 md:py-36">
      <div className="max-w-8xl mx-auto px-5 md:px-10">
        <div className="grid grid-cols-1 lg:grid-cols-12 gap-8 items-end reveal">
          <div className="lg:col-span-7">
            <Eyebrow>{s.eyebrow}</Eyebrow>
            <h2 className="text-[28px] leading-[1.4] md:text-[40px] md:leading-[1.35] font-semibold tracking-[-0.02em]"><Lines text={s.title} /></h2>
          </div>
          <p className="lg:col-span-5 text-[15px] leading-[1.9] text-ink2">{s.desc}</p>
        </div>

        {/* 분야 — 모바일은 가로 스크롤 */}
        <div className="mt-14 -mx-5 px-5 md:mx-0 md:px-0 flex md:grid md:grid-cols-5 gap-3 md:gap-4 overflow-x-auto no-scrollbar snap-x snap-mandatory">
          {s.fields.map((f) => (
            <a key={f.en} href="#portfolio" className="tile reveal group relative shrink-0 w-[68vw] sm:w-[40vw] md:w-auto snap-start aspect-[3/4] overflow-hidden bg-char">
              <img src={f.image} alt={f.ko + " 인테리어"} className="w-full h-full object-cover opacity-90" loading="lazy" />
              <div className="absolute inset-0 bg-gradient-to-t from-black/75 via-black/10 to-transparent" />
              <div className="absolute bottom-0 inset-x-0 p-5 text-white">
                <p className="font-en text-[10px] tracking-[0.25em] text-white/70">{f.en}</p>
                <h3 className="mt-1.5 text-lg font-semibold">{f.ko}</h3>
                <p className="mt-2 text-[13px] leading-relaxed text-white/80">{f.text}</p>
              </div>
            </a>
          ))}
        </div>

        {/* 일하는 방식 */}
        <div className="mt-20 md:mt-28 grid sm:grid-cols-2 lg:grid-cols-4 gap-px bg-line border border-line reveal">
          {s.approach.map((a, i) => (
            <div key={i} className="bg-paper p-7 md:p-8">
              <p className="font-en text-xs text-mute tracking-widest">0{i + 1}</p>
              <h3 className="mt-6 text-[17px] font-semibold">{a.title}</h3>
              <p className="mt-3 text-[14px] leading-[1.8] text-ink2">{a.text}</p>
            </div>
          ))}
        </div>

        {/* 진행 순서 */}
        <div className="mt-20 md:mt-28 reveal">
          <p className="font-en text-xs tracking-[0.32em] text-mute mb-8">PROCESS</p>
          <ol className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-y-10 gap-x-6">
            {s.process.map((p) => (
              <li key={p.step} className="relative pt-6 border-t border-ink/80">
                <span className="absolute -top-[5px] left-0 w-[9px] h-[9px] rounded-full bg-ink" />
                <p className="font-en text-xs text-mute tracking-widest">STEP {p.step}</p>
                <h3 className="mt-2 text-[17px] font-semibold">{p.title}</h3>
                <p className="mt-2 text-[13px] leading-[1.75] text-ink2">{p.text}</p>
              </li>
            ))}
          </ol>
        </div>
      </div>
    </section>
  );
}

/* ── 포트폴리오 (디투모로우식 한눈에 보는 그리드) ──────────────────────── */

function Portfolio({ onOpen }) {
  const c = C.portfolio;
  const [filter, setFilter] = useState("전체");
  const list = P.filter((p) => filter === "전체" || p.category === filter);
  const shown = list;
  useReveal(filter);
  const counts = (f) => (f === "전체" ? P.length : P.filter((p) => p.category === f).length);
  return (
    <section id="portfolio" className="scroll-mt-16 py-24 md:py-36">
      <div className="max-w-8xl mx-auto px-5 md:px-10">
        <div className="flex flex-col md:flex-row md:items-end md:justify-between gap-6 reveal">
          <div>
            <Eyebrow>{c.eyebrow}</Eyebrow>
            <h2 className="text-[28px] md:text-[40px] font-semibold tracking-[-0.02em]">{c.title}</h2>
            <p className="mt-4 text-[14px] md:text-[15px] text-ink2">{c.desc}</p>
          </div>
        </div>

        <div className="mt-10 -mx-5 px-5 md:mx-0 md:px-0 flex gap-2 overflow-x-auto no-scrollbar" role="tablist">
          {c.filters.filter((f) => counts(f) > 0).map((f) => (
            <button key={f} role="tab" aria-selected={filter === f} onClick={() => setFilter(f)}
              className={"shrink-0 px-4 py-2 rounded-full text-[13px] border transition-colors " + (filter === f ? "bg-ink text-white border-ink" : "border-line text-ink2 hover:border-ink/40")}>
              {f}<span className={"ml-1.5 font-en text-[11px] " + (filter === f ? "text-white/60" : "text-mute")}>{counts(f)}</span>
            </button>
          ))}
        </div>

        <div className="mt-8 grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2 md:gap-3">
          {shown.map((p) => (
            <button key={p.slug} onClick={() => onOpen(p)} className="tile reveal group relative aspect-square overflow-hidden bg-stone text-left">
              <img src={p.cover} alt={p.ko + " " + p.category + " 인테리어"} className="w-full h-full object-cover" loading="lazy" />
              <div className="absolute inset-0 bg-black/0 group-hover:bg-black/45 transition-colors duration-500" />
              <div className="absolute inset-x-0 bottom-0 p-3 md:p-5 text-white bg-gradient-to-t from-black/60 to-transparent md:bg-none md:opacity-0 md:translate-y-2 group-hover:opacity-100 group-hover:translate-y-0 transition-all duration-500">
                <p className="font-en text-[13px] md:text-lg font-medium leading-tight">{p.en}</p>
                <p className="mt-1 text-[11px] md:text-[13px] text-white/80">{[p.region, p.size, p.category].filter(Boolean).join(" · ")}</p>
              </div>
              <span className="hidden md:flex absolute top-4 right-4 w-9 h-9 rounded-full border border-white/70 text-white items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-500"><Icon id="plus" className="w-4 h-4" /></span>
            </button>
          ))}
        </div>

      </div>
    </section>
  );
}

function ProjectModal({ p, onClose, onNav }) {
  const [idx, setIdx] = useState(0);
  const photos = p.photos;
  useEffect(() => { setIdx(0); }, [p.slug]);
  useEffect(() => {
    document.body.style.overflow = "hidden";
    const k = (e) => {
      if (e.key === "Escape") onClose();
      if (e.key === "ArrowRight") setIdx((i) => (i + 1) % photos.length);
      if (e.key === "ArrowLeft") setIdx((i) => (i - 1 + photos.length) % photos.length);
    };
    window.addEventListener("keydown", k);
    return () => { document.body.style.overflow = ""; window.removeEventListener("keydown", k); };
  }, [p.slug]);
  const touch = useRef(null);
  const meta = [["지역", p.region], ["규모", p.size], ["분야", p.category], ["연도", p.year]].filter((m) => m[1]);
  return (
    <div className="fixed inset-0 z-[60] bg-paper overflow-y-auto" role="dialog" aria-modal="true" aria-label={p.ko + " 시공 사례"}>
      <div className="sticky top-0 z-10 bg-paper/95 backdrop-blur border-b border-line">
        <div className="max-w-8xl mx-auto px-5 md:px-10 h-14 md:h-16 flex items-center justify-between">
          <p className="font-en text-[12px] tracking-[0.25em] text-mute">PORTFOLIO</p>
          <div className="flex items-center gap-1">
            <button onClick={() => onNav(-1)} className="p-2 hover:opacity-60" aria-label="이전 현장"><Icon id="left" /></button>
            <button onClick={() => onNav(1)} className="p-2 hover:opacity-60" aria-label="다음 현장"><Icon id="right" /></button>
            <button onClick={onClose} className="p-2 -mr-2 ml-2 hover:opacity-60" aria-label="닫기"><Icon id="close" className="w-6 h-6" /></button>
          </div>
        </div>
      </div>

      <div className="max-w-8xl mx-auto px-5 md:px-10 py-8 md:py-12 grid grid-cols-1 lg:grid-cols-12 gap-8 lg:gap-14">
        <div className="lg:col-span-8">
          <div className="relative aspect-[4/3] bg-stone overflow-hidden select-none"
            onTouchStart={(e) => (touch.current = e.touches[0].clientX)}
            onTouchEnd={(e) => { if (touch.current == null) return; const d = e.changedTouches[0].clientX - touch.current; if (Math.abs(d) > 40) setIdx((i) => (i + (d < 0 ? 1 : -1) + photos.length) % photos.length); touch.current = null; }}>
            <img key={photos[idx]} src={photos[idx]} alt={p.ko + " 사진 " + (idx + 1)} className="w-full h-full object-cover" />
            <button onClick={() => setIdx((i) => (i - 1 + photos.length) % photos.length)} className="absolute left-0 inset-y-0 w-1/4 flex items-center pl-3 text-white/0 hover:text-white" aria-label="이전 사진"><Icon id="left" className="w-8 h-8 drop-shadow" /></button>
            <button onClick={() => setIdx((i) => (i + 1) % photos.length)} className="absolute right-0 inset-y-0 w-1/4 flex items-center justify-end pr-3 text-white/0 hover:text-white" aria-label="다음 사진"><Icon id="right" className="w-8 h-8 drop-shadow" /></button>
            <span className="absolute bottom-3 right-3 font-en text-[12px] text-white bg-black/40 px-2.5 py-1 rounded-full tabular-nums">{idx + 1} / {photos.length}</span>
          </div>
          <div className="mt-3 flex gap-2 overflow-x-auto no-scrollbar">
            {photos.map((ph, i) => (
              <button key={ph} onClick={() => setIdx(i)} className={"shrink-0 w-20 h-14 md:w-24 md:h-16 overflow-hidden transition-opacity " + (i === idx ? "opacity-100 ring-1 ring-ink ring-offset-2 ring-offset-paper" : "opacity-50 hover:opacity-80")}>
                <img src={ph} alt="" className="w-full h-full object-cover" loading="lazy" />
              </button>
            ))}
          </div>

          {p.before && p.before.length > 0 && (
            <div className="mt-12">
              <p className="font-en text-xs tracking-[0.3em] text-mute mb-4">BEFORE — 공사 전</p>
              <div className="grid grid-cols-3 gap-2">
                {p.before.map((b) => <div key={b} className="aspect-[4/3] overflow-hidden bg-stone"><img src={b} alt={p.ko + " 공사 전"} className="w-full h-full object-cover grayscale-[40%]" loading="lazy" /></div>)}
              </div>
            </div>
          )}
        </div>

        <aside className="lg:col-span-4 lg:sticky lg:top-24 self-start">
          <p className="font-en text-3xl md:text-4xl font-light tracking-tight">{p.en}</p>
          <h3 className="mt-2 text-lg text-ink2">{p.ko}</h3>
          <dl className="mt-7 border-t border-line">
            {meta.map(([k, v]) => (
              <div key={k} className="flex py-3 border-b border-line text-[14px]"><dt className="w-16 text-mute">{k}</dt><dd>{v}</dd></div>
            ))}
          </dl>
          {p.concept && <p className="mt-7 text-[15px] leading-[1.9] text-ink2">{p.concept}</p>}
          {p.works && (
            <div className="mt-7">
              <p className="text-[13px] font-semibold mb-2">주요 공사</p>
              <p className="text-[14px] leading-[1.8] text-ink2">{p.works}</p>
            </div>
          )}
          {p.points && p.points.length > 0 && (
            <ul className="mt-7 space-y-4">
              {p.points.map((pt, i) => (
                <li key={i} className="grid grid-cols-[28px_1fr]">
                  <span className="font-en text-xs text-mute pt-1">0{i + 1}</span>
                  <div><p className="text-[14px] font-semibold">{pt.t}</p>{pt.d && <p className="mt-1 text-[13px] leading-[1.75] text-ink2">{pt.d}</p>}</div>
                </li>
              ))}
            </ul>
          )}
          <div className="mt-10 grid grid-cols-2 gap-2">
            <a href={C.brand.phoneHref} className="flex items-center justify-center gap-2 py-3.5 border border-ink/25 text-[14px] hover:bg-ink hover:text-white transition-colors"><Icon id="phone" className="w-4 h-4" />전화 문의</a>
            <a href={C.brand.kakao} target="_blank" rel="noreferrer noopener" className="flex items-center justify-center gap-2 py-3.5 bg-ink text-white text-[14px] hover:bg-ink2 transition-colors"><Icon id="chat" className="w-4 h-4" />카톡 문의</a>
          </div>
        </aside>
      </div>
    </div>
  );
}

/* ── 담당 실장 ────────────────────────────────────────────────────────── */

function Manager() {
  const m = C.manager;
  return (
    <section id="manager" className="scroll-mt-16 bg-char text-white py-24 md:py-36 overflow-hidden">
      <div className="max-w-8xl mx-auto px-5 md:px-10 grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-16 items-center">
        <div className="lg:col-span-6 grid grid-cols-5 gap-3 reveal">
          <div className="col-span-3 aspect-[3/4] overflow-hidden"><img src={m.image} alt={m.name + " " + m.role} className="w-full h-full object-cover" loading="lazy" /></div>
          <div className="col-span-2 self-end aspect-[3/4] overflow-hidden"><img src={m.subImage} alt="" className="w-full h-full object-cover" loading="lazy" /></div>
        </div>
        <div className="lg:col-span-6 reveal">
          <Eyebrow dark>{m.eyebrow}</Eyebrow>
          <h2 className="text-[28px] leading-[1.4] md:text-[40px] md:leading-[1.35] font-semibold tracking-[-0.02em]"><Lines text={m.title} /></h2>
          <p className="mt-8 flex items-baseline gap-3"><span className="text-2xl font-semibold">{m.name}</span><span className="text-white/60">{m.role}</span></p>
          <p className="mt-6 text-[15px] md:text-base leading-[1.9] text-white/75">{m.intro}</p>
          <ul className="mt-9 border-t border-white/15">
            {m.points.map((pt, i) => (
              <li key={i} className="py-4 border-b border-white/15 flex gap-4 text-[14px] md:text-[15px] text-white/85"><span className="font-en text-white/40 text-xs pt-1">0{i + 1}</span>{pt}</li>
            ))}
          </ul>
          <div className="mt-9 flex flex-wrap gap-3">
            <a href={C.brand.phoneHref} className="inline-flex items-center gap-2 px-6 py-3.5 rounded-full bg-white text-ink text-[14px] hover:bg-white/85"><Icon id="phone" className="w-4 h-4" />{m.name} {m.role}에게 전화</a>
            <a href={C.brand.kakao} target="_blank" rel="noreferrer noopener" className="inline-flex items-center gap-2 px-6 py-3.5 rounded-full border border-white/40 text-[14px] hover:bg-white/10"><Icon id="chat" className="w-4 h-4" />카카오톡 상담</a>
          </div>
        </div>
      </div>
    </section>
  );
}

/* ── 후기 ─────────────────────────────────────────────────────────────── */

function Review() {
  const r = C.review;
  return (
    <section id="review" className="scroll-mt-16 py-24 md:py-36">
      <div className="max-w-8xl mx-auto px-5 md:px-10">
        <div className="reveal">
          <Eyebrow>{r.eyebrow}</Eyebrow>
          <h2 className="text-[28px] md:text-[40px] font-semibold tracking-[-0.02em]">{r.title}</h2>
        </div>
        {r.list.length > 0 ? (
          <div className="mt-12 grid md:grid-cols-2 lg:grid-cols-3 gap-4">
            {r.list.map((v, i) => (
              <figure key={i} className="reveal bg-stone p-8 flex flex-col">
                <span className="font-en text-5xl leading-none text-mute/50">“</span>
                <blockquote className="mt-2 text-[15px] leading-[1.9] text-ink2 flex-1">{v.text}</blockquote>
                <figcaption className="mt-6 pt-5 border-t border-line text-[13px]"><span className="font-semibold">{v.name}</span>{v.project && <span className="text-mute"> · {v.project}</span>}</figcaption>
              </figure>
            ))}
          </div>
        ) : (
          <div className="mt-12 grid md:grid-cols-2 gap-3 reveal">
            <a href={C.brand.blog} target="_blank" rel="noreferrer noopener" className="group bg-stone p-8 md:p-10 flex flex-col justify-between min-h-[200px] hover:bg-ink hover:text-white transition-colors">
              <p className="font-en text-xs tracking-[0.3em] text-mute group-hover:text-white/60">NAVER BLOG</p>
              <div>
                <p className="text-[15px] leading-[1.9] text-ink2 group-hover:text-white/80">{r.emptyText}</p>
                <p className="mt-5 inline-flex items-center gap-2 text-[15px] font-semibold">시공 후기 보러가기<Icon id="arrow" className="w-4 h-4 transition-transform group-hover:translate-x-1" /></p>
              </div>
            </a>
            <a href={C.brand.naverPlace} target="_blank" rel="noreferrer noopener" className="group border border-line p-8 md:p-10 flex flex-col justify-between min-h-[200px] hover:border-ink transition-colors">
              <p className="font-en text-xs tracking-[0.3em] text-mute">NAVER PLACE</p>
              <div>
                <p className="text-[15px] leading-[1.9] text-ink2">네이버 플레이스에서 비파트 인테리어의 위치와 소식을 확인하실 수 있습니다.</p>
                <p className="mt-5 inline-flex items-center gap-2 text-[15px] font-semibold">플레이스 바로가기<Icon id="arrow" className="w-4 h-4 transition-transform group-hover:translate-x-1" /></p>
              </div>
            </a>
          </div>
        )}
      </div>
    </section>
  );
}

/* ── 오시는 길 · 상담 ─────────────────────────────────────────────────── */

function Contact() {
  const c = C.contact;
  const rows = [
    ["pin", "주소", c.address + (c.addressOld ? " (" + c.addressOld + ")" : "")],
    ["car", "주차", c.parking],
    ["area", "시공 지역", c.serviceArea],
  ];
  if (c.hours) rows.push(["phone", "운영 시간", c.hours]);
  return (
    <section id="contact" className="scroll-mt-16 bg-stone py-24 md:py-36">
      <div className="max-w-8xl mx-auto px-5 md:px-10 grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-16">
        <div className="lg:col-span-5 reveal">
          <Eyebrow>{c.eyebrow}</Eyebrow>
          <h2 className="text-[28px] leading-[1.4] md:text-[40px] md:leading-[1.35] font-semibold tracking-[-0.02em]"><Lines text={c.title} /></h2>
          <p className="mt-6 text-[15px] leading-[1.9] text-ink2">{c.desc}</p>

          <div className="mt-10 grid gap-3">
            <a href={C.brand.phoneHref} className="group flex items-center justify-between bg-ink text-white px-6 py-5 hover:bg-ink2 transition-colors">
              <span className="flex items-center gap-4"><Icon id="phone" /><span><span className="block text-[12px] text-white/60">전화 상담 · 이승현 실장</span><span className="font-en text-xl tracking-wide">{C.brand.phone}</span></span></span>
              <Icon id="arrow" className="w-5 h-5 transition-transform group-hover:translate-x-1" />
            </a>
            <a href={C.brand.kakao} target="_blank" rel="noreferrer noopener" className="group flex items-center justify-between bg-paper border border-line px-6 py-5 hover:border-ink transition-colors">
              <span className="flex items-center gap-4"><Icon id="chat" /><span><span className="block text-[12px] text-mute">사진 보내고 편하게 문의</span><span className="text-lg font-semibold">카카오톡 오픈채팅 상담</span></span></span>
              <Icon id="arrow" className="w-5 h-5 transition-transform group-hover:translate-x-1" />
            </a>
          </div>

          <dl className="mt-10 border-t border-line">
            {rows.map(([ic, k, v]) => (
              <div key={k} className="flex gap-4 py-4 border-b border-line text-[14px]">
                <Icon id={ic} className="w-5 h-5 text-mute shrink-0 mt-0.5" />
                <dt className="w-16 shrink-0 text-mute">{k}</dt><dd className="leading-relaxed min-w-0">{v}</dd>
              </div>
            ))}
          </dl>
        </div>
        <div className="lg:col-span-7 reveal">
          <div className="w-full h-[320px] md:h-[440px] lg:h-full lg:min-h-[520px] bg-line overflow-hidden grayscale">
            <iframe title="비파트 인테리어 위치" src={c.mapEmbed} className="w-full h-full border-0" loading="lazy" referrerPolicy="no-referrer-when-downgrade" />
          </div>
          <div className="mt-3 grid grid-cols-2 gap-2">
            <a href={c.naverMap} target="_blank" rel="noreferrer noopener" className="py-3.5 text-center text-[14px] border border-ink/20 hover:bg-ink hover:text-white transition-colors">네이버 지도로 보기</a>
            <a href={c.kakaoMap} target="_blank" rel="noreferrer noopener" className="py-3.5 text-center text-[14px] border border-ink/20 hover:bg-ink hover:text-white transition-colors">카카오맵으로 보기</a>
          </div>
        </div>
      </div>
    </section>
  );
}

function Footer() {
  const f = C.footer;
  const info = [f.company, f.ceo && "대표 " + f.ceo, f.bizNo && "사업자등록번호 " + f.bizNo, C.contact.address, "T. " + C.brand.phone, f.email && "E. " + f.email].filter(Boolean);
  return (
    <footer className="bg-char text-white/60 pt-16 pb-28 lg:pb-16">
      <div className="max-w-8xl mx-auto px-5 md:px-10">
        <div className="flex flex-col md:flex-row md:items-end md:justify-between gap-8 pb-10 border-b border-white/10">
          <Logo light />
          <nav className="flex flex-wrap gap-x-7 gap-y-3">
            {C.nav.map((n) => <a key={n.id} href={"#" + n.id} className="font-en text-[12px] tracking-[0.2em] hover:text-white">{n.label}</a>)}
            <a href={C.brand.blog} target="_blank" rel="noreferrer noopener" className="font-en text-[12px] tracking-[0.2em] hover:text-white">BLOG</a>
          </nav>
        </div>
        <p className="mt-8 text-[12px] leading-[2] flex flex-wrap gap-x-4">{info.map((t) => <span key={t}>{t}</span>)}</p>
        <p className="mt-4 font-en text-[11px] tracking-widest text-white/35">© {new Date().getFullYear()} B.PART INTERIOR. ALL RIGHTS RESERVED.</p>
      </div>
    </footer>
  );
}

// 모바일 하단 고정 상담 바 (첫 화면 지나면 등장)
function MobileBar() {
  const [show, setShow] = useState(false);
  useEffect(() => {
    const on = () => setShow(window.scrollY > window.innerHeight * 0.6);
    on(); window.addEventListener("scroll", on, { passive: true });
    return () => window.removeEventListener("scroll", on);
  }, []);
  return (
    <div className={"lg:hidden fixed bottom-0 inset-x-0 z-30 grid grid-cols-2 bg-ink text-white transition-transform duration-300 " + (show ? "translate-y-0" : "translate-y-full")} style={{ paddingBottom: "env(safe-area-inset-bottom)" }}>
      <a href={C.brand.phoneHref} className="flex items-center justify-center gap-2 py-4 text-[14px] border-r border-white/15"><Icon id="phone" className="w-4 h-4" />전화 상담</a>
      <a href={C.brand.kakao} target="_blank" rel="noreferrer noopener" className="flex items-center justify-center gap-2 py-4 text-[14px]"><Icon id="chat" className="w-4 h-4" />카카오톡 상담</a>
    </div>
  );
}

/* ── 앱 ───────────────────────────────────────────────────────────────── */

function App() {
  const [open, setOpen] = useState(null);
  const [heroSlide, setHeroSlide] = useState(0);
  useReveal("init");
  // 주소창 #work-<slug> 로 특정 현장 바로 열기 (공유용)
  useEffect(() => {
    const m = location.hash.match(/^#work-(.+)$/);
    if (m) { const p = P.find((x) => x.slug === m[1]); if (p) setOpen(p); }
  }, []);
  const openP = (p) => { setOpen(p); history.replaceState(null, "", "#work-" + p.slug); };
  const close = () => { setOpen(null); history.replaceState(null, "", "#portfolio"); };
  const nav = (d) => { const i = P.indexOf(open); openP(P[(i + d + P.length) % P.length]); };
  return (
    <>
      <Sprite />
      <Header heroSplit={heroSlide === 0} />
      <main>
        <Hero onSlide={setHeroSlide} />
        <About />
        <Service />
        <Portfolio onOpen={openP} />
        <Manager />
        <Review />
        <Contact />
      </main>
      <Footer />
      <MobileBar />
      {open && <ProjectModal p={open} onClose={close} onNav={nav} />}
    </>
  );
}

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