// 맑은빛 세광교회 — 공유 컴포넌트 & 아이콘
const { useState, useEffect, useRef, useMemo } = React;

// 단순 SVG 아이콘 세트
const Icon = {
  arrow: (p) =>
  <svg viewBox="0 0 24 24" width={p.size || 16} height={p.size || 16} fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" {...p}>
      <path d="M5 12h14M13 6l6 6-6 6" />
    </svg>,

  play: (p) =>
  <svg viewBox="0 0 24 24" width={p.size || 20} height={p.size || 20} fill="currentColor" {...p}>
      <path d="M8 5v14l11-7L8 5z" />
    </svg>,

  youtube: (p) =>
  <svg viewBox="0 0 24 24" width={p.size || 18} height={p.size || 18} fill="currentColor" {...p}>
      <path d="M21.6 7.2a2.5 2.5 0 0 0-1.8-1.8C18.3 5 12 5 12 5s-6.3 0-7.8.4A2.5 2.5 0 0 0 2.4 7.2C2 8.7 2 12 2 12s0 3.3.4 4.8a2.5 2.5 0 0 0 1.8 1.8C5.7 19 12 19 12 19s6.3 0 7.8-.4a2.5 2.5 0 0 0 1.8-1.8c.4-1.5.4-4.8.4-4.8s0-3.3-.4-4.8zM10 15V9l5.2 3L10 15z" />
    </svg>,

  pin: (p) =>
  <svg viewBox="0 0 24 24" width={p.size || 18} height={p.size || 18} fill="none" stroke="currentColor" strokeWidth="1.6" {...p}>
      <path d="M12 21s7-6.2 7-11a7 7 0 1 0-14 0c0 4.8 7 11 7 11z" />
      <circle cx="12" cy="10" r="2.5" />
    </svg>,

  phone: (p) =>
  <svg viewBox="0 0 24 24" width={p.size || 18} height={p.size || 18} fill="none" stroke="currentColor" strokeWidth="1.6" {...p}>
      <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-2z" />
    </svg>,

  clock: (p) =>
  <svg viewBox="0 0 24 24" width={p.size || 18} height={p.size || 18} fill="none" stroke="currentColor" strokeWidth="1.6" {...p}>
      <circle cx="12" cy="12" r="9" /><path d="M12 7v5l3 2" />
    </svg>,

  mail: (p) =>
  <svg viewBox="0 0 24 24" width={p.size || 18} height={p.size || 18} fill="none" stroke="currentColor" strokeWidth="1.6" {...p}>
      <rect x="3" y="5" width="18" height="14" rx="2" /><path d="M3 7l9 6 9-6" />
    </svg>,

  menu: (p) =>
  <svg viewBox="0 0 24 24" width={p.size || 22} height={p.size || 22} fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" {...p}>
      <path d="M4 7h16M4 12h16M4 17h16" />
    </svg>,

  close: (p) =>
  <svg viewBox="0 0 24 24" width={p.size || 22} height={p.size || 22} fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" {...p}>
      <path d="M6 6l12 12M6 18L18 6" />
    </svg>,

  quote: (p) =>
  <svg viewBox="0 0 24 24" width={p.size || 24} height={p.size || 24} fill="currentColor" {...p}>
      <path d="M9 7H5a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h3v1a3 3 0 0 1-3 3v2a5 5 0 0 0 5-5V9a2 2 0 0 0-1-2zm10 0h-4a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h3v1a3 3 0 0 1-3 3v2a5 5 0 0 0 5-5V9a2 2 0 0 0-1-2z" />
    </svg>,

  cross: (p) =>
  <svg viewBox="0 0 24 24" width={p.size || 18} height={p.size || 18} fill="currentColor" {...p}>
      <path d="M10 2h4v7h7v4h-7v9h-4v-9H3V9h7z" />
    </svg>

};

// 교회 로고 — 실제 이미지를 사용 (color prop은 흰색/민트 변형용)
function LogoMark({ color = "var(--primary)", size = 32, ...rest }) {
  const colorStr = typeof color === "string" ? color.toLowerCase() : "";
  const isWhite = colorStr.includes("white") || colorStr === "#fff" || colorStr === "#ffffff" || colorStr.includes("paper") || colorStr.includes("255,255,255");
  const isMint = colorStr.includes("mint");
  const src = isMint ? "assets/logo-mint.png" : "assets/logo-blue.png";
  // 흰색이 필요한 경우(어두운 배경 위)엔 brightness/invert로 컬러 제거
  const filter = isWhite ? "brightness(0) invert(1)" : "none";
  return (
    <img
      src={src}
      alt="맑은빛 세광교회"
      width={size}
      height={size}
      style={{ width: size, height: size, objectFit: "contain", display: "inline-block", filter }}
      {...rest} />);


}

// 텍스트 포함 로고 (이미지) — 변형에 따라 색상 선택
const _LOGO_SEAL_B64 = "data:image/png;base64,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";

function LogoLockup({ variant = "blue", height = 56 }) {
  const aspectRatio = 500 / 523.7;
  const w = Math.round(height * aspectRatio);
  return (
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 523.7"
         width={w} height={height} style={{ display: "block" }}>
      <defs>
        <linearGradient id="hl-leftBeamGrad" x1="1" y1="0.5" x2="0" y2="0.5">
          <stop offset="0%" stopColor="#ffffff" stopOpacity="1"/>
          <stop offset="25%" stopColor="#7fa6c7" stopOpacity="0.8"/>
          <stop offset="65%" stopColor="#517da2" stopOpacity="0.4"/>
          <stop offset="100%" stopColor="#517da2" stopOpacity="0"/>
        </linearGradient>
        <linearGradient id="hl-rightBeamGrad" x1="0" y1="0.5" x2="1" y2="0.5">
          <stop offset="0%" stopColor="#ffffff" stopOpacity="1"/>
          <stop offset="25%" stopColor="#7fa6c7" stopOpacity="0.8"/>
          <stop offset="65%" stopColor="#517da2" stopOpacity="0.4"/>
          <stop offset="100%" stopColor="#517da2" stopOpacity="0"/>
        </linearGradient>
        <radialGradient id="hl-centerGlowGrad" cx="0.5" cy="0.5" r="0.5">
          <stop offset="0%" stopColor="#ffffff" stopOpacity="1"/>
          <stop offset="35%" stopColor="#ffffff" stopOpacity="0.85"/>
          <stop offset="70%" stopColor="#517da2" stopOpacity="0.55"/>
          <stop offset="100%" stopColor="#517da2" stopOpacity="0"/>
        </radialGradient>
        <filter id="hl-glowFilter" x="-50%" y="-50%" width="200%" height="200%">
          <feGaussianBlur stdDeviation="6" result="blur"/>
          <feMerge>
            <feMergeNode in="blur"/>
            <feMergeNode in="SourceGraphic"/>
          </feMerge>
        </filter>
        <style>{`
          @keyframes hl-pulse {
            0%, 100% { transform: scale(1); opacity: 0.45; }
            50% { transform: scale(1.15); opacity: 1; }
          }
          .hl-beam { transform-origin: 380px 145px; animation: hl-pulse 6s infinite ease-in-out; }
          .hl-glow  { transform-origin: 380px 145px; animation: hl-pulse 6s infinite ease-in-out; }
        `}</style>
      </defs>
      <g className="hl-beam" opacity="0.78">
        <polygon points="380,145 110,100 110,190" fill="url(#hl-leftBeamGrad)"/>
        <polygon points="380,145 465,130 465,160" fill="url(#hl-rightBeamGrad)"/>
      </g>
      <circle className="hl-glow" cx="380" cy="145" r="22"
              fill="url(#hl-centerGlowGrad)" filter="url(#hl-glowFilter)" opacity="0.78"/>
      <rect x="371" y="70" width="18" height="65" fill="#517da2"/>
      <rect x="371" y="155" width="18" height="155" fill="#517da2"/>
      <polygon points="120,310 250,180 360,310 335,310 250,205 145,310" fill="#517da2"/>
      <image x="0" y="320" width="500" height="203.7"
             href={_LOGO_SEAL_B64}/>
    </svg>
  );
}

// ───────────────────────────────────────────────────────────
// 약도 (SVG · 신촌·대흥동) — 건물 일러스트 버전
// ───────────────────────────────────────────────────────────
// 사용자 손그림 다이어그램(2026.5) 구조 + 입면 일러스트 건물.
// - 도로 골격: 가로 큰길(신촌기차역입구 교차로) + 가로 작은길 + 세로 신촌로26길
// - 건물이 도로에 바로 인접 (사용자 요구사항)
// - 건물은 평면 박스가 아닌 입면(facade) 일러스트:
//   옥상 라인, 창문 그리드, 1층 입구, 사이드 그라데이션
// - 교회 = 노란 본체 + 다크 타워(흰 십자가) + 벽돌 베이스 (실제 건물 모티프)
// - 마포 그랑자이 = 슬림 아파트 타워 3채 (옥상 물탱크 + 다창)
// - 라벨은 SVG 텍스트 — 수정·번역 자유
//
// props:
//   rounded   : 모서리 반경 (px)
//   bordered  : 외곽선 (부모가 카드면 false)

// 건물 팔레트
const _bldPalette = {
  beige: { bg: "#f4ecd5", side: "#c2b485", roof: "#a89770", text: "#3c3424", sub: "#7a6f4f", win: "#7a8aa3" },
  gray:  { bg: "#e6e2d9", side: "#bfb9a9", roof: "#9a9486", text: "#3c3a32", sub: "#74705f", win: "#8a8a92" },
  blue:  { bg: "#dde6f0", side: "#aebbcc", roof: "#7e8da2", text: "#33405a", sub: "#65718a", win: "#6f819c" },
  sage:  { bg: "#dfe6dc", side: "#a6b3a2", roof: "#7d8b7a", text: "#314037", sub: "#5b6a5d", win: "#67786f" },
};

// 일반 건물 입면 (마포복지관·주민센터·피부과 등)
function MapBldg({ x, y, width, height, stories = 3, winCols = 3, label, sublabel, tone = "beige", roofDetail = true, entrance = true }) {
  const p = _bldPalette[tone] || _bldPalette.beige;
  const padX = width * 0.10;
  const padTop = height * 0.14;
  const padBot = entrance ? height * 0.18 : height * 0.08;
  const winAreaW = width - padX * 2;
  const winAreaH = height - padTop - padBot;
  const winGapX = winAreaW * 0.06;
  const winW = (winAreaW - winGapX * (winCols - 1)) / winCols;
  const winGapY = winAreaH / stories * 0.30;
  const winH = winAreaH / stories - winGapY;

  return (
    <g transform={`translate(${x}, ${y})`} filter="url(#bldShadow)">
      {/* 사이드 그림자 (낮은 측면) */}
      <rect x="-2" y="2" width={width + 4} height={height} rx="2" fill={p.side} opacity="0.5" />
      {/* 본체 */}
      <rect x="0" y="0" width={width} height={height} rx="2" fill={p.bg} stroke={p.side} strokeWidth="1.1" />
      {/* 옥상 — 본체 위 옅은 띠 + 옥상 디테일 */}
      <rect x="-1.5" y="-3.5" width={width + 3} height="4.5" rx="1" fill={p.roof} />
      {roofDetail && (
        <g>
          {/* 옥상 가장자리 패러핏 */}
          <rect x="3" y="1.5" width={width - 6} height="3" fill={p.side} opacity="0.5" />
          {/* 옥상 기계실 / 물탱크 */}
          <rect x={width * 0.62} y={-1.5} width={width * 0.22} height="5" fill={p.roof} opacity="0.85" />
        </g>
      )}
      {/* 창문 그리드 */}
      {Array.from({ length: stories }).map((_, r) =>
        Array.from({ length: winCols }).map((__, c) => (
          <rect
            key={`${r}-${c}`}
            x={padX + c * (winW + winGapX)}
            y={padTop + r * (winH + winGapY)}
            width={winW}
            height={winH}
            fill={p.win}
            opacity={0.42}
            rx="0.5"
          />
        ))
      )}
      {/* 1층 입구 */}
      {entrance && (
        <g>
          <rect x={width * 0.42} y={height - padBot * 0.85} width={width * 0.16} height={padBot * 0.75} fill={p.side} opacity="0.8" rx="1" />
          <rect x={width * 0.42} y={height - padBot * 0.85} width={width * 0.16} height={padBot * 0.18} fill={p.roof} opacity="0.9" />
        </g>
      )}
      {/* 라벨 */}
      {label && (
        <text
          x={width / 2}
          y={height / 2 + (sublabel ? -2 : 4)}
          textAnchor="middle"
          fill={p.text}
          fontSize={width > 140 ? 12 : 11}
          fontWeight="700"
          style={{ paintOrder: "stroke", stroke: p.bg, strokeWidth: 3 }}
        >
          {label}
        </text>
      )}
      {sublabel && (
        <text
          x={width / 2}
          y={height / 2 + 12}
          textAnchor="middle"
          fill={p.sub}
          fontSize="10"
          fontWeight="500"
          style={{ paintOrder: "stroke", stroke: p.bg, strokeWidth: 3 }}
        >
          {sublabel}
        </text>
      )}
    </g>
  );
}

// 아파트 타워 (그랑자이용) — 슬림 + 옥상 물탱크 + 다창
function ApartmentTower({ x, y, width, height, stories = 14, tone = "blue" }) {
  const p = _bldPalette[tone] || _bldPalette.blue;
  const padX = width * 0.14;
  const padTop = height * 0.10;
  const padBot = height * 0.07;
  const winAreaW = width - padX * 2;
  const winAreaH = height - padTop - padBot;
  const winCols = 2;
  const winGapX = winAreaW * 0.18;
  const winW = (winAreaW - winGapX) / winCols;
  const winGapY = winAreaH / stories * 0.36;
  const winH = winAreaH / stories - winGapY;

  return (
    <g transform={`translate(${x}, ${y})`} filter="url(#bldShadow)">
      <rect x="-1.5" y="2" width={width + 3} height={height} rx="2" fill={p.side} opacity="0.45" />
      <rect x="0" y="0" width={width} height={height} rx="2" fill={p.bg} stroke={p.side} strokeWidth="1" />
      {/* 옥상 + 물탱크 */}
      <rect x="-1" y="-3" width={width + 2} height="4" rx="1" fill={p.roof} />
      <rect x={width * 0.30} y={-8} width={width * 0.40} height="6" rx="1.5" fill={p.roof} />
      <rect x={width * 0.34} y={-10} width={width * 0.32} height="3" rx="1" fill={p.side} opacity="0.7" />
      {/* 창문 그리드 */}
      {Array.from({ length: stories }).map((_, r) =>
        Array.from({ length: winCols }).map((__, c) => (
          <rect
            key={`${r}-${c}`}
            x={padX + c * (winW + winGapX)}
            y={padTop + r * (winH + winGapY)}
            width={winW}
            height={winH}
            fill={p.win}
            opacity={0.5}
            rx="0.4"
          />
        ))
      )}
      {/* 1층 입구(작게) */}
      <rect x={width * 0.40} y={height - padBot - 4} width={width * 0.20} height="4" fill={p.side} opacity="0.8" rx="0.5" />
    </g>
  );
}

// 교회 건물 — 실제 건물 모티프 (노란 본체 + 다크 타워 + 흰 십자가 + 벽돌 베이스)
function ChurchBldg({ x, y, width, height }) {
  const inset = width * 0.05;
  const usableW = width - inset * 2;
  const towerW = usableW * 0.32;
  const bodyW = usableW - towerW;
  const baseH = height * 0.16;
  const bodyFill = "#fbe8a8";
  const bodyHi = "#fef0c4";
  const towerFill = "#4d4d52";
  const towerSide = "#3a3a3e";
  const bodyStroke = "#cdb56a";
  const brick = "#9c5440";
  const brickDark = "#7a3a2a";
  const win = "#4a5e7a";

  return (
    <g transform={`translate(${x + inset}, ${y})`}>
      {/* 옅은 글로우 — 강조 */}
      <ellipse cx={usableW / 2} cy={height / 2} rx={usableW * 0.85} ry={height * 0.65} fill="var(--mint-deep)" opacity="0.10" />

      <g filter="url(#bldShadow)">
        {/* 노란 본체 */}
        <rect x="0" y="0" width={bodyW} height={height} rx="2" fill={bodyFill} stroke={bodyStroke} strokeWidth="1.1" />
        <rect x="0" y="0" width={bodyW} height={height * 0.22} rx="2" fill={bodyHi} opacity="0.55" />
        {/* 본체 창문 슬릿 */}
        {[0.24, 0.40, 0.56, 0.72].map((yPct, i) => (
          <rect key={i} x={bodyW * 0.16} y={height * yPct} width={bodyW * 0.58} height={height * 0.055} fill={win} opacity="0.55" rx="0.8" />
        ))}

        {/* 다크 타워 (우측) */}
        <rect x={bodyW - 1} y={-height * 0.06} width={towerW + 1} height={height + height * 0.06} rx="2" fill={towerFill} stroke={towerSide} strokeWidth="1.1" />
        {/* 타워 정면 흰 십자가 */}
        <rect x={bodyW + towerW / 2 - 2.5} y={height * 0.18} width={5} height={height * 0.50} fill="#ffffff" rx="0.5" />
        <rect x={bodyW + towerW / 2 - towerW * 0.32} y={height * 0.34} width={towerW * 0.64} height={5} fill="#ffffff" rx="0.5" />

        {/* 1층 벽돌 베이스 */}
        <rect x="0" y={height - baseH} width={bodyW} height={baseH} fill={brick} stroke={brickDark} strokeWidth="0.5" />
        <line x1="0" y1={height - baseH * 0.66} x2={bodyW} y2={height - baseH * 0.66} stroke={brickDark} strokeWidth="0.4" opacity="0.55" />
        <line x1="0" y1={height - baseH * 0.33} x2={bodyW} y2={height - baseH * 0.33} stroke={brickDark} strokeWidth="0.4" opacity="0.55" />

        {/* 1층 입구 (어두운 유리문) */}
        <rect x={bodyW * 0.42} y={height - baseH * 0.92} width={bodyW * 0.22} height={baseH * 0.88} fill={towerFill} stroke={brickDark} strokeWidth="0.5" />
        <line x1={bodyW * 0.53} y1={height - baseH * 0.92} x2={bodyW * 0.53} y2={height - baseH * 0.05} stroke="#ffffff" strokeWidth="0.5" opacity="0.6" />
      </g>
    </g>
  );
}

function IllustratedMap({ rounded = 0, bordered = false, style = {}, className = "" }) {
  return (
    <div
      className={className}
      style={{
        position: "absolute",
        inset: 0,
        overflow: "hidden",
        borderRadius: rounded,
        border: bordered ? "1px solid var(--line)" : "none",
        background: "var(--paper)",
        ...style,
      }}
      role="img"
      aria-label="맑은빛 세광교회 약도 — 2호선 신촌역(5번 출구)과 이대역(6번 출구) 사이, 신촌로26길의 우리마포복지관·대흥동 주민센터 맞은편. 이대역 6번 출구에서 약 250m, 도보 3분."
    >
      <svg
        viewBox="0 0 800 450"
        width="100%"
        height="100%"
        preserveAspectRatio="xMidYMid meet"
        style={{ display: "block", fontFamily: "var(--font-sans)" }}
      >
        <defs>
          <pattern id="mapDots" width="22" height="22" patternUnits="userSpaceOnUse">
            <circle cx="2" cy="2" r="0.7" fill="rgba(61,93,140,0.07)" />
          </pattern>
          <filter id="bldShadow" x="-30%" y="-30%" width="160%" height="160%">
            <feDropShadow dx="1" dy="2.5" stdDeviation="2.2" floodColor="#1a2238" floodOpacity="0.20" />
          </filter>
          <filter id="mapSoftShadow" x="-50%" y="-50%" width="200%" height="200%">
            <feDropShadow dx="0" dy="2" stdDeviation="2.5" floodColor="#1a2238" floodOpacity="0.16" />
          </filter>
        </defs>

        {/* 배경 */}
        <rect width="800" height="450" fill="var(--paper)" />
        <rect width="800" height="450" fill="url(#mapDots)" />

        {/* ─── 도로 골격 ─── */}
        {/* 가로 큰길 — 신촌기차역입구 교차로 */}
        <rect x="0" y="42" width="800" height="48" fill="#d9d4c6" />
        <line x1="0" y1="42" x2="800" y2="42" stroke="#b6af9d" strokeWidth="1.2" />
        <line x1="0" y1="90" x2="800" y2="90" stroke="#b6af9d" strokeWidth="1.2" />
        {/* 큰길 중앙선 (점선) */}
        <line x1="0" y1="66" x2="340" y2="66" stroke="#fff" strokeWidth="1.6" strokeDasharray="10 8" opacity="0.85" />
        <line x1="460" y1="66" x2="800" y2="66" stroke="#fff" strokeWidth="1.6" strokeDasharray="10 8" opacity="0.85" />

        {/* 세로 도로 — 신촌로26길 */}
        <rect x="340" y="42" width="44" height="408" fill="#d9d4c6" />
        <line x1="340" y1="90" x2="340" y2="450" stroke="#b6af9d" strokeWidth="1.2" />
        <line x1="384" y1="90" x2="384" y2="450" stroke="#b6af9d" strokeWidth="1.2" />
        <line x1="362" y1="90" x2="362" y2="220" stroke="#fff" strokeWidth="1.4" strokeDasharray="8 6" opacity="0.85" />
        <line x1="362" y1="252" x2="362" y2="450" stroke="#fff" strokeWidth="1.4" strokeDasharray="8 6" opacity="0.85" />

        {/* 가로 작은길 */}
        <rect x="0" y="220" width="340" height="32" fill="#d9d4c6" />
        <rect x="384" y="220" width="416" height="32" fill="#d9d4c6" />
        <line x1="0" y1="220" x2="340" y2="220" stroke="#b6af9d" strokeWidth="1" />
        <line x1="0" y1="252" x2="340" y2="252" stroke="#b6af9d" strokeWidth="1" />
        <line x1="384" y1="220" x2="800" y2="220" stroke="#b6af9d" strokeWidth="1" />
        <line x1="384" y1="252" x2="800" y2="252" stroke="#b6af9d" strokeWidth="1" />

        {/* ─── 도로명 ─── */}
        <text x="362" y="35" textAnchor="middle" fontSize="10.5" fill="var(--ink-3)" fontWeight="500" letterSpacing="0.04em">
          신촌기차역입구 교차로
        </text>
        <text transform="translate(362, 380) rotate(-90)" textAnchor="middle" fontSize="10.5" fill="var(--ink-3)" fontWeight="500" letterSpacing="0.08em">
          신촌로 26길
        </text>

        {/* ─── 지하철역 라벨 (큰길 위) ─── */}
        <g transform="translate(120, 22)">
          <rect x="-92" y="-16" width="184" height="22" rx="4" fill="var(--primary)" filter="url(#mapSoftShadow)" />
          <circle cx="-70" cy="-5" r="9" fill="none" stroke="#fff" strokeWidth="1.5" />
          <text x="-70" y="-1" fontSize="11.5" fontWeight="700" fill="#fff" textAnchor="middle">2</text>
          <text x="13" y="0" fontSize="12" fontWeight="700" fill="#fff" textAnchor="middle">신촌역 5번출구</text>
        </g>
        <g transform="translate(680, 22)">
          <rect x="-92" y="-16" width="184" height="22" rx="4" fill="var(--primary)" filter="url(#mapSoftShadow)" />
          <circle cx="-70" cy="-5" r="9" fill="none" stroke="#fff" strokeWidth="1.5" />
          <text x="-70" y="-1" fontSize="11.5" fontWeight="700" fill="#fff" textAnchor="middle">2</text>
          <text x="13" y="0" fontSize="12" fontWeight="700" fill="#fff" textAnchor="middle">이대역 6번출구</text>
        </g>

        {/* ─── 동선 화살표 (이대역 → 교회) ─── */}
        <path
          d="M 580 90 Q 480 90 405 90 Q 380 90 380 130 L 380 230"
          fill="none"
          stroke="var(--mint-deep)"
          strokeWidth="2.4"
          strokeDasharray="6 5"
          strokeLinecap="round"
          opacity="0.85"
        />

        {/* ─── 건물 ─── */}
        {/* 큰길 바로 아래 (도로 인접) */}
        <MapBldg x={228} y={92} width={128} height={120} stories={5} winCols={3} label="어썸 피부과" sublabel="의원" tone="gray" />
        <MapBldg x={400} y={92} width={128} height={120} stories={6} winCols={3} label="서희 스타힐스" tone="blue" />

        {/* 작은길 아래 — 좌측 (마포복지관 + 주민센터) */}
        <MapBldg x={140} y={258} width={220} height={78} stories={3} winCols={5} label="우리 마포복지관" tone="beige" />
        <MapBldg x={180} y={350} width={180} height={66} stories={2} winCols={4} label="대흥동 주민센터" tone="gray" />

        {/* 작은길 아래 — 우측 (★ 교회) */}
        <ChurchBldg x={400} y={258} width={134} height={138} />

        {/* 마포 그랑자이 — 슬림 아파트 3채 */}
        <ApartmentTower x={560} y={278} width={64} height={130} stories={11} tone="blue" />
        <ApartmentTower x={638} y={266} width={64} height={142} stories={12} tone="blue" />
        <ApartmentTower x={716} y={278} width={64} height={130} stories={11} tone="blue" />
        <text x={638} y={428} textAnchor="middle" fontSize="11.5" fontWeight="700" fill="var(--ink-2)" letterSpacing="0.02em">
          마포 그랑자이 아파트
        </text>

        {/* ─── 교회 핀 + 라벨 ─── */}
        <g transform="translate(467, 242)" filter="url(#mapSoftShadow)">
          <circle r="9" fill="#fff" stroke="var(--mint-deep)" strokeWidth="2.5" />
          <circle r="3.5" fill="var(--mint-deep)" />
        </g>
        <g transform="translate(467, 410)">
          <rect x="-58" y="-13" width="116" height="22" rx="11" fill="var(--mint-deep)" filter="url(#mapSoftShadow)" />
          <text x="0" y="3" textAnchor="middle" fontSize="11.5" fontWeight="700" fill="#fff">
            맑은빛 세광교회
          </text>
        </g>

        {/* ─── 나침반 + 스케일바 (좌하단) ─── */}
        <g transform="translate(38, 412)">
          <circle r="15" fill="#fff" stroke="#b6af9d" strokeWidth="1.1" filter="url(#mapSoftShadow)" />
          <path d="M0 -9 L3 0 L0 9 L-3 0 Z" fill="var(--primary)" />
          <path d="M0 -9 L3 0 L-3 0 Z" fill="#c84c4c" />
          <text y="-17" textAnchor="middle" fontSize="8.5" fontWeight="700" fill="var(--ink-2)">N</text>
        </g>
        <g transform="translate(70, 422)">
          <line x1="0" y1="0" x2="56" y2="0" stroke="var(--ink-2)" strokeWidth="1.3" />
          <line x1="0" y1="-3" x2="0" y2="3" stroke="var(--ink-2)" strokeWidth="1.3" />
          <line x1="28" y1="-3" x2="28" y2="3" stroke="var(--ink-2)" strokeWidth="1.3" />
          <line x1="56" y1="-3" x2="56" y2="3" stroke="var(--ink-2)" strokeWidth="1.3" />
          <text x="0" y="14" fontSize="8.5" fill="var(--ink-3)" fontWeight="500">0</text>
          <text x="56" y="14" textAnchor="end" fontSize="8.5" fill="var(--ink-3)" fontWeight="500">100m</text>
        </g>
      </svg>
    </div>
  );
}

// ───────────────────────────────────────────────────────────
// 약도 (카카오맵 SDK 임베드)
// ───────────────────────────────────────────────────────────
// 카카오 개발자 콘솔에서 발급받은 JavaScript 키 (도메인 화이트리스트로 보호됨)
const KAKAO_APPKEY = "60b1c3f06b8a8f5d6fd312938768b122";

// SDK 로더 — 페이지당 한 번만 로드되도록 싱글톤 프로미스 사용
let _kakaoMapsPromise = null;
function _loadKakaoMaps() {
  if (_kakaoMapsPromise) return _kakaoMapsPromise;
  _kakaoMapsPromise = new Promise((resolve, reject) => {
    // 12초 타임아웃 — 모바일에서 SDK가 로드됐지만 콜백이 안 오는 케이스 방지
    const timer = setTimeout(() => {
      _kakaoMapsPromise = null; // 다음 재시도 허용
      reject(new Error("Kakao Maps SDK timeout"));
    }, 12000);
    const done = (fn) => (...args) => { clearTimeout(timer); fn(...args); };

    if (window.kakao && window.kakao.maps && window.kakao.maps.LatLng) {
      clearTimeout(timer);
      return resolve(window.kakao);
    }
    const handleLoaded = () => {
      if (window.kakao && window.kakao.maps) {
        window.kakao.maps.load(done(() => resolve(window.kakao)));
      } else {
        done(reject)(new Error("kakao.maps unavailable after load"));
      }
    };
    const existing = document.getElementById("kakao-maps-sdk");
    if (existing) {
      if (existing.dataset.loaded === "true") {
        handleLoaded();
      } else {
        existing.addEventListener("load", handleLoaded);
        existing.addEventListener("error", done(() => reject(new Error("SDK script failed"))));
      }
      return;
    }
    const script = document.createElement("script");
    script.id = "kakao-maps-sdk";
    script.src = "https://dapi.kakao.com/v2/maps/sdk.js?appkey=" + KAKAO_APPKEY + "&autoload=false";
    script.async = true;
    script.onload = () => { script.dataset.loaded = "true"; handleLoaded(); };
    script.onerror = done(() => reject(new Error("SDK script failed")));
    document.head.appendChild(script);
  });
  return _kakaoMapsPromise;
}

// 좌표 — 교회는 실측값, 지하철역은 카카오맵 공식 좌표
const _LOC = {
  church:  { lat: 37.556002, lng: 126.943073, label: "맑은빛 세광교회" },
  sinchon: { lat: 37.5556, lng: 126.9367, label: "신촌역 5번 출구" },
  ewha:    { lat: 37.5567, lng: 126.9462, label: "이대역 6번 출구" },
};

function KakaoEmbedMap({ rounded = 0, bordered = false, style = {}, className = "" }) {
  const containerRef = useRef(null);
  const mapRef = useRef(null);
  const [status, setStatus] = useState("loading"); // loading | ready | error

  useEffect(() => {
    let cancelled = false;
    _loadKakaoMaps()
      .then((kakao) => {
        if (cancelled || !containerRef.current) return;

        const churchPos  = new kakao.maps.LatLng(_LOC.church.lat,  _LOC.church.lng);
        const sinchonPos = new kakao.maps.LatLng(_LOC.sinchon.lat, _LOC.sinchon.lng);
        const ewhaPos    = new kakao.maps.LatLng(_LOC.ewha.lat,    _LOC.ewha.lng);

        const map = new kakao.maps.Map(containerRef.current, {
          center: churchPos,
          level: 4,
        });
        mapRef.current = map;

          // 영역 자동 조정 (3점 다 보이게) — 초기 줌·센터를 항상 동일하게 고정
          const bounds = new kakao.maps.LatLngBounds();
          bounds.extend(churchPos); bounds.extend(sinchonPos); bounds.extend(ewhaPos);
          map.setBounds(bounds, 60, 70, 70, 60);

          // 줌 컨트롤 (사용자는 줌·드래그 자유롭게 가능)
          map.addControl(new kakao.maps.ZoomControl(), kakao.maps.ControlPosition.RIGHT);

          // 도보 경로 — 이대역 → 교회 (강조 점선 mint-deep)
          new kakao.maps.Polyline({
            map, path: [ewhaPos, churchPos],
            strokeWeight: 5, strokeColor: "#4ea49f", strokeOpacity: 0.92, strokeStyle: "dash",
          });
          // 도보 경로 — 신촌역 → 교회 (보조 점선 navy)
          new kakao.maps.Polyline({
            map, path: [sinchonPos, churchPos],
            strokeWeight: 3.5, strokeColor: "#3d5d8c", strokeOpacity: 0.55, strokeStyle: "shortdash",
          });

          // 지하철역 칩
          const subwayChip = (label) =>
            '<div style="background:#3d5d8c;color:#fff;padding:5px 11px;border-radius:999px;'
            + 'font:700 11.5px/1.2 \'Pretendard\',-apple-system,sans-serif;'
            + 'box-shadow:0 4px 12px rgba(20,30,60,0.18);white-space:nowrap;'
            + 'transform:translateY(-26px);"><span style="margin-right:4px">🚇</span>' + label + '</div>';
          new kakao.maps.CustomOverlay({
            map, position: sinchonPos, content: subwayChip("신촌역 5번 출구"),
            xAnchor: 0.5, yAnchor: 1, zIndex: 3,
          });
          new kakao.maps.CustomOverlay({
            map, position: ewhaPos, content: subwayChip("이대역 6번 출구"),
            xAnchor: 0.5, yAnchor: 1, zIndex: 3,
          });

          // 교회 — 강조 핀
          const churchPin =
            '<div style="position:relative;transform:translateY(-44px);'
            + 'font-family:\'Pretendard\',-apple-system,sans-serif;">'
            + '<div style="background:#4ea49f;color:#fff;padding:7px 14px 7px 10px;border-radius:999px;'
            + 'font-weight:800;font-size:13px;box-shadow:0 8px 22px rgba(20,30,60,0.28);'
            + 'white-space:nowrap;display:inline-flex;align-items:center;gap:6px;border:2px solid #fff;">'
            + '<span style="display:inline-flex;align-items:center;justify-content:center;'
            + 'width:18px;height:18px;background:#fff;border-radius:50%;color:#4ea49f;'
            + 'font-size:11px;font-weight:900;line-height:1;">✚</span>'
            + '맑은빛 세광교회</div>'
            + '<div style="position:absolute;left:50%;bottom:-9px;width:0;height:0;'
            + 'border-left:8px solid transparent;border-right:8px solid transparent;'
            + 'border-top:10px solid #4ea49f;transform:translateX(-50%);'
            + 'filter:drop-shadow(0 3px 3px rgba(20,30,60,0.16));"></div>'
            + '</div>';
          new kakao.maps.CustomOverlay({
            map, position: churchPos, content: churchPin,
            xAnchor: 0.5, yAnchor: 1, zIndex: 5,
          });

          // 도보 시간 인포 — 이대역 경로 중간 (해소된 실제 좌표 사용)
          const midPos = new kakao.maps.LatLng(
            (ewhaPos.getLat() + churchPos.getLat()) / 2,
            (ewhaPos.getLng() + churchPos.getLng()) / 2
          );
          new kakao.maps.CustomOverlay({
            map, position: midPos,
            content:
              '<div style="background:#1a2238;color:#fff;padding:4px 10px;border-radius:999px;'
              + 'font:700 10.5px/1.3 \'Pretendard\',-apple-system,sans-serif;'
              + 'box-shadow:0 4px 12px rgba(0,0,0,0.22);white-space:nowrap;">'
              + '약 250m · 도보 3분</div>',
            xAnchor: 0.5, yAnchor: 0.5, zIndex: 4,
          });

          setStatus("ready");
      })
      .catch((e) => {
        if (!cancelled) {
          console.warn("Kakao map load failed:", e);
          setStatus("error");
        }
      });
    return () => { cancelled = true; };
  }, []);

  return (
    <div
      className={className}
      style={{
        position: "absolute",
        inset: 0,
        overflow: "hidden",
        borderRadius: rounded,
        border: bordered ? "1px solid var(--line)" : "none",
        background: "var(--paper-2)",
        ...style,
      }}
      role="img"
      aria-label="맑은빛 세광교회 위치 카카오맵 — 2호선 이대역 6번 출구에서 약 250m, 도보 3분"
    >
      <div ref={containerRef} style={{ width: "100%", height: "100%" }} />
      {status !== "ready" && (
        <div style={{
          position: "absolute", inset: 0,
          display: "flex", flexDirection: "column",
          alignItems: "center", justifyContent: "center",
          background: "var(--paper-2)",
          color: "var(--ink-2)", fontFamily: "var(--font-sans)",
          fontSize: 13, gap: 12, padding: 20, textAlign: "center",
        }}>
          {status === "loading" ? (
            <React.Fragment>
              <div style={{
                width: 28, height: 28, borderRadius: 999,
                border: "3px solid var(--line)", borderTopColor: "var(--primary)",
                animation: "kakaoSpin 0.9s linear infinite",
              }} />
              <div>지도 불러오는 중…</div>
            </React.Fragment>
          ) : (
            <React.Fragment>
              <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="var(--ink-3)" strokeWidth="1.8" strokeLinecap="round">
                <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/>
              </svg>
              <div style={{ fontWeight: 700, color: "var(--ink)", fontSize: 14 }}>지도를 불러올 수 없습니다</div>
              <div style={{ fontSize: 12, color: "var(--ink-3)", maxWidth: 260, lineHeight: 1.6, textAlign: "center" }}>
                서울 마포구 신촌로26길 11<br/>맑은빛 세광교회
              </div>
              <a
                href={"https://map.kakao.com/?q=" + encodeURIComponent("서울 마포구 신촌로26길 11")}
                target="_blank" rel="noopener noreferrer"
                style={{
                  marginTop: 4, padding: "8px 18px",
                  background: "#fee500", color: "#3c1e1e",
                  borderRadius: 999, textDecoration: "none",
                  fontSize: 13, fontWeight: 700,
                  display: "inline-flex", alignItems: "center", gap: 6
                }}
              ><span>🗺</span> 카카오맵에서 보기</a>
            </React.Fragment>
          )}
        </div>
      )}
      <style>{"@keyframes kakaoSpin { to { transform: rotate(360deg); } }"}</style>
    </div>
  );
}

// 인라인 svg 십자가 모티프 배경 (장식용)
function CrossPattern({ color = "currentColor", opacity = 0.06 }) {
  return (
    <svg width="100%" height="100%" style={{ position: "absolute", inset: 0, opacity }} aria-hidden="true">
      <defs>
        <pattern id="cp" width="80" height="80" patternUnits="userSpaceOnUse" patternTransform="rotate(0)">
          <path d="M37 14h6v18h18v6H43v18h-6V38H19v-6h18z" fill={color} />
        </pattern>
      </defs>
      <rect width="100%" height="100%" fill="url(#cp)" />
    </svg>);

}

// 사진 자리 — 변형(variant) 별로 스타일 변화
function PhotoSlot({ label, ratio = "4/3", mode = "stripe", className = "", style = {}, accent = "primary" }) {
  // mode: stripe | gradient | mono | graphic
  const baseStyle = {
    aspectRatio: ratio,
    position: "relative",
    borderRadius: 4,
    overflow: "hidden",
    color: "rgba(255,255,255,0.92)",
    fontFamily: "ui-monospace, monospace",
    fontSize: 12,
    display: "flex",
    alignItems: "flex-end",
    padding: 14,
    ...style
  };
  if (mode === "stripe") {
    return (
      <div className={className} style={{
        ...baseStyle,
        background: "repeating-linear-gradient(135deg, var(--paper-2) 0 14px, var(--paper-3) 14px 28px)",
        color: "var(--ink-3)",
        border: "1px solid var(--line)"
      }}>
        <span>[ {label} ]</span>
      </div>);

  }
  if (mode === "gradient") {
    const grad = accent === "mint" ?
    "linear-gradient(135deg, #b6dedb 0%, #7fc1be 40%, #3d5d8c 100%)" :
    "linear-gradient(135deg, #6c8ab8 0%, #3d5d8c 60%, #1a2238 100%)";
    return (
      <div className={className} style={{ ...baseStyle, background: grad }}>
        <span style={{ color: "rgba(255,255,255,0.85)" }}>{label}</span>
      </div>);

  }
  if (mode === "mono") {
    return (
      <div className={className} style={{
        ...baseStyle,
        background: "var(--paper-3)",
        color: "var(--ink-3)"
      }}>
        <span>{label}</span>
      </div>);

  }
  if (mode === "graphic") {
    return (
      <div className={className} style={{
        ...baseStyle,
        background: accent === "mint" ? "var(--mint)" : "var(--primary)",
        color: "white"
      }}>
        <div style={{ position: "absolute", inset: 0, opacity: 0.55 }}>
          <svg viewBox="0 0 200 200" preserveAspectRatio="none" width="100%" height="100%">
            <defs>
              <pattern id={`gp-${label}`} width="40" height="40" patternUnits="userSpaceOnUse">
                <path d="M0 30 L20 10 L40 30" fill="none" stroke="rgba(255,255,255,0.5)" strokeWidth="1.2" />
                <path d="M19 4h2v6h6v2h-6v6h-2v-6h-6v-2h6z" fill="rgba(255,255,255,0.7)" />
              </pattern>
            </defs>
            <rect width="200" height="200" fill={`url(#gp-${label})`} />
          </svg>
        </div>
        <span style={{ position: "relative", zIndex: 2 }}>{label}</span>
      </div>);

  }
  return null;
}

// 섹션 헤더 (장식적 변형 가능)
function SectionTitle({ eyebrow, title, en, align = "left", style = {} }) {
  return (
    <header style={{ textAlign: align, marginBottom: 40, ...style }}>
      {eyebrow && <div className="eyebrow" style={{ marginBottom: 12 }}>{eyebrow}</div>}
      <h2 style={{ fontSize: "clamp(28px, 3.8vw, 44px)", fontWeight: 600, margin: 0, lineHeight: 1.2 }}>{title}</h2>
      {en && <div style={{ fontFamily: "var(--font-sans)", color: "var(--ink-3)", marginTop: 8, letterSpacing: "0.04em", fontSize: 13 }}>{en}</div>}
    </header>);

}

// 유튜브 API 설정
const YT_API_KEY = "AIzaSyB-1a3M7960mnKTuZekDYGDBql-h0_McVM";
const YT_CHANNEL_ID = "UC3MZB8Efn04qMdPLFb4_lxg";
const YT_PLAYLIST = {
  sunday: "PL_Cy6o-44syAQC6P3moBd-OF7XpTSOuYt",   // 주일예배설교
  morning: "PL_Cy6o-44syDe5i5zPU-2Z5gLQrVLNnKp",  // 아침예배
  wednesday: "PL_Cy6o-44syCgIzInp41noLRV9lTRqTZZ" // 수요예배
};

// 채널에서 키워드로 영상 검색
function useYTSearch(keyword, maxResults = 1) {
  const [videos, setVideos] = useState([]);
  useEffect(() => {
    fetch(`https://www.googleapis.com/youtube/v3/search?key=${YT_API_KEY}&channelId=${YT_CHANNEL_ID}&part=snippet&order=date&maxResults=${maxResults}&type=video&q=${encodeURIComponent(keyword)}`)
      .then(r => r.json())
      .then(data => {
        if (data.items) {
          setVideos(data.items.map(item => ({
            id: item.id.videoId,
            title: item.snippet.title,
            thumb: item.snippet.thumbnails?.medium?.url || "",
            date: (() => {
              const t = item.snippet.title || "";
              const m = t.match(/(\d{4})[.]?(\d{1,2})[.]?(\d{1,2})/);
              if (m) return `${m[1]}-${m[2].padStart(2,'0')}-${m[3].padStart(2,'0')}`;
              return item.snippet.publishedAt?.slice(0, 10) || "";
            })()
          })));
        }
      })
      .catch(() => {});
  }, [keyword]);
  return videos;
}

// 재생목록에서 최신 영상 가져오기
// 모듈 레벨 캐시: 동일 요청 중복 방지 (rate limit 우회)
const _ytPlCache = {};
const _ytPlPending = {};
function usYTPlaylist(playlistId, maxResults = 1) {
  const [videos, setVideos] = useState([]);
  useEffect(() => {
    if (!playlistId) return;
    const cacheKey = `${playlistId}__${Math.max(maxResults * 3, 10)}`;
    // 이미 캐시된 결과가 있으면 바로 사용
    if (_ytPlCache[cacheKey]) {
      setVideos(_ytPlCache[cacheKey].slice(0, maxResults));
      return;
    }
    // 이미 진행 중인 요청이 있으면 완료 후 결과 공유
    if (_ytPlPending[cacheKey]) {
      _ytPlPending[cacheKey].then(sorted => setVideos(sorted.slice(0, maxResults))).catch(() => {});
      return;
    }
    const fetchCount = Math.min(Math.max(maxResults * 3, 10), 50);
    const promise = fetch(`https://www.googleapis.com/youtube/v3/playlistItems?key=${YT_API_KEY}&playlistId=${playlistId}&part=snippet&maxResults=${fetchCount}`)
      .then(r => r.json())
      .then(data => {
        if (!data.items) return [];
        const sorted = data.items
          .map(item => ({
            id: item.snippet.resourceId?.videoId,
            title: item.snippet.title,
            thumb: item.snippet.thumbnails?.medium?.url || "",
            date: (() => {
              const t = item.snippet.title || "";
              const m = t.match(/(\d{4})\.( ?\d{1,2})\.(\d{1,2})/) || t.match(/(\d{4})[.]?(\d{1,2})[.]?(\d{1,2})/);
              if (m) { const y=m[1], mo=(m[2]||'').trim(), d=(m[3]||'').trim(); if(parseInt(mo)>=1&&parseInt(mo)<=12) return `${y}-${mo.padStart(2,'0')}-${d.padStart(2,'0')}`; }
              return "1970-01-01";
            })()
          }))
          .filter(v => v.id && v.title !== "Private video" && v.title !== "Deleted video" && v.date > "2000-01-01")
          .sort((a, b) => b.date.localeCompare(a.date));
        _ytPlCache[cacheKey] = sorted;
        delete _ytPlPending[cacheKey];
        return sorted;
      })
      .catch(() => { delete _ytPlPending[cacheKey]; return []; });
    _ytPlPending[cacheKey] = promise;
    promise.then(sorted => setVideos(sorted.slice(0, maxResults))).catch(() => {});
  }, [playlistId]);
  return videos;
}

// 유튜브 카드 - 용도별 분기
function YouTubeCard({ subtitle = "맑은빛세광교회 채널", live = false, title = "이번 주 예배 다시보기", mode = "sunday", playable = false, liveStatus = null, sermonTitle = null, scripture = null }) {
  // mode: "sunday" = 채널 업로드 전체에서 주일/온세대 키워드 최신 1개 자동 선택
  // playable = true 이면 재생버튼 클릭시 창내 iframe 재생 + YouTube 링크 버튼 제공
  // liveStatus: true=실시간, false=비실시간, null=메시지 없음
  const UPLOADS_PL = "UU" + YT_CHANNEL_ID.replace(/^UC/, "");
  const allVideos = usYTPlaylist(UPLOADS_PL, mode === "sunday" ? 25 : 15);
  const SUNDAY_KW = /주일|온세대|Sunday/i;
  const videos = mode === "sunday"
    ? allVideos.filter(v => SUNDAY_KW.test(v.title))
    : allVideos;
  const video = videos[0] || null;
  const href = video ? `https://www.youtube.com/watch?v=${video.id}` : `https://www.youtube.com/@heallight_church`;
  // 하단 정보 표시용 파싱 (영상 제목에서 날짜·설교·성구 추출)
  const _parsed = video ? parseVideoTitle(video.title) : null;
  // subtitle이 관리자 입력 날짜(YYYY-MM-DD)면 표시용으로 변환, 없으면 영상 제목 파싱값 사용
  const _fmtAdminDate = (d) => {
    if (!d || d === "맑은빛세광교회 채널") return "";
    const _m = d.match(/^(\d{4})-(\d{2})-(\d{2})$/);
    return _m ? _m[1] + "." + parseInt(_m[2]) + "." + parseInt(_m[3]) : d;
  };
  const _displayDate = _fmtAdminDate(subtitle) || (_parsed ? _parsed.date : "");
  const _displaySermon = sermonTitle || (_parsed ? _parsed.sermonTitle : "");
  const _scriptureFromTitle = video ? ((video.title.match(/([가-힣]+\s*\d+[장:]\d+(?:[-\d]*)?)/)||[])[1]||"") : "";
  const _displayScripture = scripture || _scriptureFromTitle;
  const _worshipType = video ? ((video.title.match(/(새벽예배|아침예배|수요예배|주일예배|주일\d?부예배|저녁예배|특별예배|부흥회|금요예배|목요예배|추모예배|성탄예배|부활절예배)/) || [])[1] || "") : "";
  const [playing, setPlaying] = useState(false);
  const [lockedSrc, setLockedSrc] = useState(null);

  // playable 모드 — 스크롤 이탈 시 재생 중단
  const playerRef = useRef(null);
  useEffect(() => {
    if (!playing || !playerRef.current) return;
    const obs = new IntersectionObserver(
      ([entry]) => { if (!entry.isIntersecting) { setPlaying(false); setLockedSrc(null); } },
      { threshold: 0.15 }
    );
    obs.observe(playerRef.current);
    return () => obs.disconnect();
  }, [playing]);

  // playable 모드 — 클릭 즉시 iframe 재생 (API 대기 없음)
  if (playable && playing && lockedSrc) {
    return (
      <div>
        <div ref={playerRef} style={{ position: "relative", aspectRatio: "16/9", background: "#000", overflow: "hidden", borderRadius: 14 }}>
          <iframe
            src={lockedSrc}
            title={video ? video.title : title}
            allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
            allowFullScreen
            style={{ position: "absolute", inset: 0, width: "100%", height: "100%", border: "none" }}
          />
          <a href={href} target="_blank" rel="noopener noreferrer"
            style={{ position: "absolute", bottom: 12, right: 12, zIndex: 3,
              background: "rgba(0,0,0,0.65)", borderRadius: 6, padding: "6px 12px",
              display: "inline-flex", alignItems: "center", gap: 6, color: "white",
              fontSize: 11, fontWeight: 600, textDecoration: "none",
              fontFamily: "var(--font-sans)", letterSpacing: "0.02em" }}>
            <Icon.youtube size={13} /> YouTube에서 보기
          </a>
        </div>
        <div style={{ marginTop: 2, padding: "12px 18px", background: "var(--card)", border: "1px solid var(--line)", borderRadius: "0 0 14px 14px", fontFamily: "var(--font-sans)", display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12 }}>
          <div style={{ fontSize: 13, color: "var(--ink-2)", display: "flex", alignItems: "center", flexWrap: "wrap", gap: "0 10px", flex: 1 }}>
            {_displayDate && <span style={{ color: "var(--ink-3)" }}>{_displayDate.replace(/\./g, ". ")}</span>}
            {_worshipType && <span>{_worshipType}</span>}
            {(sermonTitle || (_parsed && _parsed.hasSermon)) && _displaySermon && <span style={{ fontWeight: 700, color: "var(--ink)" }}>'{_displaySermon}'</span>}
            {_displayScripture && <span>({_displayScripture})</span>}
          </div>
          <a href="https://www.youtube.com/channel/UC3MZB8Efn04qMdPLFb4_lxg" target="_blank" rel="noopener noreferrer"
            style={{ display: "inline-flex", alignItems: "center", gap: 5, padding: "6px 14px",
              background: "#4B749D", color: "#fff", borderRadius: 8, fontSize: 12, fontWeight: 600,
              textDecoration: "none", whiteSpace: "nowrap", flexShrink: 0 }}>
            ▶ 유튜브 채널
          </a>
        </div>
      </div>
    );
  }

  // playable 모드 — 썸네일 (클릭 즉시 재생 — API 대기 없음)
  if (playable) {
    const handlePlay = () => {
      const src = video
        ? `https://www.youtube.com/embed/${video.id}?autoplay=1&rel=0&enablejsapi=1`
        : `https://www.youtube.com/embed?listType=playlist&list=${UPLOADS_PL}&index=0&autoplay=1&rel=0`;
      setLockedSrc(src);
      setPlaying(true);
    };
    return (
      <div>
        <div ref={playerRef} className="yt-card" style={{ cursor: "pointer" }}
          onClick={handlePlay}>
          {live && liveStatus === null && <div className="live"><span className="pulse" /> LIVE</div>}
          {(live || liveStatus !== null) && (
            <div style={{ position: "absolute", bottom: 12, left: "50%", transform: "translateX(-50%)", zIndex: 3,
              color: "white", fontSize: 13, fontFamily: "var(--font-sans)",
              whiteSpace: "nowrap", textAlign: "center",
              textShadow: "0 1px 4px rgba(0,0,0,0.7)", fontWeight: 600 }}>
              {(live || liveStatus === true) ? (
                <span>실시간 예배가 방송중입니다. 재생버튼을 눌러 확인 바랍니다.</span>
              ) : (
                <span>지금은 실시간 예배가 없습니다. 예배 다시보기를 활용해 주세요.</span>
              )}
            </div>
          )}
          <a href={href} target="_blank" rel="noopener noreferrer"
            onClick={e => e.stopPropagation()}
            style={{ position: "absolute", top: 12, right: 12, zIndex: 3,
              background: "rgba(0,0,0,0.55)", borderRadius: 6, padding: "5px 10px",
              display: "inline-flex", alignItems: "center", gap: 5, color: "white",
              fontSize: 11, fontWeight: 600, textDecoration: "none",
              fontFamily: "var(--font-sans)", letterSpacing: "0.02em" }}>
            <Icon.youtube size={13} /> YouTube
          </a>
          <div className="play"><Icon.play size={28} /></div>
        </div>
        <div style={{ marginTop: 2, padding: "12px 18px", background: "var(--card)", border: "1px solid var(--line)", borderRadius: "0 0 14px 14px", fontFamily: "var(--font-sans)", display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12 }}>
          <div style={{ fontSize: 13, color: "var(--ink-2)", display: "flex", alignItems: "center", flexWrap: "wrap", gap: "0 10px", flex: 1 }}>
            {_displayDate && <span style={{ color: "var(--ink-3)" }}>{_displayDate.replace(/\./g, ". ")}</span>}
            {_worshipType && <span>{_worshipType}</span>}
            {(sermonTitle || (_parsed && _parsed.hasSermon)) && _displaySermon && <span style={{ fontWeight: 700, color: "var(--ink)" }}>'{_displaySermon}'</span>}
            {_displayScripture && <span>({_displayScripture})</span>}
            {!_displaySermon && !_worshipType && !_displayDate && video && (
              <span>{video.title.replace(/\[.*?\]/g, "").trim()}</span>
            )}
          </div>
          <a href="https://www.youtube.com/channel/UC3MZB8Efn04qMdPLFb4_lxg" target="_blank" rel="noopener noreferrer"
            style={{ display: "inline-flex", alignItems: "center", gap: 5, padding: "6px 14px",
              background: "#4B749D", color: "#fff", borderRadius: 8, fontSize: 12, fontWeight: 600,
              textDecoration: "none", whiteSpace: "nowrap", flexShrink: 0 }}>
            ▶ 유튜브 채널
          </a>
        </div>
        {liveStatus !== null && (
          <div className="yt-live-below" style={{ marginTop: 4, padding: "6px 14px",
            fontFamily: "var(--font-sans)", fontSize: 12, color: "var(--ink-2)" }}>
            {liveStatus ? (
              <span>지금은 실시간 예배중입니다.</span>
            ) : (
              <span>지금은 실시간 예배가 없습니다. 예배 다시보기를 활용 바랍니다.</span>
            )}
          </div>
        )}
      </div>
    );
  }

  // 기본 모드 — 전체 클릭시 YouTube 이동
  return (
    <a className="yt-card" href={href} target="_blank" rel="noopener noreferrer">
      {live && <div className="live"><span className="pulse" /> LIVE</div>}
      <div className="play"><Icon.play size={28} /></div>
      <div className="meta">
        <div style={{ fontWeight: 700, fontSize: 14, marginBottom: 2 }}>{video ? video.title : title}</div>
        <div>{video ? video.date : subtitle}</div>
      </div>
    </a>);
}

// 지난 예배 다시보기 목록 (주일 키워드 최신순)
function YouTubeArchive({ maxResults = 6 }) {
  const videos = usYTPlaylist(YT_PLAYLIST.sunday, maxResults);
  if (!videos.length) return null;
  return (
    <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill,minmax(200px,1fr))", gap: 16 }}>
      {videos.map((v, i) => (
        <a key={v.id} href={`https://www.youtube.com/watch?v=${v.id}`} target="_blank" rel="noopener noreferrer"
          style={{ textDecoration: "none", color: "inherit" }}>
          <div style={{ fontWeight: i === 0 ? 700 : 500, fontSize: 13, lineHeight: 1.4 }}>{v.title}</div>
          <div style={{ fontSize: 12, color: "var(--ink-3)", marginTop: 4 }}>{v.date}</div>
        </a>
      ))}
    </div>
  );
}

// 영상 제목에서 정보 파싱
function parseVideoTitle(title) {
  const worshipMatch = title.match(/(주일|수요|아침|특별|부활|성탄|송구영신)/);
  const worship = worshipMatch ? worshipMatch[1] + "예배" : "예배";
  const sermonMatch = title.match(/[‘’“”']([^‘’“”']+)[‘’“”']/);
  const sermonTitle = sermonMatch ? sermonMatch[1].trim() : "";
  const dateMatch = title.match(/(\d{4})[.](\d{1,2})[.](\d{1,2})/);
  const date = dateMatch ? dateMatch[1] + "." + dateMatch[2] + "." + dateMatch[3] : "";
  const pastorMatch = title.match(/([가-힣]{2,4})\s*목사/);
  const pastor = pastorMatch ? pastorMatch[1] + " 목사" : "박병규 목사";
  const sundayMatch = title.match(/(부활주일|성탄주일|종려주일|어버이주일|맥추주일|추수감사주일)/);
  const sunday = sundayMatch ? sundayMatch[1] : "";
  let displayTitle = sermonTitle;
  if (!displayTitle && date) {
    const parts = date.split(".");
    const month = parts[1] ? parseInt(parts[1]) + "월" : "";
    const day = parts[2] ? parseInt(parts[2]) + "일" : "";
    displayTitle = month + " " + day + " " + (worship || "예배");
  } else if (!displayTitle) {
    displayTitle = title.replace(/\[.*?\]/g, "").trim();
  }
  return { worship, sermonTitle: displayTitle, hasSermon: !!sermonTitle, date, pastor, sunday };
}

// 지난 예배 다시보기 리스트 (온라인 예배 섹션용)
// 채널 업로드 재생목록에서 한 번에 불러와 클라이언트에서 분류
// 순서: 주일예배 최신 1개(1위) → 아침예배 최신 3개(2-4위) → 수요예배 최신 1개(5위)
function ArchiveList() {
  const UPLOADS_PL = "UU" + YT_CHANNEL_ID.replace(/^UC/, "");
  const [allVideos, setAllVideos] = useState([]);
  const [loading,   setLoading]   = useState(true);
  const [fetchErr,  setFetchErr]  = useState(false);
  const [slots,     setSlots]     = useState({});   // Firestore weekly/current.videos.slots

  // Firestore에서 슬롯 메타데이터 읽기
  useEffect(() => {
    try {
      firebase.firestore().collection("weekly").doc("current").get()
        .then(snap => { if (snap.exists) setSlots(snap.data()?.videos?.slots || {}); })
        .catch(() => {});
    } catch(e) {}
  }, []);

  const loadVideos = () => {
    setLoading(true);
    setFetchErr(false);
    fetch(`https://www.googleapis.com/youtube/v3/playlistItems?key=${YT_API_KEY}&playlistId=${UPLOADS_PL}&part=snippet&maxResults=50`)
      .then(r => r.json())
      .then(data => {
        if (!data.items) { setFetchErr(true); setLoading(false); return; }
        const vids = data.items
          .map(item => ({
            id:    item.snippet.resourceId.videoId,
            title: item.snippet.title,
            date: (() => {
              const t = item.snippet.title || "";
              const m = t.match(/(\d{4})[.](\d{1,2})[.](\d{1,2})/);
              if (m) return `${m[1]}-${m[2].padStart(2,"0")}-${m[3].padStart(2,"0")}`;
              return item.snippet.publishedAt?.slice(0, 10) || "1970-01-01";
            })(),
          }))
          .filter(v => v.title && v.title !== "Private video" && v.title !== "Deleted video" && v.date > "2000-01-01")
          .sort((a, b) => b.date.localeCompare(a.date));

        const isSunday  = v => /주일/.test(v.title);
        const isMorning = v => /아침/.test(v.title);
        const isWed     = v => /수요/.test(v.title);

        const sunday  = vids.filter(isSunday).slice(0, 1).map(v => ({ ...v, _tag: "주일예배",  _slotKey: "sunday0"    }));
        const morning = vids.filter(isMorning).slice(0, 3).map((v, i) => ({ ...v, _tag: "아침예배",  _slotKey: `morning${i}` }));
        const wed     = vids.filter(isWed).slice(0, 1).map(v => ({ ...v, _tag: "수요예배",  _slotKey: "wednesday0" }));

        const result = [...sunday, ...morning, ...wed];
        if (result.length < 3) {
          const usedIds = new Set(result.map(v => v.id));
          const extra = vids.filter(v => !usedIds.has(v.id)).slice(0, 5 - result.length)
            .map(v => ({ ...v, _tag: "예배", _slotKey: null }));
          result.push(...extra);
        }
        setAllVideos(result);
        setLoading(false);
      })
      .catch(() => { setFetchErr(true); setLoading(false); });
  };

  useEffect(() => { loadVideos(); }, []);

  if (loading) return (
    <div style={{ color: "var(--ink-3)", fontSize: 13 }}>불러오는 중...</div>
  );
  if (fetchErr || !allVideos.length) return (
    <div style={{ display: "flex", flexDirection: "column", gap: 10, padding: "4px 0" }}>
      <div style={{ color: "var(--ink-3)", fontSize: 13 }}>영상 목록을 불러올 수 없습니다.</div>
      <div style={{ display: "flex", gap: 8, flexWrap: "wrap" }}>
        <button onClick={loadVideos} style={{ fontSize: 12, padding: "6px 14px", borderRadius: 8, border: "1px solid var(--line)", background: "var(--paper-2)", cursor: "pointer", color: "var(--ink-2)" }}>
          다시 시도
        </button>
        <a href="https://www.youtube.com/@heallight_church" target="_blank" rel="noopener noreferrer"
          style={{ fontSize: 12, padding: "6px 14px", borderRadius: 8, border: "none", background: "var(--primary)", color: "#fff", textDecoration: "none", display: "inline-flex", alignItems: "center", gap: 5 }}>
          <Icon.youtube size={12}/> 유튜브 채널 바로가기
        </a>
      </div>
    </div>
  );

  return (
    <div>
      {allVideos.map((v, i) => {
        const p = parseVideoTitle(v.title);
        const s = v._slotKey ? (slots[v._slotKey] || {}) : {};
        // 우선순위: Firestore slots > YouTube 파싱 > YouTube 원본 제목
        const displayTitle     = s.title     || p.sermonTitle || v.title;
        const displayDate      = s.date      || p.date        || v.date;
        const displayPastor    = s.preacher  || p.pastor;
        const displayScripture = s.scripture || "";
        const videoUrl = (s.url && s.url.trim()) ? s.url.trim() : `https://www.youtube.com/watch?v=${v.id}`;
        const subtitle = [displayDate, displayPastor, displayScripture].filter(Boolean).join(" · ");
        return (
          <a key={v.id} href={videoUrl} target="_blank" rel="noopener noreferrer"
            style={{ textDecoration: "none", color: "inherit", display: "flex", gap: 10, padding: "8px 0", borderTop: i > 0 ? "1px solid var(--line)" : "none", alignItems: "flex-start" }}>
            <div style={{ width: 40, height: 40, borderRadius: 8, background: "var(--primary)", display: "flex", alignItems: "center", justifyContent: "center", color: "#fff", flexShrink: 0, marginTop: 2 }}>
              <Icon.play size={16} />
            </div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 11, fontWeight: 700, color: "var(--primary)", letterSpacing: "0.05em", marginBottom: 3 }}>{v._tag}</div>
              <div style={{ fontWeight: 600, fontSize: 14, lineHeight: 1.4, marginBottom: 4, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                {displayTitle}
              </div>
              <div style={{ fontSize: 12, color: "var(--ink-3)" }}>{subtitle}</div>
            </div>
          </a>
        );
      })}
    </div>
  );
}
// 도형 배경의 십자가 아이콘 (포인트용)
function CrossBadge({ color = "var(--mint)", size = 56 }) {
  return (
    <div style={{ width: size, height: size, borderRadius: "50%", background: color, display: "inline-flex", alignItems: "center", justifyContent: "center", color: "white" }}>
      <Icon.cross size={size * 0.4} />
    </div>);

}

// 공통 네비게이션 항목
const NAV_ITEMS = [
{ id: "home", label: "홈" },
{ id: "about", label: "교회 소개" },
{ id: "worship", label: "예배·공동체" },
{ id: "thisweek", label: "이번 주" },
{ id: "media", label: "온라인 예배" },
{ id: "prayer", label: "기도" },
{ id: "visit", label: "오시는 길" },
{ id: "community", label: "교인마당", href: "community/community.html", accent: true }];


// 스무스 스크롤 (또는 external 링크 이동)
function scrollToId(id) {
  const item = NAV_ITEMS.find((i) => i.id === id);
  if (item && item.href) {
    window.location.href = item.href;
    return;
  }
  const el = document.getElementById(id);
  if (!el) return;
  const top = el.getBoundingClientRect().top + window.scrollY - 72;
  window.scrollTo({ top, behavior: "smooth" });
}

// 모바일 메뉴 훅
function useScrollSpy(ids) {
  // external 항목은 spy 대상에서 제외
  ids = ids.filter((id) => {
    const item = NAV_ITEMS.find((i) => i.id === id);
    return !item || !item.href;
  });
  const [active, setActive] = useState(ids[0]);
  useEffect(() => {
    const onScroll = () => {
      const y = window.scrollY + 200;
      let cur = ids[0];
      for (const id of ids) {
        const el = document.getElementById(id);
        if (el && el.offsetTop <= y) cur = id;
      }
      setActive(cur);
    };
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);
  return active;
}

// ─── 텍스트 복사 — Clipboard API + execCommand fallback + 시각 피드백 ───
async function copyText(text) {
  try {
    if (navigator.clipboard && window.isSecureContext) {
      await navigator.clipboard.writeText(text);
      return true;
    }
  } catch (e) {
    console.warn("clipboard API 실패, fallback 시도:", e.message);
  }
  // Fallback — execCommand
  try {
    const ta = document.createElement("textarea");
    ta.value = text;
    ta.setAttribute("readonly", "");
    ta.style.position = "fixed";
    ta.style.top = "-9999px";
    ta.style.opacity = "0";
    document.body.appendChild(ta);
    ta.select();
    ta.setSelectionRange(0, text.length);
    const ok = document.execCommand("copy");
    document.body.removeChild(ta);
    return ok;
  } catch (e) {
    console.warn("execCommand 복사 실패:", e.message);
    return false;
  }
}

// 복사 버튼용 React 훅 — 클릭시 피드백 라벨로 잠깐 바뀜
function useCopyButton() {
  const [copied, setCopied] = React.useState(false);
  const trigger = async (text) => {
    const ok = await copyText(text);
    if (ok) {
      setCopied(true);
      setTimeout(() => setCopied(false), 1500);
    } else {
      // 최후 fallback — 사용자에게 직접 노출
      window.prompt("자동 복사가 안 됐어요. 길게 눌러 복사하세요:", text);
    }
  };
  return [copied, trigger];
}

Object.assign(window, {
  Icon, LogoMark, LogoLockup, CrossPattern, PhotoSlot, SectionTitle, YouTubeCard, YouTubeArchive, ArchiveList, CrossBadge,
  NAV_ITEMS, scrollToId, useScrollSpy,
  IllustratedMap, KakaoEmbedMap,
  copyText, useCopyButton,
});