/* ============================================================
   VARIATION A — Full-bleed, section-snap, title-led
   ============================================================ */

const A = {
  bg: "#FAFBFC",
  surface: "#FFFFFF",
  ink: "#0A2540",
  ink2: "#3C4B66",
  ink3: "#6B7A91",
  line: "rgba(10,37,64,0.08)",
  lineStrong: "rgba(10,37,64,0.16)",
  accent: "#635BFF",
  accent2: "#0EA5E9",
  accentSoft: "#EEF0FF",
  good: "#0E9F6E",
};

const aHeading = { fontFamily: "var(--font-sans)", letterSpacing: "-0.03em", color: A.ink, fontWeight: 700, lineHeight: 1.1, wordBreak: "keep-all", overflowWrap: "break-word", textAlign: "center" };

// Snap section wrapper
const Snap = ({ bg = A.bg, children, style = {}, id }) => {
  const { isMobile, isTablet } = useViewport();
  return (
    <section
      id={id}
      className="snap-section-100vh"
      style={{
        scrollSnapAlign: "start",
        scrollSnapStop: "always",
        width: "100%",
        display: "flex",
        flexDirection: "column",
        justifyContent: "center",
        alignItems: "stretch",
        padding: isMobile ? "84px 18px 56px" : isTablet ? "100px 40px" : "120px 64px",
        background: bg,
        position: "relative",
        overflow: "hidden",
        boxSizing: "border-box",
        ...style,
      }}>
      {children}
    </section>
  );
};

// Auto-rotating active index that runs only when the section is visible.
// Pauses on hover within the section — user can take manual control via onSelect.
const useAutoRotate = (count, ref, interval = 2400) => {
  const [active, setActive] = React.useState(0);
  const [paused, setPaused] = React.useState(false);
  const [visible, setVisible] = React.useState(false);

  React.useEffect(() => {
    const el = ref.current; if (!el) return;
    if (typeof IntersectionObserver === "undefined") { setVisible(true); return; }
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => setVisible(e.isIntersecting));
    }, { threshold: 0.4, root: el.closest('[data-scroll-root]') || null });
    io.observe(el);
    return () => io.disconnect();
  }, [ref]);

  React.useEffect(() => {
    if (!visible || paused) return;
    const t = setInterval(() => setActive((a) => (a + 1) % count), interval);
    return () => clearInterval(t);
  }, [visible, paused, count, interval]);

  return { active, setActive, setPaused };
};

// ---------- HERO ----------
const HeroA = () => {
  const { isMobile } = useViewport();
  return (
  <Snap id="hero">
    <div aria-hidden style={{
      position: "absolute", right: isMobile ? -120 : -200, top: isMobile ? -80 : -120,
      width: isMobile ? 420 : 800, height: isMobile ? 420 : 800,
      background: "radial-gradient(closest-side, rgba(99,91,255,.18), rgba(99,91,255,0) 70%)",
      filter: "blur(8px)", pointerEvents: "none",
    }} />
    <div aria-hidden style={{
      position: "absolute", left: isMobile ? -80 : -120, bottom: isMobile ? -120 : -200,
      width: isMobile ? 320 : 540, height: isMobile ? 320 : 540,
      background: "radial-gradient(closest-side, rgba(14,159,110,.10), rgba(14,159,110,0) 70%)",
      filter: "blur(6px)", pointerEvents: "none",
    }} />
    <div style={{ maxWidth: 1280, margin: "0 auto", width: "100%", position: "relative" }}>
      <Reveal delay={80}>
        <h1 style={{ ...aHeading, fontSize: "clamp(44px, 5.6vw, 96px)", margin: 0 }}>
          이제는{" "}
          <span style={{
            color: A.ink2,
            fontWeight: 500,
            background: `linear-gradient(110deg, ${A.ink2} 45%, ${A.ink3} 50%, ${A.ink2} 55%)`,
            backgroundSize: "300% 100%",
            WebkitBackgroundClip: "text",
            backgroundClip: "text",
            WebkitTextFillColor: "transparent",
            animation: "fadeOldA 12s 0.5s ease-in-out infinite",
            opacity: 0.92,
          }}><span style={{
              background: `linear-gradient(110deg, #F97316 0%, #EF4444 50%, #F97316 100%)`,
              backgroundSize: "200% 100%",
              WebkitBackgroundClip: "text",
              backgroundClip: "text",
              WebkitTextFillColor: "transparent",
              animation: "keywordOldA 6s ease-in-out infinite",
              fontWeight: 700,
              position: "relative",
            }}>검색</span></span>이 아니라<br />
          <span style={{ position: "relative", display: "inline-block" }}>
            <span style={{
              background: `linear-gradient(110deg, ${A.accent} 0%, #8b7dff 35%, ${A.accent2} 70%, ${A.accent} 100%)`,
              backgroundSize: "200% 100%",
              WebkitBackgroundClip: "text",
              backgroundClip: "text",
              WebkitTextFillColor: "transparent",
              animation: "keywordNewA 6s ease-in-out infinite",
              paddingBottom: "0.06em",
              fontWeight: 700,
              position: "relative",
            }}>AI가 추천하는</span>
            <span aria-hidden style={{
              position: "absolute",
              inset: 0,
              background: "linear-gradient(110deg, transparent 30%, rgba(255,255,255,0.85) 48%, rgba(255,255,255,1) 50%, rgba(255,255,255,0.85) 52%, transparent 70%)",
              backgroundSize: "300% 100%",
              WebkitBackgroundClip: "text",
              backgroundClip: "text",
              WebkitTextFillColor: "transparent",
              animation: "shimmerGlossA 8s linear infinite",
              fontWeight: 700,
              fontFamily: "inherit",
              fontSize: "inherit",
              letterSpacing: "inherit",
              lineHeight: "inherit",
              pointerEvents: "none",
              mixBlendMode: "screen",
            }}>AI가 추천하는</span>
            <span aria-hidden style={{
              position: "absolute",
              left: 0, right: 0, bottom: 0,
              height: "0.08em",
              background: A.accent,
              transformOrigin: "left center",
              transform: "scaleX(0)",
              animation: "drawUnderlineA 1.8s 0.5s ease-out forwards",
            }} />
          </span>{" "}
          시대입니다
        </h1>
        <style>{`
          @keyframes shimmerSlowA {
            0% { background-position: 200% 0; }
            100% { background-position: -200% 0; }
          }
          @keyframes shimmerGlossA {
            0% { background-position: 200% 0; }
            100% { background-position: -200% 0; }
          }
          @keyframes fadeOldA {
            0% { background-position: 200% 0; }
            100% { background-position: -200% 0; }
          }
          @keyframes keywordOldA {
            0%, 100% { background-position: 100% 0; }
            50% { background-position: 0% 0; }
          }
          @keyframes keywordNewA {
            0%, 100% { background-position: 100% 0; }
            50% { background-position: 0% 0; }
          }
          @keyframes drawUnderlineA { from { transform: scaleX(0); } to { transform: scaleX(1); } }
          @keyframes shimmerA { 0% { background-position: 200% 0 } 100% { background-position: -200% 0 } }
          @keyframes pulseGlow { 0%, 100% { box-shadow: 0 0 0 0 rgba(99,91,255,0); } 50% { box-shadow: 0 0 0 12px rgba(99,91,255,0.08); } }
          @keyframes floatY { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
          @keyframes drawLine { from { stroke-dashoffset: 240; } to { stroke-dashoffset: 0; } }
        `}</style>
      </Reveal>
      <Reveal delay={280}>
        <div style={{
          display: "flex", gap: isMobile ? 10 : 14,
          marginTop: isMobile ? 36 : 56,
          flexDirection: isMobile ? "column" : "row",
          flexWrap: "wrap",
          justifyContent: "center",
          alignItems: isMobile ? "stretch" : "center",
        }}>
          <button style={{
            display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 12,
            background: A.ink, color: "#fff", border: "none",
            padding: isMobile ? "16px 22px" : "20px 28px",
            borderRadius: 14, fontSize: isMobile ? 16 : 17, fontWeight: 600,
            cursor: "pointer", fontFamily: "var(--font-sans)",
            minHeight: 52,
            boxShadow: "0 1px 0 rgba(255,255,255,.1) inset, 0 8px 22px rgba(10,37,64,.18)",
            transition: "transform .15s ease, box-shadow .15s ease",
          }}
            onMouseEnter={(e) => { if (!isMobile) e.currentTarget.style.transform = "translateY(-2px)"; }}
            onMouseLeave={(e) => { if (!isMobile) e.currentTarget.style.transform = "translateY(0)"; }}>
            <Icon kind="kakao" size={18} color="#FEE500" />
            카카오톡 상담 시작하기
            <Icon kind="arrow" size={18} />
          </button>
          <button style={{
            background: "#fff", color: A.ink, border: `1px solid ${A.lineStrong}`,
            padding: isMobile ? "16px 22px" : "20px 28px",
            borderRadius: 14, fontSize: isMobile ? 16 : 17, fontWeight: 600, cursor: "pointer",
            fontFamily: "var(--font-sans)",
            minHeight: 52,
          }}>상품 살펴보기</button>
        </div>
      </Reveal>
    </div>
  </Snap>
  );
};

// ---------- 2섹션: AI 추천 작동 원리 ----------
const AiCriteriaA = () => {
  const sectionRef = React.useRef(null);
  const data = HJ.aiCriteria;
  const { isMobile, isTablet } = useViewport();
  const { active, setActive, setPaused } = useAutoRotate(data.items.length, sectionRef, 2400);
  const [titleVisible, setTitleVisible] = React.useState(false);
  const [cardsVisible, setCardsVisible] = React.useState(false);
  React.useEffect(() => {
    const el = sectionRef.current; if (!el) return;
    if (typeof IntersectionObserver === "undefined") {
      setTitleVisible(true); setCardsVisible(true); return;
    }
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          setTitleVisible(true);
          setTimeout(() => setCardsVisible(true), 600);
        } else {
          setTitleVisible(false);
          setCardsVisible(false);
        }
      });
    }, { threshold: 0.2, root: el.closest('[data-scroll-root]') || null });
    io.observe(el);
    const fb = setTimeout(() => { setTitleVisible(true); setCardsVisible(true); }, 1500);
    return () => { io.disconnect(); clearTimeout(fb); };
  }, []);

  const titleWords = data.title.split(/(\s+|<br\s*\/?>)/);
  return (
    <Snap id="ai-criteria" bg="#fff" style={{ borderTop: `1px solid ${A.line}`, borderBottom: `1px solid ${A.line}` }}>
      <div ref={sectionRef} style={{ maxWidth: 1280, margin: "0 auto", width: "100%" }}
        onMouseEnter={() => setPaused(true)}
        onMouseLeave={() => setPaused(false)}>
        <h2 style={{ ...aHeading, fontSize: "clamp(36px, 4.4vw, 72px)", margin: "0 auto", maxWidth: 1100 }}>
          {(() => {
            // "AI 추천은 어떻게 이루어질까요?" — "AI 추천" 부분에 1섹션 효과 적용, "은"부터는 일반
            const words = data.title.split(" ");
            const out = [];
            words.forEach((w, i) => {
              const baseStyle = {
                display: "inline-block",
                marginRight: "0.28em",
                opacity: titleVisible ? 1 : 0,
                transform: titleVisible ? "translateY(0) rotateX(0)" : "translateY(40px) rotateX(-30deg)",
                transformOrigin: "50% 100%",
                transition: `opacity 0.7s cubic-bezier(.2,.7,.2,1) ${i * 0.08}s, transform 0.8s cubic-bezier(.2,.7,.2,1) ${i * 0.08}s`,
              };
              if (i === 0 && w === "AI") {
                // "AI" 단어 — 그라디언트 + shimmer + underline
                out.push(
                  <span key={i} style={{ ...baseStyle, marginRight: "0.28em", position: "relative" }}>
                    <span style={{ position: "relative", display: "inline-block" }}>
                      <span style={{
                        background: `linear-gradient(110deg, ${A.accent} 0%, #8b7dff 35%, ${A.accent2} 70%, ${A.accent} 100%)`,
                        backgroundSize: "200% 100%",
                        WebkitBackgroundClip: "text",
                        backgroundClip: "text",
                        WebkitTextFillColor: "transparent",
                        animation: "keywordNewA 6s ease-in-out infinite",
                        fontWeight: 700,
                        position: "relative",
                      }}>AI</span>
                      <span aria-hidden style={{
                        position: "absolute", inset: 0,
                        background: "linear-gradient(110deg, transparent 30%, rgba(255,255,255,0.85) 48%, rgba(255,255,255,1) 50%, rgba(255,255,255,0.85) 52%, transparent 70%)",
                        backgroundSize: "300% 100%",
                        WebkitBackgroundClip: "text",
                        backgroundClip: "text",
                        WebkitTextFillColor: "transparent",
                        animation: "shimmerGlossA 8s linear infinite",
                        fontWeight: 700,
                        fontFamily: "inherit", fontSize: "inherit", letterSpacing: "inherit", lineHeight: "inherit",
                        pointerEvents: "none", mixBlendMode: "screen",
                      }}>AI</span>
                    </span>
                  </span>
                );
              } else if (i === 1 && w.startsWith("추천")) {
                // "추천은" → "추천" 효과 + "은" 일반
                const rest = w.slice(2); // "은"
                out.push(
                  <span key={i} style={baseStyle}>
                    <span style={{ position: "relative", display: "inline-block" }}>
                      <span style={{
                        background: `linear-gradient(110deg, ${A.accent} 0%, #8b7dff 35%, ${A.accent2} 70%, ${A.accent} 100%)`,
                        backgroundSize: "200% 100%",
                        WebkitBackgroundClip: "text",
                        backgroundClip: "text",
                        WebkitTextFillColor: "transparent",
                        animation: "keywordNewA 6s ease-in-out infinite",
                        fontWeight: 700,
                        paddingBottom: "0.06em",
                        position: "relative",
                      }}>추천</span>
                      <span aria-hidden style={{
                        position: "absolute", inset: 0,
                        background: "linear-gradient(110deg, transparent 30%, rgba(255,255,255,0.85) 48%, rgba(255,255,255,1) 50%, rgba(255,255,255,0.85) 52%, transparent 70%)",
                        backgroundSize: "300% 100%",
                        WebkitBackgroundClip: "text",
                        backgroundClip: "text",
                        WebkitTextFillColor: "transparent",
                        animation: "shimmerGlossA 8s linear infinite",
                        fontWeight: 700,
                        fontFamily: "inherit", fontSize: "inherit", letterSpacing: "inherit", lineHeight: "inherit",
                        pointerEvents: "none", mixBlendMode: "screen",
                      }}>추천</span>
                    </span>
                    {rest}
                  </span>
                );
              } else {
                out.push(<span key={i} style={baseStyle}>{w}</span>);
              }
            });
            return out;
          })()}
        </h2>
        <div style={{
          marginTop: isMobile ? 36 : 96,
          display: "grid",
          gridTemplateColumns: isMobile ? "1fr" : isTablet ? "repeat(2, 1fr)" : "repeat(4, 1fr)",
          gap: isMobile ? 10 : 16,
          perspective: 1200,
        }}>
          {data.items.map((it, i) => {
            const isActive = active === i;
            return (
              <div key={it.t}
                onMouseEnter={() => { if (!isMobile) setActive(i); }}
                onClick={() => setActive(i)}
                style={{
                  opacity: cardsVisible ? 1 : 0,
                  transform: cardsVisible
                    ? (isActive ? "translateY(-6px) scale(1)" : "translateY(0) scale(1)")
                    : "translateY(80px) scale(0.92)",
                  transition: `opacity 0.7s cubic-bezier(.2,.7,.2,1) ${i * 0.12}s, transform 0.7s cubic-bezier(.2,.7,.2,1) ${cardsVisible ? i * 0.12 : 0}s, background .5s ease, color .5s ease, box-shadow .5s ease, border-color .5s ease`,
                  background: isActive ? A.ink : "#fff",
                  color: isActive ? "#fff" : A.ink,
                  border: `1px solid ${isActive ? "transparent" : A.line}`,
                  borderRadius: 18,
                  padding: isMobile ? 18 : 28,
                  minHeight: isMobile ? 120 : 360,
                  display: "flex", flexDirection: isMobile ? "row" : "column",
                  alignItems: isMobile ? "center" : "stretch",
                  justifyContent: isMobile ? "flex-start" : "space-between",
                  gap: isMobile ? 14 : 0,
                  position: "relative", overflow: "hidden",
                  boxShadow: isActive ? "0 30px 60px -20px rgba(10,37,64,.35)" : "0 0 0 rgba(0,0,0,0)",
                  cursor: "pointer",
                }}>
                {isActive && (
                  <div aria-hidden style={{
                    position: "absolute", inset: 0,
                    background: `radial-gradient(circle at 100% 0%, ${A.accent}55, transparent 50%)`,
                    pointerEvents: "none",
                  }} />
                )}
                {isActive && (
                  <div aria-hidden style={{
                    position: "absolute", inset: -2,
                    borderRadius: 20,
                    border: `2px solid ${A.accent}`,
                    opacity: 0,
                    animation: "criteriaPulse 1.6s ease-out infinite",
                    pointerEvents: "none",
                  }} />
                )}
                <div style={{ position: "relative", display: "flex", justifyContent: "space-between", alignItems: "flex-start", flexShrink: 0 }}>
                  <div style={{
                    width: isMobile ? 40 : 48, height: isMobile ? 40 : 48, borderRadius: 12,
                    background: isActive ? "rgba(255,255,255,.1)" : A.accentSoft,
                    color: isActive ? "#fff" : A.accent,
                    display: "flex", alignItems: "center", justifyContent: "center",
                    border: isActive ? "1px solid rgba(255,255,255,.14)" : "none",
                    transform: isActive ? "rotate(-6deg) scale(1.05)" : "rotate(0) scale(1)",
                    transition: "all .5s cubic-bezier(.2,.7,.2,1)",
                  }}>
                    <Icon kind={it.k} size={isMobile ? 20 : 24} />
                  </div>
                </div>
                <div style={{ position: "relative", flex: 1, minWidth: 0 }}>
                  <h3 style={{ fontSize: isMobile ? 17 : 22, fontWeight: 700, letterSpacing: "-.02em", lineHeight: 1.3, margin: 0, color: isActive ? "#fff" : A.ink, transition: "color .4s ease", wordBreak: "keep-all" }}>
                    {it.t}
                  </h3>
                  <p style={{ marginTop: isMobile ? 6 : 12, fontSize: isMobile ? 13 : 14.5, lineHeight: 1.55, color: isActive ? "rgba(255,255,255,.78)" : A.ink2, margin: `${isMobile ? 6 : 12}px 0 0`, transition: "color .4s ease", wordBreak: "keep-all" }}>
                    {it.d}
                  </p>
                </div>
              </div>
            );
          })}
        </div>
        <style>{`
          @keyframes criteriaPulse {
            0% { opacity: 0.6; transform: scale(1); }
            100% { opacity: 0; transform: scale(1.04); }
          }
        `}</style>
      </div>
    </Snap>
  );
};

// ---------- 3섹션: 외부 채널 vs 홈페이지 ----------
// ---------- 3섹션: 외부 채널 vs 홈페이지 ----------
// ---------- 3섹션: 4채널 → AI 허브 시너지 ----------
// AiHubDiagram: 4개 채널 노드가 동시에 중앙 AI로 흘러들어 추천 결과로 출력
const AiHubDiagram = ({ step }) => {
  const { isMobile } = useViewport();
  // PC: channels left arc, AI center, output right
  // Mobile: channels top row, AI center, output bottom
  const channels = isMobile
    ? [
        { name: "블로그",   k: "naver",     x: 14, y: 18 },
        { name: "SNS",      k: "instagram", x: 38, y: 18 },
        { name: "유튜브",   k: "youtube",   x: 62, y: 18 },
        { name: "홈페이지", k: "globe",     x: 86, y: 18 },
      ]
    : [
        { name: "블로그",   k: "naver",     x: 10, y: 18 },
        { name: "SNS",      k: "instagram", x: 10, y: 40 },
        { name: "유튜브",   k: "youtube",   x: 10, y: 62 },
        { name: "홈페이지", k: "globe",     x: 10, y: 84 },
      ];
  // Output position
  const output = isMobile ? { x: 50, y: 86 } : { x: 80, y: 50 };
  // AI core stop ratio for line endings (in viewbox %)
  return (
    <div style={{
      position: "relative",
      width: "100%",
      aspectRatio: isMobile ? "1 / 1.05" : "2.2 / 1",
      maxHeight: isMobile ? "70vh" : "48vh",
      overflow: "visible",
    }}>
      {/* radial glow background */}
      <div aria-hidden style={{
        position: "absolute", left: "50%", top: "50%",
        width: "70%", height: "120%",
        transform: "translate(-50%, -50%)",
        background: `radial-gradient(ellipse at center, ${A.accent}1a 0%, transparent 60%)`,
        opacity: step >= 2 ? 1 : 0,
        transition: "opacity 0.35s ease",
        pointerEvents: "none",
      }} />

      {/* subtle grid bg */}
      <div aria-hidden style={{
        position: "absolute", inset: 0,
        backgroundImage: `linear-gradient(${A.line} 1px, transparent 1px), linear-gradient(90deg, ${A.line} 1px, transparent 1px)`,
        backgroundSize: "40px 40px",
        opacity: 0.4,
        maskImage: "radial-gradient(ellipse at center, black 30%, transparent 75%)",
        WebkitMaskImage: "radial-gradient(ellipse at center, black 30%, transparent 75%)",
        transform: "rotateX(45deg) translateZ(-40px) scale(1.4)",
        transformOrigin: "center center",
      }} />

      {/* Connecting lines: each channel → AI core → output */}
      <svg aria-hidden viewBox="0 0 100 100" preserveAspectRatio="none" style={{ position: "absolute", inset: 0, width: "100%", height: "100%", pointerEvents: "none", zIndex: 1 }}>
        <defs>
          <linearGradient id="flowGrad" x1="0%" y1="0%" x2="100%" y2="0%">
            <stop offset="0%" stopColor={A.accent} stopOpacity="0.15" />
            <stop offset="100%" stopColor={A.accent} stopOpacity="0.85" />
          </linearGradient>
          <radialGradient id="aiGlow" cx="50%" cy="50%">
            <stop offset="0%" stopColor={A.accent} stopOpacity="0.6" />
            <stop offset="100%" stopColor={A.accent} stopOpacity="0" />
          </radialGradient>
        </defs>

        {/* AI core radial glow halo */}
        <circle cx="50" cy="50" r="22" fill="url(#aiGlow)" opacity={step >= 2 ? 0.5 : 0} style={{ transition: "opacity 0.35s ease" }} />

        {channels.map((c, i) => {
          // Line from channel node to AI core (50,50), ending just before AI core
          const dx = 50 - c.x;
          const dy = 50 - c.y;
          const dist = Math.sqrt(dx * dx + dy * dy);
          // stop 6 units before AI core
          const stopRatio = (dist - 6) / dist;
          const x2 = c.x + dx * stopRatio;
          const y2 = c.y + dy * stopRatio;
          // line starts 4 units away from channel node
          const startRatio = 4 / dist;
          const x1 = c.x + dx * startRatio;
          const y1 = c.y + dy * startRatio;
          return (
            <React.Fragment key={c.name}>
              <line
                x1={x1} y1={y1}
                x2={x2} y2={y2}
                stroke="url(#flowGrad)"
                strokeWidth="0.5"
                strokeDasharray="1.2 0.8"
                opacity={step >= 1 ? 1 : 0}
                style={{ transition: `opacity 0.6s ease ${i * 0.1}s` }}
              />
              {/* Flowing particle along the line, channel → AI */}
              <circle r="0.9" fill={A.accent} opacity={step >= 2 ? 1 : 0} style={{ transition: "opacity 0.3s ease" }}>
                <animate attributeName="cx" values={`${x1};${x2}`} dur="2s" begin={`${i * 0.5}s`} repeatCount="indefinite" />
                <animate attributeName="cy" values={`${y1};${y2}`} dur="2s" begin={`${i * 0.5}s`} repeatCount="indefinite" />
              </circle>
            </React.Fragment>
          );
        })}
        {/* AI core → output */}
        {(() => {
          const dx = output.x - 50, dy = output.y - 50;
          const dist = Math.sqrt(dx * dx + dy * dy);
          const sr = 6 / dist, er = (dist - 8) / dist;
          const x1 = 50 + dx * sr, y1 = 50 + dy * sr;
          const x2 = 50 + dx * er, y2 = 50 + dy * er;
          return (
            <React.Fragment>
              <line
                x1={x1} y1={y1}
                x2={x2} y2={y2}
                stroke={A.accent}
                strokeWidth="0.6"
                strokeDasharray="1.5 0.8"
                opacity={step >= 3 ? 0.9 : 0}
                style={{ transition: "opacity 0.6s ease" }}
              />
              {step >= 3 && (
                <circle r="1" fill={A.accent}>
                  <animate attributeName="cx" values={`${x1};${x2}`} dur="1.6s" repeatCount="indefinite" />
                  <animate attributeName="cy" values={`${y1};${y2}`} dur="1.6s" repeatCount="indefinite" />
                  <animate attributeName="opacity" values="0;1;1;0" keyTimes="0;0.15;0.85;1" dur="1.6s" repeatCount="indefinite" />
                </circle>
              )}
            </React.Fragment>
          );
        })()}
      </svg>

      {/* 4 Channel nodes — left column */}
      {channels.map((c, i) => {
        const visible = step >= 1;
        return (
          <div key={c.name} style={{
            position: "absolute",
            left: `${c.x}%`, top: `${c.y}%`,
            transform: "translate(-50%, -50%)",
            display: "flex", flexDirection: "column", alignItems: "center", gap: 6,
            zIndex: 2,
            opacity: visible ? 1 : 0,
            transitionProperty: "opacity",
            transitionDuration: "0.6s",
            transitionTimingFunction: "cubic-bezier(.2,.7,.2,1)",
            transitionDelay: `${i * 0.1}s`,
          }}>
            <div style={{
              width: 56, height: 56,
              color: A.accent,
              display: "flex", alignItems: "center", justifyContent: "center",
            }}>
              <Icon kind={c.k} size={48} strokeWidth={1.8} color={A.accent} />
            </div>
            <div style={{ fontSize: 13, fontWeight: 700, color: A.ink, letterSpacing: "-.005em", whiteSpace: "nowrap" }}>{c.name}</div>
          </div>
        );
      })}

      {/* pulse rings — independent of AI core wrapper, no transform accumulation */}
      <div aria-hidden style={{
        position: "absolute",
        left: "50%", top: "50%",
        width: 100, height: 100,
        marginLeft: -50, marginTop: -50,
        pointerEvents: "none",
        zIndex: 2,
      }}>
        <div style={{
          position: "absolute", inset: -24,
          borderRadius: "50%",
          border: `1.5px solid ${A.accent}`,
          opacity: step >= 2 ? 0.3 : 0,
          transition: "opacity 0.35s ease",
          animation: "aiHubPulse 2.4s ease-out infinite",
          willChange: "transform",
        }} />
        <div style={{
          position: "absolute", inset: -24,
          borderRadius: "50%",
          border: `1.5px solid ${A.accent}`,
          opacity: step >= 2 ? 0.2 : 0,
          transition: "opacity 0.35s ease",
          animation: "aiHubPulse 2.4s ease-out infinite 1.2s",
          willChange: "transform",
        }} />
      </div>

      {/* AI core (center) */}
      <div style={{
        position: "absolute",
        left: "50%", top: "50%",
        width: 100, height: 100,
        marginLeft: -50, marginTop: -50,
        opacity: step >= 2 ? 1 : 0,
        transform: step >= 2 ? "scale(1)" : "scale(0.85)",
        transformOrigin: "center center",
        transition: "opacity 0.35s ease, transform 0.35s cubic-bezier(.2,.7,.2,1)",
        zIndex: 3,
      }}>
        <div style={{
          position: "absolute", inset: 0,
          willChange: "transform",
          animation: "aiCoreFloatStaticOnly 5s ease-in-out 0.4s infinite",
        }}>
        <div style={{
          width: 100, height: 100, borderRadius: "50%",
          background: `linear-gradient(135deg, ${A.accent} 0%, #8b7dff 35%, ${A.accent2} 70%, ${A.accent} 100%)`,
          color: "#fff",
          display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center",
          gap: 2,
          boxShadow: `0 12px 28px -8px ${A.accent}88`,
          fontFamily: "var(--font-display)",
          position: "relative",
        }}>
          {/* glossy highlight */}
          <div aria-hidden style={{
            position: "absolute",
            top: 6, left: "50%", transform: "translateX(-50%)",
            width: "70%", height: "30%",
            borderRadius: "50%",
            background: "radial-gradient(ellipse at center, rgba(255,255,255,0.45) 0%, transparent 70%)",
            pointerEvents: "none",
          }} />
          <div style={{ fontSize: 34, fontWeight: 800, letterSpacing: ".02em", lineHeight: 1, position: "relative" }}>AI</div>
        </div>
        </div>
      </div>

      {/* Output: recommendation result */}
      <div style={isMobile ? {
        position: "absolute",
        left: "50%", bottom: "6%",
        transform: `translateX(-50%) translateY(${step >= 3 ? 0 : 16}px)`,
        opacity: step >= 3 ? 1 : 0,
        transition: "all 0.7s cubic-bezier(.2,.7,.2,1)",
        zIndex: 2,
        width: "78%", maxWidth: 340,
      } : {
        position: "absolute",
        right: "8%", top: "50%",
        transform: `translateY(-50%) translateX(${step >= 3 ? 0 : 16}px)`,
        opacity: step >= 3 ? 1 : 0,
        transition: "all 0.7s cubic-bezier(.2,.7,.2,1)",
        zIndex: 2,
        width: "26%", maxWidth: 240,
      }}>
        <div style={{
          background: A.ink, color: "#fff",
          borderRadius: 16, padding: isMobile ? "14px 16px" : "18px 18px 16px",
          boxShadow: `0 12px 24px -8px rgba(10,37,64,.4)`,
          display: "flex", flexDirection: "column", gap: 8,
          position: "relative",
        }}>
          <div style={{ fontSize: isMobile ? 14 : 16, fontWeight: 700, lineHeight: 1.4, letterSpacing: "-.01em", wordBreak: "keep-all" }}>
            "○○ 시술은 △△ 병원이 잘합니다"
          </div>
        </div>
      </div>

      <style>{`
        @keyframes aiHubPulse {
          0%   { transform: scale(1);   opacity: 0.35; }
          80%  { transform: scale(1.6); opacity: 0; }
          100% { transform: scale(1.6); opacity: 0; }
        }
        @keyframes aiCoreSpin {
          to { transform: rotate(360deg); }
        }
        @keyframes aiCoreEnterStatic {
          0%   { transform: scale(0.85) translateY(0); }
          70%  { transform: scale(1) translateY(0); }
          100% { transform: scale(1) translateY(-3px); }
        }
        @keyframes aiCoreFloatStatic {
          0%, 100% { transform: scale(1) translateY(-3px); }
          50%      { transform: scale(1) translateY(3px); }
        }
        @keyframes aiCoreFloatStaticOnly {
          0%, 100% { transform: translateY(-3px); }
          50%      { transform: translateY(3px); }
        }
        @keyframes aiCoreGrad {
          0%, 100% { background-position: 100% 50%; }
          50%      { background-position: 0% 50%; }
        }
        @keyframes nodeFloatA0 {
          0%, 100% { transform: translate(-50%, -50%) translateY(0); }
          50%      { transform: translate(-50%, -50%) translateY(-5px); }
        }
        @keyframes nodeFloatA1 {
          0%, 100% { transform: translate(-50%, -50%) translateY(0); }
          50%      { transform: translate(-50%, -50%) translateY(-7px); }
        }
        @keyframes nodeFloatA2 {
          0%, 100% { transform: translate(-50%, -50%) translateY(0); }
          50%      { transform: translate(-50%, -50%) translateY(-6px); }
        }
        @keyframes nodeFloatA3 {
          0%, 100% { transform: translate(-50%, -50%) translateY(0); }
          50%      { transform: translate(-50%, -50%) translateY(-4px); }
        }
        @keyframes outputFloat {
          0%, 100% { transform: translateY(-50%) translateX(0) rotateY(-6deg); }
          50%      { transform: translateY(calc(-50% - 5px)) translateX(0) rotateY(-6deg); }
        }
        @keyframes outputShimmer {
          0%, 50% { left: -100%; }
          80%, 100% { left: 100%; }
        }
      `}</style>
    </div>
  );
};

const LawUpdateA = () => {
  const data = HJ.lawUpdate;
  const { isMobile } = useViewport();
  const sectionRef = React.useRef(null);
  const [step, setStep] = React.useState(0);
  React.useEffect(() => {
    const el = sectionRef.current; if (!el) return;
    let timers = [];
    const trigger = () => {
      timers.forEach(clearTimeout);
      setStep(0);
      timers = [
        setTimeout(() => setStep(1), 300),
        setTimeout(() => setStep(2), 900),
        setTimeout(() => setStep(3), 1500),
      ];
    };
    if (typeof IntersectionObserver === "undefined") { setStep(3); return; }
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) trigger();
        else { timers.forEach(clearTimeout); setStep(0); }
      });
    }, { threshold: 0.3, root: el.closest('[data-scroll-root]') || null });
    io.observe(el);
    return () => { io.disconnect(); timers.forEach(clearTimeout); };
  }, []);

  const blockedGroup = data.groups.find((g) => g.status === "blocked");
  const openGroup = data.groups.find((g) => g.status === "open");
  void blockedGroup; void openGroup;

  return (
    <Snap id="law-update" style={isMobile ? { height: "100vh", minHeight: 0 } : { height: "100vh", minHeight: 0, padding: "100px 64px" }}>
      <div ref={sectionRef} style={{ maxWidth: 1320, margin: "0 auto", width: "100%", display: "flex", flexDirection: "column", gap: isMobile ? 32 : 100, justifyContent: "center" }}>
        {/* TOP — headline */}
        <Reveal delay={140}>
          <h2 style={{ ...aHeading, fontSize: "clamp(36px, 3.8vw, 60px)", margin: 0, whiteSpace: "pre-line", lineHeight: 1.12, textAlign: "center" }}>
            {data.title}
          </h2>
        </Reveal>

        {/* BOTTOM — diagram (no card, sits on section bg) */}
        <Reveal delay={240}>
          <AiHubDiagram step={step} />
        </Reveal>
      </div>
    </Snap>
  );
};

// ---------- 4섹션: 3채널 유입 전략 ----------
const ChannelStrategyA = () => {
  const data = HJ.channelStrategy;
  const { isMobile } = useViewport();
  return (
    <Snap id="channels" bg="#fff" style={{ borderTop: `1px solid ${A.line}`, borderBottom: `1px solid ${A.line}` }}>
      <div style={{ maxWidth: 1280, margin: "0 auto", width: "100%" }}>
        <Reveal delay={60}>
          <h2 style={{ ...aHeading, fontSize: "clamp(28px, 4.4vw, 72px)", margin: "0 auto", maxWidth: 1100, whiteSpace: "pre-line" }}>
            {data.title}
          </h2>
        </Reveal>

        {/* Hub diagram */}
        <div style={{ marginTop: isMobile ? 28 : 72, position: "relative", padding: isMobile ? "10px 0" : "20px 0" }}>
          <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : "repeat(3, 1fr)", gap: isMobile ? 10 : 20 }}>
            {data.channels.map((c, i) => (
              <Reveal key={c.name} delay={180 + i * 90}>
                <div style={{
                  background: A.bg,
                  border: `1px solid ${A.line}`,
                  borderRadius: 18,
                  padding: isMobile ? 18 : 28,
                  minHeight: isMobile ? 0 : 280,
                  display: "flex", flexDirection: "column",
                  position: "relative", overflow: "hidden",
                  transition: "transform .4s ease, box-shadow .4s ease, border-color .4s ease",
                }}
                  onMouseEnter={(e) => { if (!isMobile) { e.currentTarget.style.transform = "translateY(-4px)"; e.currentTarget.style.boxShadow = "0 20px 40px -20px rgba(10,37,64,.18)"; e.currentTarget.style.borderColor = A.lineStrong; } }}
                  onMouseLeave={(e) => { if (!isMobile) { e.currentTarget.style.transform = "translateY(0)"; e.currentTarget.style.boxShadow = "none"; e.currentTarget.style.borderColor = A.line; } }}>
                  <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
                    <div style={{ width: isMobile ? 36 : 44, height: isMobile ? 36 : 44, borderRadius: 12, background: A.accentSoft, color: A.accent, display: "flex", alignItems: "center", justifyContent: "center" }}>
                      <Icon kind={c.k} size={isMobile ? 18 : 22} />
                    </div>
                    <span style={{ fontSize: 11, fontWeight: 700, letterSpacing: ".1em", color: A.ink3, fontFamily: "var(--font-display)", textTransform: "uppercase" }}>
                      {c.platform}
                    </span>
                  </div>
                  <h3 style={{ fontSize: isMobile ? 22 : 30, fontWeight: 700, letterSpacing: "-.02em", margin: isMobile ? "12px 0 2px" : "20px 0 4px", color: A.ink, fontFamily: "var(--font-display)" }}>
                    {c.name}
                  </h3>
                  <div style={{ fontSize: isMobile ? 13 : 14, fontWeight: 600, color: A.accent, marginBottom: isMobile ? 8 : 14 }}>{c.role}</div>
                  <p style={{ fontSize: isMobile ? 13.5 : 14.5, lineHeight: 1.6, color: A.ink2, margin: 0, wordBreak: "keep-all" }}>
                    {c.desc}
                  </p>
                  <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginTop: isMobile ? 12 : 20 }}>
                    {c.formats.map((f) => (
                      <span key={f} style={{ fontSize: 12, fontWeight: 500, padding: "5px 10px", borderRadius: 999, background: "#fff", border: `1px solid ${A.line}`, color: A.ink2 }}>
                        {f}
                      </span>
                    ))}
                  </div>
                </div>
              </Reveal>
            ))}
          </div>

          {/* Hub footer */}
          <Reveal delay={460}>
            <div style={{
              marginTop: isMobile ? 14 : 28,
              padding: isMobile ? "16px 18px" : "20px 28px",
              borderRadius: 14, background: A.ink, color: "#fff",
              display: "flex",
              flexDirection: isMobile ? "column" : "row",
              alignItems: isMobile ? "flex-start" : "center",
              justifyContent: "space-between",
              gap: isMobile ? 8 : 16,
              position: "relative", overflow: "hidden",
            }}>
              <div aria-hidden style={{ position: "absolute", inset: 0, background: `radial-gradient(circle at 0% 50%, ${A.accent}55, transparent 50%)`, pointerEvents: "none" }} />
              <div style={{ position: "relative", display: "flex", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
                <span style={{ width: 8, height: 8, borderRadius: 999, background: A.accent, boxShadow: `0 0 0 6px ${A.accent}33` }} />
                <span style={{ fontSize: 12, fontWeight: 700, letterSpacing: ".1em", textTransform: "uppercase", fontFamily: "var(--font-display)", color: "rgba(255,255,255,.65)" }}>HUB</span>
                <span style={{ fontSize: isMobile ? 16 : 18, fontWeight: 600, letterSpacing: "-.01em" }}>병원 자체 홈페이지</span>
              </div>
              <div style={{ position: "relative", fontSize: isMobile ? 12.5 : 14, color: "rgba(255,255,255,.7)", wordBreak: "keep-all" }}>
                3개 채널의 유입을 모두 모으는 최종 도착지
              </div>
            </div>
          </Reveal>
        </div>
      </div>
    </Snap>
  );
};

// ---------- 5섹션 (Part 1): 마케팅 가격 ----------
const PricingMarketingA = () => {
  const data = HJ.pricingV2;
  const { isMobile, isTablet } = useViewport();
  return (
    <Snap id="pricing-marketing">
      <div style={{ maxWidth: 1280, margin: "0 auto", width: "100%" }}>
        <Reveal delay={60}>
          <h2 style={{ ...aHeading, fontSize: "clamp(28px, 4.4vw, 72px)", margin: 0 }}>
            {data.marketing.title}
          </h2>
        </Reveal>

        <div style={{ marginTop: isMobile ? 28 : 64 }}>
          <div style={{ display: "grid", gridTemplateColumns: isMobile ? "1fr" : isTablet ? "repeat(2, 1fr)" : "repeat(3, 1fr)", gap: isMobile ? 10 : 16 }}>
            {data.marketing.items.map((m, i) => (
              <Reveal key={m.name} delay={140 + i * 80}>
                <div style={{
                  background: "#fff",
                  border: `1px solid ${A.line}`,
                  borderRadius: 18,
                  padding: isMobile ? 18 : 28,
                  minHeight: isMobile ? 0 : 280,
                  display: "flex", flexDirection: "column",
                  transition: "transform .4s ease, box-shadow .4s ease, border-color .4s ease",
                }}
                  onMouseEnter={(e) => { if (!isMobile) { e.currentTarget.style.transform = "translateY(-4px)"; e.currentTarget.style.boxShadow = "0 20px 40px -20px rgba(10,37,64,.18)"; e.currentTarget.style.borderColor = A.lineStrong; } }}
                  onMouseLeave={(e) => { if (!isMobile) { e.currentTarget.style.transform = "translateY(0)"; e.currentTarget.style.boxShadow = "none"; e.currentTarget.style.borderColor = A.line; } }}>
                  <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                    <span style={{ fontSize: 22, fontWeight: 700, fontFamily: "var(--font-display)", color: A.ink, letterSpacing: "-.01em" }}>{m.name}</span>
                    <span style={{ fontSize: 12, fontWeight: 600, padding: "3px 10px", borderRadius: 999, background: A.accentSoft, color: A.accent, letterSpacing: ".02em" }}>{m.channel}</span>
                  </div>
                  <p style={{ marginTop: 8, fontSize: 14, color: A.ink2, lineHeight: 1.6 }}>{m.desc}</p>
                  <ul style={{ listStyle: "none", padding: 0, margin: "20px 0 0", display: "flex", flexDirection: "column", gap: 10 }}>
                    {m.rows.map((r) => (
                      <li key={r.label} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "12px 0", borderTop: `1px solid ${A.line}` }}>
                        <span style={{ fontSize: 14.5, color: A.ink2 }}>{r.label}</span>
                        <span style={{ fontSize: 16, fontWeight: 700, color: A.ink, fontFamily: "var(--font-display)", letterSpacing: "-.01em" }}>{r.price}</span>
                      </li>
                    ))}
                  </ul>
                </div>
              </Reveal>
            ))}
          </div>

          {/* Marketing PACKAGE */}
          <Reveal delay={400}>
            <div style={{
              marginTop: isMobile ? 12 : 20,
              background: A.ink,
              color: "#fff",
              borderRadius: 20,
              padding: isMobile ? 22 : 40,
              position: "relative", overflow: "hidden",
              display: "grid",
              gridTemplateColumns: isMobile ? "1fr" : "1.4fr 1fr",
              gap: isMobile ? 18 : 40,
              alignItems: "center",
              boxShadow: "0 30px 60px -20px rgba(10,37,64,.4)",
            }}>
              <div aria-hidden style={{ position: "absolute", inset: 0, background: `radial-gradient(circle at 100% 0%, ${A.accent}55, transparent 55%)`, pointerEvents: "none" }} />
              <div style={{ position: "relative" }}>
                <div style={{ display: "inline-flex", alignItems: "center", gap: 8, padding: "5px 12px", borderRadius: 999, background: "rgba(255,255,255,.1)", border: "1px solid rgba(255,255,255,.16)", fontSize: 12, fontWeight: 700, letterSpacing: ".06em", color: "#fff", marginBottom: 16 }}>
                  <span style={{ width: 6, height: 6, borderRadius: 999, background: A.accent }} />
                  PACKAGE
                </div>
                <h4 style={{ fontSize: isMobile ? 22 : 32, fontWeight: 700, letterSpacing: "-.02em", margin: "0 0 6px" }}>{data.marketing.package.name}</h4>
                <div style={{ fontSize: isMobile ? 13 : 14.5, color: "rgba(255,255,255,.7)", marginBottom: isMobile ? 14 : 22, wordBreak: "keep-all" }}>{data.marketing.package.sub}</div>
                <ul style={{ listStyle: "none", padding: 0, margin: 0, display: "flex", flexDirection: "column", gap: 10 }}>
                  {data.marketing.package.rows.map((r) => (
                    <li key={r.label} style={{ display: "flex", alignItems: "center", gap: 12, fontSize: 14.5, color: "rgba(255,255,255,.85)" }}>
                      <Icon kind="check" size={15} color={A.accent} strokeWidth={2.5} />
                      <span>{r.label}</span>
                      <span style={{ fontSize: 11, padding: "3px 8px", borderRadius: 999, background: "rgba(255,255,255,.08)", color: "rgba(255,255,255,.55)", letterSpacing: ".05em", fontFamily: "var(--font-display)" }}>{r.note}</span>
                    </li>
                  ))}
                </ul>
              </div>
              <div style={{ position: "relative", textAlign: isMobile ? "left" : "right" }}>
                <div style={{ fontSize: 13, color: "rgba(255,255,255,.5)", letterSpacing: ".1em", textTransform: "uppercase", fontFamily: "var(--font-display)", fontWeight: 600 }}>월 정액</div>
                <div style={{ fontFamily: "var(--font-display)", fontSize: isMobile ? 38 : 56, fontWeight: 700, letterSpacing: "-.02em", marginTop: 6 }}>{data.marketing.package.price}</div>
                <div style={{ fontSize: 13, color: A.accent, marginTop: 6, fontWeight: 600 }}>{data.marketing.package.save}</div>
              </div>
            </div>
          </Reveal>
        </div>
      </div>
    </Snap>
  );
};

// ---------- 5섹션 (Part 2): 홈페이지 가격 ----------
const PricingHomepageA = () => {
  const data = HJ.pricingV2;
  const { isMobile, isTablet } = useViewport();
  return (
    <Snap id="pricing-homepage" bg="#fff" style={{ borderTop: `1px solid ${A.line}`, borderBottom: `1px solid ${A.line}` }}>
      <div style={{ maxWidth: 1280, margin: "0 auto", width: "100%" }}>
        <Reveal delay={60}>
          <h2 style={{ ...aHeading, fontSize: "clamp(28px, 4.4vw, 72px)", margin: 0 }}>
            {data.homepage.title}
          </h2>
        </Reveal>
        <div style={{
          marginTop: isMobile ? 28 : 64,
          display: "grid",
          gridTemplateColumns: isMobile ? "1fr" : isTablet ? "repeat(2, 1fr)" : "repeat(4, 1fr)",
          gap: isMobile ? 10 : 16,
        }}>
            {data.homepage.items.map((p, i) => {
              const featured = i === 3;
              return (
                <Reveal key={p.name} delay={120 + i * 70}>
                  <div style={{
                    background: featured ? A.ink : A.bg,
                    color: featured ? "#fff" : A.ink,
                    border: `1px solid ${featured ? "transparent" : A.line}`,
                    borderRadius: 18,
                    padding: isMobile ? 20 : 28,
                    minHeight: isMobile ? 0 : 480,
                    display: "flex", flexDirection: "column",
                    position: "relative", overflow: "hidden",
                    boxShadow: featured ? "0 30px 60px -20px rgba(10,37,64,.35)" : "none",
                    transition: "transform .4s ease, box-shadow .4s ease",
                  }}
                    onMouseEnter={(e) => { if (!isMobile) e.currentTarget.style.transform = "translateY(-4px)"; }}
                    onMouseLeave={(e) => { if (!isMobile) e.currentTarget.style.transform = "translateY(0)"; }}>
                    {featured && (
                      <div aria-hidden style={{ position: "absolute", inset: 0, background: `radial-gradient(circle at 100% 0%, ${A.accent}55, transparent 55%)`, pointerEvents: "none" }} />
                    )}
                    {featured && (
                      <div style={{ display: "inline-flex", alignSelf: "flex-start", alignItems: "center", gap: 8, position: "relative", background: A.accent, color: "#fff", fontSize: 12, fontWeight: 700, padding: "5px 12px", borderRadius: 999, letterSpacing: ".02em", marginBottom: 14 }}>
                        <span style={{ width: 5, height: 5, borderRadius: 999, background: "#fff" }} />
                        한정 모집
                      </div>
                    )}
                    <div style={{ fontSize: 12, fontWeight: 700, letterSpacing: ".12em", color: featured ? "rgba(255,255,255,.85)" : A.accent, textTransform: "uppercase", position: "relative" }}>{p.tag}</div>
                    <h3 style={{ fontSize: isMobile ? 20 : 24, fontWeight: 700, letterSpacing: "-.02em", margin: "10px 0 6px", color: featured ? "#fff" : A.ink, position: "relative", wordBreak: "keep-all" }}>{p.name}</h3>
                    <div style={{ fontFamily: "var(--font-display)", fontSize: isMobile ? 26 : 32, fontWeight: 700, color: featured ? "#fff" : A.ink, letterSpacing: "-.02em", marginTop: isMobile ? 6 : 10, position: "relative" }}>{p.price}</div>
                    <p style={{ fontSize: isMobile ? 13.5 : 14, lineHeight: 1.6, color: featured ? "rgba(255,255,255,.78)" : A.ink2, margin: isMobile ? "12px 0 10px" : "20px 0 16px", position: "relative", wordBreak: "keep-all" }}>{p.desc}</p>
                    <ul style={{ listStyle: "none", padding: 0, margin: isMobile ? "0 0 14px" : "0 0 20px", display: "flex", flexDirection: "column", gap: isMobile ? 6 : 10, position: "relative" }}>
                      {p.points.map((pt) => (
                        <li key={pt} style={{ display: "flex", gap: 10, fontSize: 13.5, alignItems: "center", color: featured ? "rgba(255,255,255,.85)" : A.ink2 }}>
                          <Icon kind="check" size={14} color={A.accent} strokeWidth={2.5} />
                          {pt}
                        </li>
                      ))}
                    </ul>
                    <button style={{
                      marginTop: "auto",
                      background: featured ? A.accent : "transparent",
                      color: featured ? "#fff" : A.ink,
                      border: featured ? "none" : `1px solid ${A.lineStrong}`,
                      padding: isMobile ? "14px 16px" : "13px 16px",
                      borderRadius: 12,
                      fontSize: 14, fontWeight: 600, cursor: "pointer", fontFamily: "var(--font-sans)",
                      display: "flex", alignItems: "center", justifyContent: "space-between",
                      position: "relative",
                      minHeight: 48,
                    }}>
                      상담 요청 <Icon kind="arrow" size={14} />
                    </button>
                  </div>
                </Reveal>
              );
            })}
          </div>
      </div>
    </Snap>
  );
};

// ---------- COMPARE ----------
const CompareA = () => {
  const sectionRef = React.useRef(null);
  const { isMobile } = useViewport();
  const [revealedRows, setRevealedRows] = React.useState(0);
  React.useEffect(() => {
    const el = sectionRef.current; if (!el) return;
    if (typeof IntersectionObserver === "undefined") {
      setRevealedRows(HJ.compare.rows.length);
      return;
    }
    let intervalId = null;
    const io = new IntersectionObserver((entries) => {
      entries.forEach((e) => {
        if (e.isIntersecting) {
          if (intervalId) clearInterval(intervalId);
          let i = 0;
          setRevealedRows(0);
          intervalId = setInterval(() => {
            i += 1;
            setRevealedRows(i);
            if (i >= HJ.compare.rows.length) { clearInterval(intervalId); intervalId = null; }
          }, 180);
        } else {
          if (intervalId) { clearInterval(intervalId); intervalId = null; }
          setRevealedRows(0);
        }
      });
    }, { threshold: 0.25, root: el.closest('[data-scroll-root]') || null });
    io.observe(el);
    return () => { io.disconnect(); if (intervalId) clearInterval(intervalId); };
  }, []);

  return (
    <Snap id="compare" bg="#fff" style={{ borderTop: `1px solid ${A.line}`, borderBottom: `1px solid ${A.line}` }}>
      <div ref={sectionRef} style={{ maxWidth: 1280, margin: "0 auto", width: "100%" }}>
        <Reveal delay={80}>
          <h2 style={{ ...aHeading, fontSize: "clamp(28px, 4.4vw, 72px)", margin: 0 }}>
            나란히 두면<br /><span style={{ color: A.accent }}>분명해집니다</span>
          </h2>
        </Reveal>
        <Reveal delay={160}>
          {isMobile ? (
            <div style={{ marginTop: 24, display: "flex", flexDirection: "column", gap: 10, maxHeight: "60vh", overflowY: "auto", paddingRight: 4 }}>
              {HJ.compare.rows.map((r, i) => {
                const shown = i < revealedRows;
                return (
                  <div key={r.axis} style={{
                    border: `1px solid ${A.line}`,
                    borderRadius: 14,
                    padding: 14,
                    background: "#fff",
                    opacity: shown ? 1 : 0,
                    transform: shown ? "translateX(0)" : "translateX(-12px)",
                    transition: "opacity .5s ease, transform .5s cubic-bezier(.2,.7,.2,1)",
                  }}>
                    <div style={{ fontSize: 11, fontWeight: 700, color: A.ink3, letterSpacing: ".08em", textTransform: "uppercase", marginBottom: 8 }}>{r.axis}</div>
                    <div style={{ display: "flex", alignItems: "center", gap: 10, fontSize: 14, color: A.ink2, marginBottom: 8, wordBreak: "keep-all" }}>
                      <span style={{ width: 22, height: 22, borderRadius: 999, background: "#F4F5F7", display: "inline-flex", alignItems: "center", justifyContent: "center", color: "#94A0B0", flexShrink: 0 }}>
                        <Icon kind="x" size={12} strokeWidth={2} />
                      </span>
                      <span style={{ flex: 1 }}>{r.a}</span>
                      <span style={{ fontSize: 10.5, color: A.ink3, letterSpacing: ".05em", textTransform: "uppercase" }}>일반</span>
                    </div>
                    <div style={{ display: "flex", alignItems: "center", gap: 10, fontSize: 14, color: A.ink, fontWeight: 500, wordBreak: "keep-all" }}>
                      <span style={{ width: 22, height: 22, borderRadius: 999, background: A.accent, display: "inline-flex", alignItems: "center", justifyContent: "center", color: "#fff", flexShrink: 0 }}>
                        <Icon kind="check" size={12} strokeWidth={2.5} />
                      </span>
                      <span style={{ flex: 1 }}>{r.b}</span>
                      <span style={{ fontSize: 10.5, color: A.accent, letterSpacing: ".05em", textTransform: "uppercase", fontWeight: 700 }}>HJ</span>
                    </div>
                  </div>
                );
              })}
            </div>
          ) : (
          <div style={{ marginTop: 64, border: `1px solid ${A.line}`, borderRadius: 20, overflow: "hidden", background: "#fff" }}>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", background: A.bg, padding: "22px 28px", borderBottom: `1px solid ${A.line}`, fontSize: 13, color: A.ink3, fontWeight: 700, letterSpacing: ".08em", textTransform: "uppercase" }}>
              <div>비교 항목</div>
              <div>일반 마케팅 업체</div>
              <div style={{ color: A.accent }}>HJ기획</div>
            </div>
            {HJ.compare.rows.map((r, i) => {
              const shown = i < revealedRows;
              return (
                <div key={r.axis} style={{
                  display: "grid", gridTemplateColumns: "1fr 1fr 1fr",
                  padding: "24px 28px",
                  borderBottom: i === HJ.compare.rows.length - 1 ? "none" : `1px solid ${A.line}`,
                  alignItems: "center", fontSize: 16,
                  opacity: shown ? 1 : 0,
                  transform: shown ? "translateX(0)" : "translateX(-12px)",
                  transition: "opacity .5s ease, transform .5s cubic-bezier(.2,.7,.2,1)",
                }}>
                  <div style={{ fontWeight: 600, color: A.ink }}>{r.axis}</div>
                  <div style={{ display: "flex", alignItems: "center", gap: 12, color: A.ink2 }}>
                    <span style={{ width: 24, height: 24, borderRadius: 999, background: "#F4F5F7", display: "inline-flex", alignItems: "center", justifyContent: "center", color: "#94A0B0", flexShrink: 0 }}>
                      <Icon kind="x" size={13} strokeWidth={2} />
                    </span>
                    {r.a}
                  </div>
                  <div style={{ display: "flex", alignItems: "center", gap: 12, color: A.ink, fontWeight: 500 }}>
                    <span style={{ width: 24, height: 24, borderRadius: 999, background: A.accent, display: "inline-flex", alignItems: "center", justifyContent: "center", color: "#fff", flexShrink: 0 }}>
                      <Icon kind="check" size={13} strokeWidth={2.5} />
                    </span>
                    {r.b}
                  </div>
                </div>
              );
            })}
          </div>
          )}
        </Reveal>
      </div>
    </Snap>
  );
};

// ---------- FAQ ----------
const FaqA = () => {
  const [open, setOpen] = React.useState(0);
  const items = HJ.faq;
  const { isMobile } = useViewport();
  return (
    <Snap id="faq">
      <div style={{ maxWidth: 1080, margin: "0 auto", width: "100%" }}>
        <Reveal delay={80}>
          <h2 style={{ ...aHeading, fontSize: "clamp(28px, 4.4vw, 72px)", margin: 0 }}>자주 묻는 질문</h2>
        </Reveal>
        <div style={{ marginTop: isMobile ? 24 : 56, borderTop: `1px solid ${A.lineStrong}` }}>
          {items.map((f, i) => {
            const isOpen = open === i;
            return (
              <Reveal key={i} delay={i * 60}>
                <div style={{ borderBottom: `1px solid ${A.line}` }}>
                  <button onClick={() => setOpen(isOpen ? -1 : i)} style={{
                    width: "100%", textAlign: "left",
                    padding: isMobile ? "18px 0" : "28px 0",
                    background: "transparent", border: "none", cursor: "pointer",
                    display: "flex", alignItems: "center", justifyContent: "space-between",
                    fontFamily: "var(--font-sans)", color: A.ink,
                    gap: isMobile ? 12 : 24,
                    minHeight: 56,
                  }}>
                    <span style={{ fontSize: isMobile ? 15.5 : "clamp(18px, 1.5vw, 22px)", fontWeight: 600, letterSpacing: "-.01em", wordBreak: "keep-all", lineHeight: 1.4 }}>{f.q}</span>
                    <span style={{
                      width: isMobile ? 36 : 40, height: isMobile ? 36 : 40, borderRadius: 999,
                      background: isOpen ? A.ink : "#fff",
                      color: isOpen ? "#fff" : A.ink,
                      border: `1px solid ${isOpen ? A.ink : A.line}`,
                      display: "inline-flex", alignItems: "center", justifyContent: "center",
                      transition: "all .3s ease", flexShrink: 0,
                      transform: isOpen ? "rotate(180deg)" : "rotate(0deg)",
                    }}>
                      <Icon kind={isOpen ? "minus" : "plus"} size={isMobile ? 16 : 18} />
                    </span>
                  </button>
                  <div style={{
                    maxHeight: isOpen ? (isMobile ? 320 : 220) : 0,
                    overflow: "hidden",
                    transition: "max-height .4s ease, opacity .4s ease, padding .4s ease",
                    opacity: isOpen ? 1 : 0,
                    paddingBottom: isOpen ? (isMobile ? 18 : 28) : 0,
                  }}>
                    <p style={{ fontSize: isMobile ? 14.5 : 17, color: A.ink2, lineHeight: 1.7, margin: 0, maxWidth: 820, wordBreak: "keep-all" }}>{f.a}</p>
                  </div>
                </div>
              </Reveal>
            );
          })}
        </div>
      </div>
    </Snap>
  );
};

// ---------- FINAL CTA ----------
const CtaA = () => {
  const { isMobile } = useViewport();
  return (
  <Snap id="cta" style={isMobile ? {} : { padding: "80px 64px" }}>
    <div style={{ maxWidth: 1280, margin: "0 auto", width: "100%" }}>
      <div style={{
        background: A.ink,
        borderRadius: isMobile ? 20 : 28,
        padding: isMobile ? "56px 24px" : "120px 80px",
        color: "#fff", position: "relative", overflow: "hidden",
      }}>
        <div aria-hidden style={{
          position: "absolute", inset: 0,
          background: `radial-gradient(circle at 90% 10%, ${A.accent}66, transparent 50%), radial-gradient(circle at 10% 90%, #0E9F6E33, transparent 50%)`,
          animation: "floatY 8s ease-in-out infinite",
        }} />
        <div style={{ position: "relative", textAlign: "center" }}>
          <Reveal>
            <h2 style={{ fontSize: "clamp(36px, 4.6vw, 80px)", fontWeight: 700, letterSpacing: "-.03em", lineHeight: 1.2, margin: 0, wordBreak: "keep-all" }}>
              지금 <span style={{
                background: `linear-gradient(110deg, #fff 25%, ${A.accent} 50%, #fff 75%)`,
                backgroundSize: "200% 100%",
                WebkitBackgroundClip: "text",
                backgroundClip: "text",
                color: "transparent",
                animation: "shimmerA 6s linear infinite",
              }}>AI시대</span>에<br />대응하셔야 됩니다
            </h2>
          </Reveal>
          <Reveal delay={220}>
            <div style={{
              display: "flex",
              gap: isMobile ? 10 : 14,
              marginTop: isMobile ? 32 : 64,
              justifyContent: "center",
              flexDirection: isMobile ? "column" : "row",
              alignItems: isMobile ? "stretch" : "center",
              flexWrap: "wrap",
            }}>
              <button style={{
                background: "#FEE500", color: "#000", border: "none",
                padding: isMobile ? "16px 24px" : "20px 28px",
                borderRadius: 14, fontSize: isMobile ? 16 : 17, fontWeight: 700, cursor: "pointer",
                fontFamily: "var(--font-sans)",
                display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 12,
                animation: "pulseGlow 2.4s ease-in-out infinite",
                minHeight: 52,
              }}>
                <Icon kind="kakao" size={18} color="#000" />
                카카오톡 상담하기
              </button>
              <button style={{
                background: "rgba(255,255,255,.08)", color: "#fff",
                border: "1px solid rgba(255,255,255,.18)",
                padding: isMobile ? "16px 24px" : "20px 28px",
                borderRadius: 14, fontSize: isMobile ? 16 : 17, fontWeight: 600, cursor: "pointer",
                fontFamily: "var(--font-sans)",
                minHeight: 52,
              }}>견적 메일 받기</button>
            </div>
          </Reveal>
        </div>
      </div>
      <footer style={{
        padding: isMobile ? "24px 0 0" : "48px 0 0",
        display: "flex",
        flexDirection: isMobile ? "column" : "row",
        justifyContent: "space-between",
        alignItems: isMobile ? "flex-start" : "center",
        color: A.ink3, fontSize: isMobile ? 12 : 13, flexWrap: "wrap",
        gap: isMobile ? 8 : 16,
      }}>
        <div>© 2026 닥터트래픽. All rights reserved.</div>
        <div style={{ display: "flex", gap: isMobile ? 14 : 24, flexWrap: "wrap" }}>
          <a style={{ color: A.ink3, cursor: "pointer" }}>이용약관</a>
          <a style={{ color: A.ink3, cursor: "pointer" }}>개인정보처리방침</a>
          <a style={{ color: A.ink3, cursor: "pointer" }}>사업자정보</a>
        </div>
      </footer>
    </div>
  </Snap>
  );
};

// ---------- ROOT ----------
const VariationA = () => {
  const scrollRef = React.useRef(null);

  React.useEffect(() => {
    const root = scrollRef.current;
    if (!root) return;

    let isAnimating = false;
    let animationId = null;
    let lastWheelEnd = 0;
    const COOLDOWN = 120; // ms after animation before next wheel registers (filters trackpad inertia)
    const DURATION = 1400; // ms — section transition duration; tune for feel

    const easeInOutCubic = (t) => (t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2);

    const animateTo = (target) => {
      if (animationId) cancelAnimationFrame(animationId);
      isAnimating = true;
      const start = root.scrollTop;
      const distance = target - start;
      const startTime = performance.now();
      const step = (now) => {
        const elapsed = now - startTime;
        const t = Math.min(elapsed / DURATION, 1);
        root.scrollTop = start + distance * easeInOutCubic(t);
        if (t < 1) {
          animationId = requestAnimationFrame(step);
        } else {
          isAnimating = false;
          animationId = null;
          lastWheelEnd = performance.now();
        }
      };
      animationId = requestAnimationFrame(step);
    };

    const sectionsList = () => Array.from(root.querySelectorAll("section"));

    const currentIndex = () => {
      const sections = sectionsList();
      const top = root.scrollTop;
      let bestIdx = 0, bestDist = Infinity;
      sections.forEach((s, i) => {
        const d = Math.abs(s.offsetTop - top);
        if (d < bestDist) { bestDist = d; bestIdx = i; }
      });
      return bestIdx;
    };

    const onWheel = (e) => {
      e.preventDefault();
      // Suppress when mobile menu (or any modal) has body scroll lock active
      if (document.body.style.overflow === "hidden") return;
      const now = performance.now();
      if (isAnimating) return;
      if (now - lastWheelEnd < COOLDOWN) return;
      const sections = sectionsList();
      if (!sections.length) return;
      const cur = currentIndex();
      const dir = e.deltaY > 0 ? 1 : -1;
      const next = Math.max(0, Math.min(sections.length - 1, cur + dir));
      if (next === cur) return;
      animateTo(sections[next].offsetTop);
    };

    const onKey = (e) => {
      const keys = ["ArrowDown", "ArrowUp", "PageDown", "PageUp", "Home", "End", " "];
      if (!keys.includes(e.key)) return;
      if (document.body.style.overflow === "hidden") return;
      e.preventDefault();
      if (isAnimating) return;
      const sections = sectionsList();
      if (!sections.length) return;
      const cur = currentIndex();
      let next = cur;
      if (e.key === "ArrowDown" || e.key === "PageDown" || e.key === " ") next = cur + 1;
      else if (e.key === "ArrowUp" || e.key === "PageUp") next = cur - 1;
      else if (e.key === "Home") next = 0;
      else if (e.key === "End") next = sections.length - 1;
      next = Math.max(0, Math.min(sections.length - 1, next));
      if (next === cur) return;
      animateTo(sections[next].offsetTop);
    };

    // Expose nav-jump function so TopBar nav links use the same smooth animation
    window.__dtScrollToId = (selector) => {
      const target = root.querySelector(selector);
      if (target) animateTo(target.offsetTop);
    };

    root.addEventListener("wheel", onWheel, { passive: false });
    window.addEventListener("keydown", onKey);
    return () => {
      root.removeEventListener("wheel", onWheel);
      window.removeEventListener("keydown", onKey);
      if (animationId) cancelAnimationFrame(animationId);
      delete window.__dtScrollToId;
    };
  }, []);

  return (
    <div
      ref={scrollRef}
      data-scroll-root="true"
      className="scroll-root-100vh"
      tabIndex={0}
      style={{
        overflowY: "scroll", overflowX: "hidden",
        scrollSnapType: "y mandatory",
        background: A.bg, color: A.ink, fontFamily: "var(--font-sans)",
        outline: "none",
      }}>
      <div style={{ position: "fixed", top: 0, left: 0, right: 0, zIndex: 100 }}>
        <TopBar logoSrc="assets/logo.png" textColor={A.ink} subColor={A.ink2} ctaBg={A.ink} ctaColor="#fff" border="rgba(10,37,64,0.10)" barBg="rgba(238,240,255,0.85)" fadeColor="rgba(238,240,255,0.85)" />
      </div>
      <HeroA />
      <AiCriteriaA />
      <LawUpdateA />
      <ChannelStrategyA />
      <PricingMarketingA />
      <PricingHomepageA />
      <CompareA />
      <FaqA />
      <CtaA />
    </div>
  );
};

window.VariationA = VariationA;
