// 메인 앱 — 시안 전환 + Tweaks
const { useState, useEffect } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "typeMode": "mixed",
  "theme": "light",
  "palette": "heallight",
  "heroExtra": "none"
}/*EDITMODE-END*/;

// ─────────── 방문자용 팝업 ───────────
function popupColor(c) {
  const map = {
    warm: "linear-gradient(135deg, #f6e3c8, #e9b574)",
    mint: "linear-gradient(135deg, #b6dedb, #4ea49f)",
    blue: "linear-gradient(135deg, #6c8ab8, #2c4670)",
    rose: "linear-gradient(135deg, #f4d4d6, #d98a91)",
    plum: "linear-gradient(135deg, #c6b2cb, #8a6c8f)",
  };
  return map[c] || map.warm;
}

// 서식 렌더러: **굵게**, *기울임*, • 목록
function renderRichText(text) {
  if (!text) return null;
  const lines = String(text).split("\n");
  const result = [];
  let listBuf = [];
  const flush = () => {
    if (!listBuf.length) return;
    result.push(<ul key={"u"+result.length} style={{margin:"5px 0",paddingLeft:18}}>
      {listBuf.map((c,i)=><li key={i} style={{lineHeight:1.75}}>{c}</li>)}
    </ul>);
    listBuf = [];
  };
  const inline = (s, key) => {
    const parts = [];
    const rx = /(\*\*(.*?)\*\*|\*(.*?)\*)/g;
    let last = 0, k = 0, m;
    while ((m = rx.exec(s)) !== null) {
      if (m.index > last) parts.push(s.slice(last, m.index));
      if (m[0].startsWith("**")) parts.push(<strong key={k++}>{m[2]}</strong>);
      else parts.push(<em key={k++}>{m[3]}</em>);
      last = m.index + m[0].length;
    }
    if (last < s.length) parts.push(s.slice(last));
    return <React.Fragment key={key}>{parts}</React.Fragment>;
  };
  lines.forEach((line, i) => {
    if (/^[•·]\s/.test(line)) { listBuf.push(inline(line.slice(2), i)); }
    else { flush(); if (line.trim()==="") result.push(<br key={i}/>); else result.push(<div key={i} style={{lineHeight:1.8, marginBottom:4}}>{inline(line,i)}</div>); }
  });
  flush();
  return <>{result}</>;
}

function HomepagePopups() {
  const [popups, setPopups] = useState([]);
  const [dismissed, setDismissed] = useState(() => {
    try { return JSON.parse(localStorage.getItem("hlc-popup-dismissed") || "{}"); }
    catch { return {}; }
  });
  const [closedIds, setClosedIds] = useState(new Set());
  const [detailPopup, setDetailPopup] = useState(null);
  const [expanded, setExpanded] = useState(null);

  // 팝업별 드래그 위치 — 오늘 날짜 기준 localStorage 저장
  const today = new Date().toISOString().slice(0, 10);
  const [positions, setPositions] = useState(() => {
    try {
      const raw = JSON.parse(localStorage.getItem("hlc-popup-positions") || "{}");
      const result = {};
      Object.keys(raw).forEach(id => { if (raw[id].date === today) result[id] = raw[id]; });
      return result;
    } catch { return {}; }
  });
  const boxRefs  = useRef({});    // { [popupId]: domEl }
  const dragState = useRef(null); // 드래그 진행 상태
  const [stackBottoms, setStackBottoms] = useState({}); // 겹침 방지 스택 위치

  useEffect(() => {
    try {
      const unsub = firebase.firestore().collection("popupNotices")
        .where("active", "==", true)
        .onSnapshot(snap => {
          setPopups(snap.docs.map(d => {
            const { id: _localId, ...rest } = d.data();
            return { id: d.id, ...rest };
          }));
        }, () => {});
      return () => unsub();
    } catch(e) {}
  }, []);

  const visible = popups.filter(p => {
    if (!p.active) return false;
    if (closedIds.has(p.id)) return false;
    if (p.startDate && p.startDate > today) return false;
    if (!p.alwaysOn && p.endDate && p.endDate < today) return false;
    if (p.audience === "member") return false;
    if (dismissed[p.id] === today) return false;
    return true;
  });

  // 팝업 겹침 방지 — 드래그 안된 팝업 바텀 위치 동적 계산
  const _vIds = visible.map(p => p.id).join(',');
  const _pKeys = Object.keys(positions).join(',');
  (React.useLayoutEffect || React.useEffect)(() => {
    const _m = typeof window !== "undefined" && window.innerWidth <= 640;
    let cur = _m ? 12 : 32;
    const next = {};
    visible.forEach(p => {
      if (!_m && positions[p.id]) return;
      next[p.id] = cur;
      const el = boxRefs.current[p.id];
      cur += (el ? el.offsetHeight : 280) + 12;
    });
    setStackBottoms(prev => {
      if (Object.keys(next).join(',') === Object.keys(prev).join(',') &&
          Object.keys(next).every(k => prev[k] === next[k])) return prev;
      return next;
    });
  }, [_vIds, expanded, _pKeys]);

  if (visible.length === 0 && !detailPopup) return null;

  // 위치 저장/초기화
  const savePos = (id, top, left) => {
    setPositions(prev => {
      const next = { ...prev, [id]: { date: today, top, left } };
      try { localStorage.setItem("hlc-popup-positions", JSON.stringify(next)); } catch {}
      return next;
    });
  };
  const clearPos = (id) => {
    setPositions(prev => {
      const next = { ...prev };
      delete next[id];
      try { localStorage.setItem("hlc-popup-positions", JSON.stringify(next)); } catch {}
      return next;
    });
  };

  const close = (id) => setClosedIds(prev => new Set([...prev, id]));
  const dontShowToday = (id) => {
    const next = { ...dismissed, [id]: today };
    setDismissed(next);
    localStorage.setItem("hlc-popup-dismissed", JSON.stringify(next));
    clearPos(id);
    close(id);
  };

  // 드래그 (PC 전용)
  const startDrag = (e, id) => {
    if (e.target.tagName === "BUTTON" || e.target.closest("button")) return;
    e.preventDefault();
    const box = boxRefs.current[id];
    if (!box) return;
    const rect = box.getBoundingClientRect();
    dragState.current = { id, startX: e.clientX, startY: e.clientY, origTop: rect.top, origLeft: rect.left };
    const onMove = (ev) => {
      if (!dragState.current) return;
      const dx = ev.clientX - dragState.current.startX;
      const dy = ev.clientY - dragState.current.startY;
      const newTop  = Math.max(0, Math.min(window.innerHeight - 80,  dragState.current.origTop  + dy));
      const newLeft = Math.max(0, Math.min(window.innerWidth  - 320, dragState.current.origLeft + dx));
      if (box) { box.style.top = newTop + "px"; box.style.left = newLeft + "px"; box.style.bottom = "auto"; box.style.right = "auto"; }
    };
    const onUp = () => {
      if (!dragState.current) return;
      const b = boxRefs.current[dragState.current.id];
      if (b) { savePos(dragState.current.id, parseFloat(b.style.top)||0, parseFloat(b.style.left)||0); b.style.cursor = ""; }
      dragState.current = null;
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mouseup", onUp);
    };
    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseup", onUp);
  };

  const handleCta = (popup) => {
    if (!popup.ctaUrl) return;
    if (popup.ctaUrl.startsWith("#")) {
      const el = document.getElementById(popup.ctaUrl.slice(1));
      if (el) { close(popup.id); setTimeout(() => window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 72, behavior: "smooth" }), 200); }
    } else { window.open(popup.ctaUrl, "_blank"); }
  };

  const BODY_LIMIT = 140;
  const renderBody = (popup, isExp, titleLong) => {
    const body = popup.body || "";
    const bodyTruncated = !isExp && body.length > BODY_LIMIT;
    const showExpand = !isExp && (bodyTruncated || titleLong);
    const displayBody = bodyTruncated ? body.slice(0, BODY_LIMIT) + "…" : body;
    return (
      <div>
        <p style={{ fontSize: 14, lineHeight: 1.7, whiteSpace: "pre-wrap", margin: 0 }}>{renderRichText(displayBody)}</p>
        {showExpand && (
          <button onClick={() => setExpanded(popup.id)} style={{
            marginTop: 8, background: "transparent", border: 0, padding: 0,
            color: "var(--accent, #2c5282)", fontWeight: 700, fontSize: 13,
            cursor: "pointer", textDecoration: "underline",
          }}>자세히 보기 →</button>
        )}
        {isExp && (
          <button onClick={() => setExpanded(null)} style={{
            marginTop: 10, background: "transparent", border: 0, padding: 0,
            color: "var(--ink-3,#6b7088)", fontWeight: 600, fontSize: 12,
            cursor: "pointer",
          }}>접기 ↑</button>
        )}
      </div>
    );
  };

  const isMobile = typeof window !== "undefined" && window.innerWidth <= 640;

  return (
    <>
      {[...visible].reverse().map((popup, idx) => {
        const layout = popup.layout || "text-only";
        const hasImage = (layout === "image-only" || layout === "image-text") && popup.imageUrl;
        const isExp = expanded === popup.id;
        const titleLong = (popup.title||"").replace(/\n/g,"").length > 45;
        const savedPos = !isMobile && positions[popup.id];
        // 위치: 저장된 위치 우선, 없으면 기본 스택
        const posStyle = savedPos
          ? { top: savedPos.top, left: savedPos.left, bottom: "auto", right: "auto" }
          : { bottom: stackBottoms[popup.id] ?? ((isMobile ? 12 : 32) + idx * 320), left: isMobile ? 8 : 32, right: isMobile ? 8 : "auto" };

        return (
          <div
            key={popup.id}
            ref={el => { if (el) boxRefs.current[popup.id] = el; }}
            onMouseDown={!isMobile ? (e => startDrag(e, popup.id)) : undefined}
            className="hlc-popup-box"
            style={{
              position: "fixed", zIndex: 500, ...posStyle,
              background: "var(--card, white)", color: "var(--ink, #1a2238)",
              borderRadius: 18, width: isMobile ? "auto" : 460, overflow: "hidden",
              boxShadow: "0 20px 50px -20px rgba(20,30,60,0.3)",
              animation: "popupSlide .28s ease",
              display: "flex", flexDirection: "column",
              cursor: !isMobile ? "grab" : "default",
              userSelect: "none",
            }}
          >
            {/* 닫기 버튼 */}
            <button onClick={() => close(popup.id)} aria-label="닫기" style={{
              position: "absolute", top: 12, right: 12, zIndex: 2,
              width: 30, height: 30, borderRadius: 999,
              background: "rgba(20,30,60,0.55)", color: "white", border: 0,
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              cursor: "pointer", fontSize: 18, lineHeight: 1,
              backdropFilter: "blur(6px)",
            }}>×</button>

            {/* 콘텐츠 영역 */}
            <div style={{ flex: "0 0 auto", maxHeight: isExp ? 600 : 260, overflow: isExp ? "auto" : "hidden", minHeight: 0, transition: "max-height 0.42s cubic-bezier(0.4,0,0.2,1)" }}>

            {/* 1. 이미지만 */}
            {layout === "image-only" && (
              <div>
                <img src={popup.imageUrl} alt={popup.title} style={{ width: "100%", display: "block", maxHeight: 560, objectFit: "contain", background: "#1a1a1a" }}/>
                {(popup.ctaLabel || popup.title) && (
                  <div style={{ padding: "14px 18px", display: "flex", alignItems: "center", gap: 12 }}>
                    {popup.title && <div style={{ flex: 1, fontSize: 13, fontWeight: 600, color: "var(--ink-2,#3b4358)", whiteSpace: "pre-wrap" }}>{popup.title}</div>}
                    {popup.ctaLabel && popup.ctaUrl && (
                      <button onClick={() => handleCta(popup)} style={{ flexShrink: 0, padding: "6px 14px", borderRadius: 999, background: "var(--ink,#1a2238)", color: "white", border: 0, fontWeight: 700, fontSize: 13, cursor: "pointer" }}>
                        {popup.ctaLabel} →
                      </button>
                    )}
                  </div>
                )}
              </div>
            )}

            {/* 2. 이미지 + 텍스트 */}
            {layout === "image-text" && (
              <div>
                {hasImage ? (
                  <img src={popup.imageUrl} alt={popup.title} style={{ width: "100%", aspectRatio: "16/9", objectFit: "cover", display: "block" }}/>
                ) : (
                  <div style={{ height: 80, background: popupColor(popup.coverColor) }}/>
                )}
                <div style={{ padding: "16px 20px" }}>
                  <div style={{ fontFamily: "var(--font-display)", fontSize: 18, fontWeight: 600, lineHeight: 1.35, marginBottom: 8, whiteSpace: "pre-wrap",
                    ...(isExp ? {} : { overflow: "hidden", display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical" })
                  }}>{popup.title}</div>
                  <div>{renderBody(popup, isExp, titleLong)}</div>
                  {popup.ctaLabel && popup.ctaUrl && (
                    <button onClick={() => handleCta(popup)} style={{ marginTop: 14, padding: "8px 16px", borderRadius: 999, background: "var(--ink,#1a2238)", color: "white", border: 0, fontWeight: 700, fontSize: 13, cursor: "pointer" }}>
                      {popup.ctaLabel} →
                    </button>
                  )}
                </div>
              </div>
            )}

            {/* 3. 텍스트만 */}
            {layout === "text-only" && (
              <div>
                <div style={{ minHeight: 84, background: popupColor(popup.coverColor), padding: "14px 20px 16px", display: "flex", alignItems: "flex-end" }}>
                  <div style={{ fontFamily: "var(--font-display)", fontSize: 18, fontWeight: 600, color: "white", textShadow: "0 1px 4px rgba(0,0,0,0.2)", lineHeight: 1.35, whiteSpace: "pre-wrap",
                    ...(isExp ? {} : { overflow: "hidden", display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical" })
                  }}>
                    {popup.title}
                  </div>
                </div>
                <div style={{ padding: "16px 20px" }}>
                  {renderBody(popup, isExp, titleLong)}
                  {popup.ctaLabel && popup.ctaUrl && (
                    <button onClick={() => handleCta(popup)} style={{ marginTop: 14, padding: "8px 16px", borderRadius: 999, background: "var(--ink,#1a2238)", color: "white", border: 0, fontWeight: 700, fontSize: 13, cursor: "pointer" }}>
                      {popup.ctaLabel} →
                    </button>
                  )}
                </div>
              </div>
            )}

            </div>{/* 콘텐츠 영역 끝 */}

            {/* 공통 푸터 */}
            <div style={{ flexShrink: 0, padding: "10px 20px", borderTop: "1px solid var(--line,#e6e3dc)", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
              <button onClick={() => dontShowToday(popup.id)} style={{ background: "transparent", border: 0, color: "var(--ink-3,#6b7088)", cursor: "pointer", fontSize: 11 }}>
                오늘 하루 보지 않기
              </button>
              <button onClick={() => close(popup.id)} style={{ background: "transparent", border: 0, color: "var(--ink-2,#3b4358)", cursor: "pointer", fontSize: 11, fontWeight: 600 }}>
                닫기
              </button>
            </div>
          </div>
        );
      })}
      <style>{`
        @keyframes popupSlide { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
        @keyframes modalPop { from { opacity: 0; transform: scale(0.86) translateY(24px); } to { opacity: 1; transform: scale(1) translateY(0); } }
        @media (max-width: 640px) {
          .hlc-popup-box { left: 8px !important; right: 8px !important; width: auto !important; }
        }
      `}</style>

    {/* 자세히 보기 모달 */}
    {detailPopup && (
      <div onClick={() => setDetailPopup(null)} style={{
        position: "fixed", inset: 0, zIndex: 600,
        background: "rgba(10,15,40,0.55)", backdropFilter: "blur(4px)",
        display: "flex", alignItems: "center", justifyContent: "center", padding: 24,
      }}>
        <div onClick={e => e.stopPropagation()} style={{
          background: "var(--card, white)", color: "var(--ink, #1a2238)",
          borderRadius: 20, width: "100%", maxWidth: 580,
          boxShadow: "0 30px 80px -20px rgba(10,20,60,0.4)",
          overflow: "hidden", maxHeight: "85vh", display: "flex", flexDirection: "column",
          animation: "modalPop .32s cubic-bezier(0.34, 1.42, 0.64, 1)",
        }}>
          {/* 모달 커버 */}
          {(detailPopup.layout || "text-only") === "text-only" && (
            <div style={{ minHeight: 100, background: popupColor(detailPopup.coverColor), padding: "20px 28px", display: "flex", alignItems: "flex-end" }}>
              <div style={{ fontFamily: "var(--font-display)", fontSize: 24, fontWeight: 500, color: "white", textShadow: "0 1px 4px rgba(0,0,0,0.2)", lineHeight: 1.3, whiteSpace: "pre-wrap" }}>
                {detailPopup.title}
              </div>
            </div>
          )}
          {(detailPopup.layout === "image-text" || detailPopup.layout === "image-only") && detailPopup.imageUrl && (
            <img src={detailPopup.imageUrl} alt={detailPopup.title} style={{ width: "100%", aspectRatio: "16/9", objectFit: "cover", display: "block" }}/>
          )}
          {/* 모달 본문 */}
          <div style={{ padding: "24px 28px", overflowY: "auto", flex: 1 }}>
            {(detailPopup.layout || "text-only") !== "text-only" && (
              <div style={{ fontFamily: "var(--font-display)", fontSize: 22, fontWeight: 500, lineHeight: 1.3, marginBottom: 12, whiteSpace: "pre-wrap" }}>{detailPopup.title}</div>
            )}
            <div style={{ fontSize: 15, lineHeight: 1.8, whiteSpace: "pre-wrap" }}>{renderRichText(detailPopup.body)}</div>
            {detailPopup.ctaLabel && detailPopup.ctaUrl && (
              <button onClick={() => handleCta(detailPopup)} style={{ marginTop: 20, padding: "10px 22px", borderRadius: 999, background: "var(--ink,#1a2238)", color: "white", border: 0, fontWeight: 700, fontSize: 14, cursor: "pointer" }}>
                {detailPopup.ctaLabel} →
              </button>
            )}
          </div>
          {/* 모달 푸터 */}
          <div style={{ padding: "14px 28px", borderTop: "1px solid var(--line,#e6e3dc)", display: "flex", justifyContent: "flex-end" }}>
            <button onClick={() => setDetailPopup(null)} style={{ background: "transparent", border: 0, color: "var(--ink-2,#3b4358)", cursor: "pointer", fontSize: 13, fontWeight: 600 }}>닫기</button>
          </div>
        </div>
      </div>
    )}
    </>
  );
}


const SITE_THEME_KEY = "hlc-site-theme";
function loadAdminTheme() {
  try {
    const raw = localStorage.getItem(SITE_THEME_KEY);
    return raw ? JSON.parse(raw) : null;
  } catch { return null; }
}
function saveAdminTheme(next) {
  try { localStorage.setItem(SITE_THEME_KEY, JSON.stringify(next)); } catch {}
}

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  // 사이트 문구가 Firestore에서 업데이트되면 재렌더
  const [copyVersion, setCopyVersion] = useState(0);
  useEffect(() => {
    const onCopyUpdated = () => setCopyVersion(v => v + 1);
    window.addEventListener('hlc-copy-updated', onCopyUpdated);
    return () => window.removeEventListener('hlc-copy-updated', onCopyUpdated);
  }, []);

  // siteSettings/siteCopy Firestore 실시간 동기화 → localStorage → 재렌더
  useEffect(() => {
    try {
      const unsub = firebase.firestore().collection("siteSettings").doc("siteCopy")
        .onSnapshot(doc => {
          if (!doc.exists) return;
          const data = doc.data();
          let changed = false;
          Object.keys(data).forEach(k => {
            const v = String(data[k]);
            try {
              if (localStorage.getItem('hlc-copy-' + k) !== v) {
                localStorage.setItem('hlc-copy-' + k, v);
                changed = true;
              }
            } catch(e) {}
          });
          if (changed) window.dispatchEvent(new CustomEvent('hlc-copy-updated'));
        }, () => {});
      return () => unsub();
    } catch(e) {}
  }, []);

  // 주보 데이터 Firestore weekly/current → window.CHURCH 실시간 동기화
  const [weeklyVer, setWeeklyVer] = useState(0);
  const [historyVer, setHistoryVer] = useState(0);
  useEffect(() => {
    try {
      const unsub = firebase.firestore().collection("weekly").doc("current")
        .onSnapshot(doc => {
          if (!doc.exists) return;
          const d = doc.data();
          // sundayInfo → thisWeek.date / season
          if (d.sundayInfo) {
            if (d.sundayInfo.date)   window.CHURCH.thisWeek.date   = d.sundayInfo.date;
            if (d.sundayInfo.season) window.CHURCH.thisWeek.season = d.sundayInfo.season;
          }
          // sermon → thisWeek.sermonTitle / scripture 등
          if (d.sermon) {
            if (d.sermon.title)          window.CHURCH.thisWeek.sermonTitle    = d.sermon.title;
            if (d.sermon.titleEn)        window.CHURCH.thisWeek.sermonTitleEn  = d.sermon.titleEn;
            if (d.sermon.scripture)      window.CHURCH.thisWeek.scripture      = d.sermon.scripture;
            if (d.sermon.preacher)       window.CHURCH.thisWeek.preacher       = d.sermon.preacher;
            if (d.sermon.nextMonthTheme) window.CHURCH.thisWeek.nextMonthTheme = d.sermon.nextMonthTheme;
          const _st = d.sermon.scriptureText || d.sermon.excerpt;
          if (_st) window.CHURCH.thisWeek.scriptureText = _st;
          }
          if (d.notices      && d.notices.length)      window.CHURCH.thisWeek.notices = d.notices;
          if (d.weeklyEssay  && d.weeklyEssay.title)   window.CHURCH.weeklyEssay      = d.weeklyEssay;
          if (d.prayerPoints && d.prayerPoints.length) window.CHURCH.prayerPoints     = d.prayerPoints;
          setWeeklyVer(v => v + 1); // 재렌더 트리거
          window.dispatchEvent(new CustomEvent('hlc-weekly-updated')); // ClassicThisWeek 직접 업데이트
        }, () => {});
      return () => unsub();
    } catch(e) {}
  }, []);

  // 교회연혁 Firestore → window.CHURCH.history 실시간 동기화
  useEffect(() => {
    try {
      const unsub = firebase.firestore().collection("siteSettings").doc("siteHistory")
        .onSnapshot(doc => {
          if (doc.exists && doc.data().items && doc.data().items.length > 0) {
            if (window.CHURCH) window.CHURCH.history = doc.data().items;
            setHistoryVer(v => v + 1);
            window.dispatchEvent(new CustomEvent('hlc-history-updated'));
          }
        }, () => {});
      return () => unsub();
    } catch(e) {}
  }, []);

  // 층별 사용공간 Firestore → window.CHURCH.building 실시간 동기화
  const [buildingVer, setBuildingVer] = useState(0);
  useEffect(() => {
    try {
      const unsub = firebase.firestore().collection("siteSettings").doc("building")
        .onSnapshot(doc => {
          if (doc.exists && doc.data().floors && doc.data().floors.length > 0) {
            if (window.CHURCH) window.CHURCH.building = doc.data().floors;
            setBuildingVer(v => v + 1);
          }
        }, () => {});
      return () => unsub();
    } catch(e) {}
  }, []);

  // 관리자가 교인마당에서 저장한 테마·문구를 페이지 진입 시 Firestore에서 로드
  const [adminInit, setAdminInit] = useState(false);
  useEffect(() => {
    if (adminInit) return;
    // 1) localStorage 우선 적용 (즉시)
    const saved = loadAdminTheme();
    if (saved) {
      setTweak({
        typeMode: saved.typeMode || t.typeMode,
        theme:    saved.theme    || t.theme,
        palette:  saved.palette  || t.palette,
        heroExtra:saved.heroExtra|| t.heroExtra,
      });
    }
    setAdminInit(true);

    // 2) Firestore에서 최신 테마 로드
    // localStorage가 없을 때만 Firestore 값을 사용
    // (localStorage가 있으면 관리자가 최근에 저장한 값이므로 우선)
    try {
      firebase.firestore().collection("siteSettings").doc("siteTheme").get()
        .then(doc => {
          if (doc.exists) {
            const d = doc.data();
            const hasLocal = !!localStorage.getItem("hlc-site-theme");
            if (!hasLocal) {
              // localStorage가 없을 때만 Firestore 값 적용
              saveAdminTheme(d);
              setTweak({
                typeMode: d.typeMode || TWEAK_DEFAULTS.typeMode,
                theme:    d.theme    || TWEAK_DEFAULTS.theme,
                palette:  d.palette  || TWEAK_DEFAULTS.palette,
                heroExtra:d.heroExtra|| TWEAK_DEFAULTS.heroExtra,
              });
            }
          }
        }).catch(() => {});
    } catch(e) {}

    // 3) Firestore에서 사이트 문구 동기화
    if (window._loadSiteCopyFromFirestore) {
      window._loadSiteCopyFromFirestore();
    }

    // 다른 탭/창에서 관리자가 변경하면 실시간 반영
    const onStorage = (e) => {
      if (e.key !== SITE_THEME_KEY || !e.newValue) return;
      try {
        const next = JSON.parse(e.newValue);
        setTweak(next);
      } catch {}
    };
    window.addEventListener("storage", onStorage);
    return () => window.removeEventListener("storage", onStorage);
  }, []);

  // 변경시 admin storage에도 반영 (Tweaks 패널 사용시)
  useEffect(() => {
    if (!adminInit) return;
    saveAdminTheme({
      typeMode: t.typeMode, theme: t.theme,
      palette: t.palette, heroExtra: t.heroExtra,
    });
  }, [t.typeMode, t.theme, t.palette, t.heroExtra, adminInit]);

  // sync to body
  useEffect(() => {
    document.body.setAttribute("data-type-mode", t.typeMode);
    document.body.setAttribute("data-theme", t.theme);
    document.body.setAttribute("data-palette", t.palette);
  }, [t.typeMode, t.theme, t.palette]);

  // 시안: B(Blended)로 고정 — A(Classic) / C(Devotional) source는 _alternates/ 에 보관
  const VariantComp = window.VariantBlended;

  return (
    <React.Fragment>
      <div>
        <VariantComp heroExtra={t.heroExtra} copyVersion={copyVersion} weeklyVer={weeklyVer} historyVer={historyVer} buildingVer={buildingVer}/>
      </div>

      <HomepagePopups/>


      {/* Tweaks 패널 */}
      <TweaksPanel title="Tweaks">
        <TweakSection label="히어로 보조 카드">
          <TweakRadio
            label="LIVE 카드 아래 영역"
            value={t.heroExtra}
            onChange={(v) => setTweak({ heroExtra: v })}
            options={[
              { value: "sermon", label: "이번 주 설교" },
              { value: "verse",  label: "말씀 한 구절" },
              { value: "schedule", label: "다가오는 예배" },
              { value: "none", label: "없음" },
            ]}
          />
        </TweakSection>

        <TweakSection label="컬러 팔레트">
          <TweakRadio
            label="톤"
  
            value={t.palette}
            onChange={(v) => setTweak({ palette: v })}
            options={[
              { value: "heallight", label: "맑은빛" },
              { value: "dawn", label: "새벽" },
              { value: "galilee", label: "갈릴리" },
            ]}
          />
          <div style={{ fontFamily: "var(--font-sans)", fontSize: 11, color: "var(--ink-3)", marginTop: 8, lineHeight: 1.55 }}>
            맑은빛(navy·mint) · 새벽(terra·sage) · 갈릴리(teal·gold)
          </div>
        </TweakSection>

        <TweakSection label="타이포그래피">
          <TweakRadio
            label="글꼴 조합"
            value={t.typeMode}
            onChange={(v) => setTweak({ typeMode: v })}
            options={[
              { value: "mixed", label: "혼합" },
              { value: "serif", label: "세리프" },
              { value: "sans", label: "산세리프" },
            ]}
          />
          <div style={{ fontFamily: "var(--font-sans)", fontSize: 11, color: "var(--ink-3)", marginTop: 8, lineHeight: 1.55 }}>
            세리프(Noto Serif KR) · 산세리프(Pretendard)
          </div>
        </TweakSection>

        <TweakSection label="테마">
          <TweakRadio
            label="라이트 / 다크"
            value={t.theme}
            onChange={(v) => setTweak({ theme: v })}
            options={[
              { value: "light", label: "라이트" },
              { value: "dark", label: "다크" },
            ]}
          />
        </TweakSection>
      </TweaksPanel>
    </React.Fragment>
  );
}

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