// Tilos — Landing page (single React component)
// 섹션 1: 히어로(복도 + Tilos + 양옆 앱) — 기존 디자인 그대로 유지
// 섹션 2: Why Tilos (매표소)  ·  섹션 3: Our Apps (사막+석양, 앱 카드 5개)
// 모든 배경 경로 / 앱 데이터는 상단 상수·배열로 분리 → 수치 조정 용이.

const { useState, useEffect, useRef } = React;

// ── 색 토큰 ──
const COLORS = {
  dark: "#0d1020",
  warm: "#f4c98a",
  sand: "#f3ece0",
};

// ── 섹션 배경 이미지 경로 ──
const BG = {
  corridor: "assets/bg-corridor.jpg",
  boxoffice: "assets/sec2-boxoffice.jpg",
  // 사막+석양 이미지를 여기에 넣으면 자동 적용 (없으면 따뜻한 그라데이션 placeholder)
  desert: "assets/sec3-desert.jpg",
};

// ── 글로우 / 그림자 ──
const COPY_GLOW = "0 0 24px rgba(255,255,255,0.9), 0 0 12px rgba(255,255,255,0.7)";
const BRAND_GLOW = "0 0 30px rgba(255,255,255,0.85), 0 0 14px rgba(255,255,255,0.6)";
const TEXT_SHADOW_DARK = "0 2px 18px rgba(0,0,0,0.7), 0 1px 4px rgba(0,0,0,0.6)";

// ════════════════════════════════════════════════════════════
//  섹션 1 — 히어로 데이터
// ════════════════════════════════════════════════════════════
const STAGE_W = 1440;
const STAGE_H = 1024;

const HERO_APPS = [
  { id: "retirement", name: "퇴사계산기",        image: "assets/app-retirement.png", side: "left",  rotateY: 46,  scale: 1,    left: 13,   top: 158, width: 260, height: 561 },
  { id: "quotes",     name: "JJ명언",            image: "assets/app-quotes.png",     side: "left",  rotateY: 54,  scale: 0.85, left: 296,  top: 232, width: 194, height: 420 },
  { id: "letter",     name: "미래로 보내는 편지", image: "assets/app-letter.png",     side: "right", rotateY: -54, scale: 0.85, left: 950,  top: 232, width: 194, height: 420 },
  { id: "fit",        name: "핏트레이너",         image: "assets/app-fit.png",        side: "right", rotateY: -46, scale: 1,    left: 1167, top: 158, width: 260, height: 561 },
];

const HERO_COPY = [
  "그리스 신화 속 섬 틸로스에서는 지친 이들에게 약초를 건넸습니다.",
  "Tilos는 불안한 당신에게 앱을 서비스합니다.",
];

// ════════════════════════════════════════════════════════════
//  섹션 2 — Why Tilos 데이터
// ════════════════════════════════════════════════════════════
const WHY_LINES = [
  "퇴사를 고민하는 밤에는 감정 대신 숫자를,",
  "버틸 힘이 없는 아침에는 한 문장을,",
  "흔들리는 하루에는 작은 처방 하나를.",
];
const WHY_HEADLINE = "Tilos는 직장인·학생의 불안을 해결하는 앱을 만듭니다.";

// ════════════════════════════════════════════════════════════
//  섹션 3 — Our Apps 데이터 (지그재그 배치 좌표 포함)
// ════════════════════════════════════════════════════════════

// ── 섹션3 카드 데이터 (피그마 원본 좌표 그대로) ──
// 카드 크기: 200×265 (피그마 Frame77 원본)
// lx/ly = 컨테이너 내부 로컬 좌표(px). 절대 위치 환산: x=(881+lx)/1440*100vw, y=(26+ly)/1024*100vh
// bg = 각 카드 hover 시 섹션 배경으로 전환될 이미지 경로
const APP_CARDS = [
  { id: "retirement", name: "퇴사계산기",        desc: "감정말고 숫자로.\n생존력·준비력·시장성을\n3분 만에 진단합니다.",                       lx: 0,   ly: 0,   bg: "assets/bg-retirement.jpg" },
  { id: "letter",     name: "미래로 보내는 편지", desc: "미래의 나에게 편지를 씁니다.\n그 날이 오면 도착하도록.",                            lx: 0,   ly: 353, bg: "assets/bg-letter.jpg" },
  { id: "fit",        name: "핏트레이너",         desc: "스쿼트/런지/팔올리기\n기본 동작의 자세를 AI가\n정확히 분석해줍니다.",                 lx: 0,   ly: 706, bg: "assets/bg-fit.png" },
  { id: "quotes",     name: "JJ의 명언",         desc: "AI 코치가 오늘의 당신에게\n건네는 명언 한 문장과 해설.\n아침/저녁마다 도착합니다.",   lx: 255, ly: 177, bg: "assets/bg-jj.jpg" },
  { id: "cat",        name: "교양이 키우기",      desc: "교양을 먹고 자라는\n나만의 고양이를 키웁니다.",                                    lx: 255, ly: 530, bg: "assets/bg-cat.png" },
];

// 기본 배경 — 아무 카드도 hover 안 된 상태
const SEC3_DEFAULT_BG = "assets/sec3-desert.jpg";
// 프리로드 목록
const SEC3_ALL_BGS = [SEC3_DEFAULT_BG, ...APP_CARDS.map(c => c.bg)];

// px → vw (1440 기준) / px → section-relative vh (1024 기준)
const toVW = (px) => `${(px / 1440) * 100}vw`;
const toVH = (py) => `${(py / 1024) * 100}vh`;

// ── 뷰포트 추적 (모바일 분기) ──
function useViewport() {
  const [vp, setVp] = useState({ w: window.innerWidth, h: window.innerHeight });
  useEffect(() => {
    const onResize = () => setVp({ w: window.innerWidth, h: window.innerHeight });
    window.addEventListener("resize", onResize);
    return () => window.removeEventListener("resize", onResize);
  }, []);
  return vp;
}

// prefers-reduced-motion 훅
function useReducedMotion() {
  const [reduced, setReduced] = useState(
    () => window.matchMedia("(prefers-reduced-motion: reduce)").matches
  );
  useEffect(() => {
    const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
    const fn = (e) => setReduced(e.matches);
    mq.addEventListener("change", fn);
    return () => mq.removeEventListener("change", fn);
  }, []);
  return reduced;
}

// ════════════════════════════════════════════════════════════
//  히어로 — 앱 카드 / 중앙 콘텐츠 / 무대
// ════════════════════════════════════════════════════════════
function HeroAppCard({ app }) {
  const origin = app.side === "left" ? "right center" : "left center";
  return (
    <div
      aria-label={app.name}
      className="absolute overflow-hidden rounded-md bg-cover bg-center bg-no-repeat"
      style={{
        left: app.left, top: app.top, width: app.width, height: app.height,
        backgroundImage: `url("${app.image}")`,
        transform: `rotateY(${app.rotateY}deg) scale(${app.scale})`,
        transformOrigin: origin,
        opacity: app.scale < 1 ? 0.94 : 1,
        boxShadow: "0 30px 60px rgba(0,0,0,0.5)",
        backfaceVisibility: "hidden",
      }}
    />
  );
}

function HeroCenter() {
  return (
    <div className="absolute left-1/2 top-[337px] z-10 flex -translate-x-1/2 flex-col items-center text-center">
      <h1 className="font-serif font-bold leading-none text-black"
        style={{ fontSize: 128, letterSpacing: "-0.01em", textShadow: BRAND_GLOW }}>
        Tilos
      </h1>
      <p className="mt-[18px] font-serif font-bold text-black"
        style={{ fontSize: 16, lineHeight: 1.45, textShadow: COPY_GLOW }}>
        {HERO_COPY.map((line, i) => (
          <span key={i} className="block whitespace-pre">{line}</span>
        ))}
      </p>
    </div>
  );
}

function HeroDesktop({ scale }) {
  return (
    <div className="absolute left-1/2 top-1/2"
      style={{ width: STAGE_W, height: STAGE_H, transform: `translate(-50%,-50%) scale(${scale})`, transformOrigin: "center center" }}>
      <div className="relative overflow-hidden bg-cover bg-center bg-no-repeat"
        style={{ width: STAGE_W, height: STAGE_H, backgroundImage: `url("${BG.corridor}")` }}>
        <div className="pointer-events-none absolute left-1/2 -translate-x-1/2"
          style={{
            top: 205, width: 740, height: 480, filter: "blur(2px)",
            background: "radial-gradient(ellipse 50% 50% at 50% 50%, rgba(255,255,255,0.98) 0%, rgba(255,255,255,0.95) 36%, rgba(255,255,255,0.68) 56%, rgba(255,255,255,0.26) 72%, rgba(255,255,255,0) 85%)",
          }} />
        <div className="absolute inset-0" style={{ perspective: "1150px", perspectiveOrigin: "center 45%" }}>
          {HERO_APPS.map((app) => <HeroAppCard key={app.id} app={app} />)}
        </div>
        <HeroCenter />
      </div>
    </div>
  );
}

function HeroMobile() {
  return (
    <div className="flex h-full w-full flex-col items-center justify-center text-center"
      style={{
        padding: "clamp(24px,7vw,56px)",
        background: `radial-gradient(125% 62% at 50% 44%, rgba(255,255,255,0.96) 0%, rgba(255,255,255,0.88) 30%, rgba(255,255,255,0.35) 52%, rgba(0,0,0,0) 72%), linear-gradient(rgba(6,5,7,0.55), rgba(6,5,7,0.68)), url('${BG.corridor}') center / cover no-repeat`,
      }}>
      <h1 className="font-serif font-bold leading-none text-black"
        style={{ fontSize: "clamp(64px,22vw,168px)", letterSpacing: "-0.01em", textShadow: BRAND_GLOW }}>Tilos</h1>
      <p className="mt-5 font-serif font-bold text-black"
        style={{ fontSize: "clamp(13.5px,3.4vw,22px)", lineHeight: 1.5, maxWidth: "34ch", textShadow: COPY_GLOW, textWrap: "balance" }}>
        {HERO_COPY.join(" ")}
      </p>
    </div>
  );
}

function HeroSection({ isMobile, scale }) {
  return (
    <section id="hero" data-screen-label="01 Hero"
      className="relative w-full overflow-hidden"
      style={{ height: "100vh", background: "#050507" }}>
      <header
        aria-label="Tilos navigation"
        style={{
          position: "absolute",
          top: isMobile ? 18 : 30,
          right: isMobile ? 18 : 44,
          zIndex: 40,
          display: "flex",
          alignItems: "center",
          gap: isMobile ? 14 : 26,
          fontFamily: '"Pretendard", sans-serif',
          fontSize: isMobile ? 12 : 14,
          fontWeight: 700,
          color: "rgba(255,255,255,0.92)",
          textShadow: "0 2px 10px rgba(0,0,0,0.45)",
        }}>
        {!isMobile && (
          <>
            <a href="#why" style={{ color:"inherit", textDecoration:"none" }}>Why</a>
            <a href="#apps" style={{ color:"inherit", textDecoration:"none" }}>Apps</a>
          </>
        )}
        <a href="#start"
          style={{
            color: "#111",
            textDecoration: "none",
            borderRadius: 999,
            background: "rgba(255,255,255,0.9)",
            padding: isMobile ? "8px 13px" : "10px 18px",
            boxShadow: "0 8px 24px rgba(0,0,0,0.18)",
            textShadow: "none",
            whiteSpace: "nowrap",
          }}>
          오늘의 처방
        </a>
      </header>
      {isMobile ? <HeroMobile /> : <HeroDesktop scale={scale} />}
    </section>
  );
}

// ════════════════════════════════════════════════════════════
//  섹션 2 — Why Tilos
// ════════════════════════════════════════════════════════════
function Pill({ label, color, className }) {
  return (
    <span className={`inline-flex items-center justify-center rounded-full border px-[18px] py-[6px] font-serif font-bold ${className || ""}`}
      style={{ borderColor: color, color, fontSize: 16, letterSpacing: "0.04em", whiteSpace: "nowrap" }}>
      {label}
    </span>
  );
}

function WhyTilosSection({ isMobile }) {
  return (
    <section id="why" data-screen-label="02 Why Tilos"
      className="relative flex w-full items-center justify-center overflow-hidden"
      style={{ minHeight: "100vh", background: `url('${BG.boxoffice}') center / cover no-repeat`, backgroundColor: COLORS.dark }}>
      {/* 가독성 오버레이 — 가운데로 갈수록 살짝 더 어둡게 */}
      <div className="absolute inset-0"
        style={{ background: isMobile
          ? "radial-gradient(120% 90% at 50% 50%, rgba(0,0,0,0.62) 0%, rgba(0,0,0,0.78) 100%)"
          : "radial-gradient(120% 90% at 50% 50%, rgba(0,0,0,0.5) 0%, rgba(0,0,0,0.38) 100%)" }} />
      <div className="relative z-10 flex flex-col items-center px-6 text-center text-white"
        style={{ textShadow: TEXT_SHADOW_DARK }}>
        <Pill label="WHY TILOS ?" color="rgba(255,255,255,0.92)" />
        <p className="mt-9 font-sans font-medium"
          style={{ fontSize: isMobile ? "clamp(17px,5vw,22px)" : 24, lineHeight: 1.75 }}>
          {WHY_LINES.map((line, i) => (
            <span key={i} className="block">{line}</span>
          ))}
        </p>
        <h2 className="mt-9 font-serif font-bold"
          style={{ fontSize: isMobile ? "clamp(24px,6.4vw,32px)" : 32, lineHeight: 1.45, maxWidth: isMobile ? "22ch" : undefined, whiteSpace: isMobile ? "normal" : "nowrap", wordBreak: "keep-all", textWrap: isMobile ? "balance" : undefined }}>
          {WHY_HEADLINE}
        </h2>
      </div>
    </section>
  );
}

// ════════════════════════════════════════════════════════════
//  섹션 3 — Our Apps  (크로스페이드 bg + 카드 hover)
// ════════════════════════════════════════════════════════════
function AppInfoCard({ card, idx, isActive, anyActive, onActivate, onDeactivate, onTap, mobile, reducedMotion }) {
  const CARD_W_PX = 200;
  const CARD_H_PX = 265;
  const dur = reducedMotion ? "0s" : ".25s";
  const dimmed = anyActive && !isActive;

  const inner = (
    <div style={{
      width: mobile ? "100%" : `clamp(140px, ${(CARD_W_PX/1440)*100}vw, ${CARD_W_PX}px)`,
      aspectRatio: `${CARD_W_PX} / ${CARD_H_PX}`,
      borderRadius: 10,
      background: "rgba(255,255,255,0.92)",
      backdropFilter: "blur(10px)",
      WebkitBackdropFilter: "blur(10px)",
      display: "flex",
      flexDirection: "column",
      justifyContent: "flex-end",
      padding: "0 17px 29px 16px",
      boxSizing: "border-box",
      overflow: "hidden",
      border: isActive ? "2px solid rgba(255,255,255,0.85)" : "2px solid transparent",
      boxShadow: isActive ? "0 22px 50px rgba(0,0,0,0.32)" : "0 6px 20px rgba(0,0,0,0.13)",
      transform: isActive ? "translateY(-6px)" : "translateY(0)",
      opacity: dimmed ? 0.72 : 1,
      cursor: "pointer",
      transition: `transform ${dur} cubic-bezier(.2,.7,.2,1), box-shadow ${dur} ease, border-color ${dur} ease, opacity ${dur} ease`,
    }}>
      <h3 style={{ fontFamily: '"Gowun Batang", serif', fontWeight: 700, fontSize: mobile ? 16 : "clamp(13px,1.11vw,16px)", color: "#000", lineHeight: 1, whiteSpace: "nowrap" }}>{card.name}</h3>
      <p  style={{ fontFamily: '"Gowun Batang", serif', fontWeight: 400, fontSize: mobile ? 12 : "clamp(10px,0.83vw,12px)", color: "#000", marginTop: 10, whiteSpace: "pre-line", lineHeight: 1.45 }}>{card.desc}</p>
    </div>
  );

  if (mobile) {
    return <div onClick={() => onTap(idx)} style={{ width: "100%" }}>{inner}</div>;
  }

  return (
    <div
      onMouseEnter={() => onActivate(idx)}
      onMouseLeave={() => onDeactivate()}
      style={{ position: "absolute", left: toVW(881 + card.lx), top: toVH(26 + card.ly), zIndex: Math.round(1000 - card.ly) }}>
      {inner}
    </div>
  );
}

function OurAppsSection({ isMobile }) {
  const apps = [
    { name:"퇴사계산기", bg:"assets/bg-retirement.jpg" },
    { name:"JJ의 명언", bg:"assets/bg-jj.jpg" },
    { name:"미래로 보내는 편지", bg:"assets/bg-letter.jpg" },
    { name:"교양이 키우기", bg:"assets/bg-cat.png" },
    { name:"핏트레이너", bg:"assets/bg-fit.png" },
  ];

  // 카드 텍스트와 앱 순서는 유지하고, 데스크톱은 긴 스크롤 트랙에 맞춰 크기·간격만 조정
  const CARDS = [
    { id:"retirement", name:"퇴사계산기",        desc:"감정말고 숫자로.\n생존력·준비력·시장성을\n3분 만에 진단합니다.",                       col:"left",  bg:apps[0].bg },
    { id:"quotes",     name:"JJ의 명언",         desc:"AI 코치가 오늘의 당신에게\n건네는 명언 한 문장과 해설.\n아침/저녁마다 도착합니다.",     col:"right", bg:apps[1].bg },
    { id:"letter",     name:"미래로 보내는 편지", desc:"미래의 나에게 편지를 씁니다.\n그 날이 오면 도착하도록.",                             col:"left",  bg:apps[2].bg },
    { id:"cat",        name:"교양이 키우기",      desc:"교양을 먹고 자라는\n나만의 고양이를 키웁니다.",                                      col:"right", bg:apps[3].bg },
    { id:"fit",        name:"핏트레이너",         desc:"스쿼트/런지/팔올리기\n기본 동작의 자세를 AI가\n정확히 분석해줍니다.",                   col:"left",  bg:apps[4].bg },
  ];
  const desktopCardWidth = "clamp(220px,18.75vw,300px)";
  const desktopCardHeight = "clamp(292px,24.844vw,398px)";
  const desktopCardStep = "clamp(205px,15.625vw,250px)";
  const desktopCardTops = [
    "30vh",
    `calc(30vh + ${desktopCardStep})`,
    `calc(30vh + ${desktopCardStep} + ${desktopCardStep})`,
    `calc(30vh + ${desktopCardStep} + ${desktopCardStep} + ${desktopCardStep})`,
    `calc(30vh + ${desktopCardStep} + ${desktopCardStep} + ${desktopCardStep} + ${desktopCardStep})`,
  ];
  const desktopLeftCol = "54.5vw";
  const desktopRightCol = `calc(${desktopLeftCol} + ${desktopCardWidth} + 64px)`;

  const [scrollIdx, setScrollIdx] = useState(0);
  const [hoverIdx,  setHoverIdx]  = useState(null);
  const reducedMotion = useReducedMotion();
  const xfade = reducedMotion ? "0s" : "0.6s";
  const cardRefs = useRef([]);
  const centerHitsRef = useRef(new Set());
  const activeIdx = hoverIdx !== null ? hoverIdx : scrollIdx;

  // 이미지 프리로드
  useEffect(() => {
    CARDS.forEach(c => { const img = new Image(); img.src = c.bg; });
  }, []);

  // IntersectionObserver — 중앙 band에 들어온 카드 중 화면 중앙에 가장 가까운 카드 → scrollIdx
  useEffect(() => {
    const root = document.getElementById("main-scroll");
    const rootRect = () => root ? root.getBoundingClientRect() : { top: 0, bottom: window.innerHeight, height: window.innerHeight };
    let rafId = 0;

    const pickClosestCard = () => {
      const viewport = rootRect();
      const centerY = viewport.top + viewport.height / 2;
      const centerHits = centerHitsRef.current;
      let closestIdx = 0;
      let closestDistance = Infinity;
      let hasCandidate = false;

      cardRefs.current.forEach((el, i) => {
        if (!el) return;
        const rect = el.getBoundingClientRect();
        const isVisible = rect.bottom >= viewport.top && rect.top <= viewport.bottom;
        const isCenterHit = centerHits.size === 0 || centerHits.has(i);
        if (!isVisible || !isCenterHit) return;

        const cardCenterY = rect.top + rect.height / 2;
        const distance = Math.abs(cardCenterY - centerY);
        if (distance < closestDistance) {
          closestDistance = distance;
          closestIdx = i;
          hasCandidate = true;
        }
      });

      if (hasCandidate) setScrollIdx(closestIdx);
    };

    const schedulePick = () => {
      cancelAnimationFrame(rafId);
      rafId = requestAnimationFrame(pickClosestCard);
    };

    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          const idx = Number(entry.target.dataset.appIndex);
          if (Number.isNaN(idx)) return;
          if (entry.isIntersecting) centerHitsRef.current.add(idx);
          else centerHitsRef.current.delete(idx);
        });
        schedulePick();
      },
      { root, rootMargin: "-45% 0px -45% 0px", threshold: 0 }
    );

    cardRefs.current.forEach((el) => el && observer.observe(el));
    const scrollTarget = root || window;
    scrollTarget.addEventListener("scroll", schedulePick, { passive: true });
    window.addEventListener("resize", schedulePick);
    schedulePick();

    return () => {
      cancelAnimationFrame(rafId);
      observer.disconnect();
      scrollTarget.removeEventListener("scroll", schedulePick);
      window.removeEventListener("resize", schedulePick);
    };
  }, []);

  // 크로스페이드 배경 레이어 (인라인 JSX, remount 방지)
  const bgLayersJSX = (
    <div style={{ position:"absolute", inset:0, overflow:"hidden", zIndex:0 }}>
      {CARDS.map((card, i) => (
        <div key={card.id} style={{
          position:"absolute", inset:0,
          backgroundImage:`url(${card.bg})`,
          backgroundSize:"cover", backgroundPosition:"center",
          filter: card.id === "retirement" ? "brightness(0.58) contrast(1.04)" : "none",
          opacity: activeIdx === i ? 1 : 0,
          transition:`opacity ${xfade} ease, filter ${xfade} ease`,
        }} />
      ))}
      <div style={{ position:"absolute", inset:0, background:"rgba(0,0,0,0.3)" }} />
    </div>
  );

  if (isMobile) {
  return (
    <section id="apps" data-screen-label="03 Our Apps"
        style={{ position:"relative", minHeight:"100vh", padding:"60px 24px 80px" }}>
        {bgLayersJSX}
        <div style={{ position:"relative", zIndex:1 }}>
          <div style={{ display:"flex", flexDirection:"column", alignItems:"center", gap:20, textAlign:"center", marginBottom:32 }}>
            <span style={{ alignSelf:"center", width:"fit-content", maxWidth:"max-content", display:"inline-flex", alignItems:"center", borderRadius:50, boxShadow:"inset 0 0 0 1px rgba(255,255,255,0.85)", padding:"5px 18px", fontFamily:'"Gowun Batang",serif', fontWeight:700, fontSize:16, color:"rgba(255,255,255,0.9)", whiteSpace:"nowrap", boxSizing:"border-box", flex:"0 0 auto" }}>Our Apps</span>
            <h2 style={{ fontFamily:'"Gowun Batang",serif', fontWeight:700, fontSize:"clamp(22px,7vw,32px)", lineHeight:1.35, color:"#fff", wordBreak:"keep-all", textShadow:"0 2px 10px rgba(0,0,0,0.5)" }}>당신의 오늘에 필요한 5가지 앱</h2>
          </div>
          <div style={{ display:"flex", flexDirection:"column", gap:16, maxWidth:280, margin:"0 auto" }}>
            {CARDS.map((card, i) => (
              <div key={card.id} data-app-index={i} ref={el => { cardRefs.current[i] = el; }}
                style={{ width:"100%", aspectRatio:"200/265", borderRadius:30, background:"rgba(255,255,255,0.92)", backdropFilter:"blur(8px)", WebkitBackdropFilter:"blur(8px)", boxShadow:"0 4px 20px rgba(0,0,0,0.15)", display:"flex", flexDirection:"column", justifyContent:"flex-end", padding:"0 17px 29px 16px", boxSizing:"border-box", overflow:"hidden",
                  opacity: activeIdx === i ? 1 : 0.85,
                  transition: reducedMotion ? "none" : "opacity 0.3s ease",
                }}>
                <h3 style={{ fontFamily:'"Gowun Batang",serif', fontWeight:700, fontSize:"clamp(18px,5.1vw,22px)", color:"#000", lineHeight:1 }}>{card.name}</h3>
                <p style={{ fontFamily:'"Gowun Batang",serif', fontWeight:400, fontSize:"clamp(13px,3.6vw,15px)", color:"#000", marginTop:10, whiteSpace:"pre-line", lineHeight:1.45 }}>{card.desc}</p>
              </div>
            ))}
          </div>
        </div>
      </section>
    );
  }

  return (
    <section id="apps" data-screen-label="03 Our Apps"
      style={{ position:"relative", minHeight:`calc(42vh + ${desktopCardStep} + ${desktopCardStep} + ${desktopCardStep} + ${desktopCardStep} + ${desktopCardHeight})`, overflow:"visible" }}>
      <div style={{ position:"sticky", top:0, height:"100vh", overflow:"hidden", zIndex:0 }}>
        {/* 크로스페이드 배경 */}
        {bgLayersJSX}
        {/* 왼쪽 텍스트 — 배경과 함께 고정, 카드만 긴 트랙으로 스크롤 */}
        <div style={{ position:"absolute", zIndex:2, left:"7.22vw", top:"50%", transform:"translateY(-50%)", display:"flex", flexDirection:"column", alignItems:"flex-start", gap:35 }}>
          <span style={{ display:"inline-flex", width:"fit-content", maxWidth:"max-content", alignItems:"center", borderRadius:50, boxShadow:"inset 0 0 0 1px rgba(255,255,255,0.85)", padding:"5px 18px", whiteSpace:"nowrap", fontFamily:'"Gowun Batang",serif', fontWeight:700, fontSize:16, color:"rgba(255,255,255,0.92)", lineHeight:1, boxSizing:"border-box", flex:"0 0 auto" }}>Our Apps</span>
          <h2 style={{ fontFamily:'"Gowun Batang",serif', fontWeight:700, fontSize:"clamp(22px,2.22vw,32px)", lineHeight:1, color:"#fff", whiteSpace:"nowrap", textShadow:"0 2px 12px rgba(0,0,0,0.5)" }}>당신의 오늘에 필요한 5가지 앱</h2>
        </div>
      </div>
      {/* 카드 5개 — 비율 유지, GS Energy 사업소개처럼 촘촘한 지그재그 간격으로 배치 */}
      {CARDS.map((card, i) => {
        const isFocused = activeIdx === i;
        return (
        <div key={card.id}
          data-app-index={i}
          ref={el => { cardRefs.current[i] = el; }}
          onMouseEnter={() => setHoverIdx(i)}
          onMouseLeave={() => setHoverIdx(null)}
          style={{
            position:"absolute",
            left: card.col === "right" ? desktopRightCol : desktopLeftCol,
            top:desktopCardTops[i],
            width: desktopCardWidth,
            aspectRatio:"200/265",
            borderRadius:30,
            background:isFocused ? "rgba(255,255,255,0.82)" : "#fff",
            backdropFilter:isFocused ? "blur(8px)" : "none",
            WebkitBackdropFilter:isFocused ? "blur(8px)" : "none",
            boxShadow: isFocused ? "0 18px 44px rgba(0,0,0,0.3)" : "0 4px 16px rgba(0,0,0,0.12)",
            display:"flex", flexDirection:"column", justifyContent:"flex-end",
            padding:"0 clamp(19px,1.7vw,25px) clamp(31px,2.7vw,43px) clamp(18px,1.6vw,24px)",
            boxSizing:"border-box", overflow:"hidden",
            maskImage: card.id === "retirement" ? "linear-gradient(to bottom, rgba(0,0,0,0.18) 0%, rgba(0,0,0,0.72) 18%, #000 36%)" : "none",
            WebkitMaskImage: card.id === "retirement" ? "linear-gradient(to bottom, rgba(0,0,0,0.18) 0%, rgba(0,0,0,0.72) 18%, #000 36%)" : "none",
            zIndex: 3,
            opacity: 1,
            transition: reducedMotion ? "none" : "background-color 0.28s ease, opacity 0.28s ease, box-shadow 0.28s ease",
            cursor:"default",
          }}>
          <h3 style={{ fontFamily:'"Gowun Batang",serif', fontWeight:700, fontSize:"clamp(20px,1.72vw,25px)", color:"#000", lineHeight:1, whiteSpace:"nowrap", transform:"translateY(-42px)" }}>{card.name}</h3>
          <p style={{ fontFamily:'"Gowun Batang",serif', fontWeight:400, fontSize:"clamp(13px,1.11vw,16px)", color:"rgba(0,0,0,0.82)", marginTop:14, whiteSpace:"pre-line", lineHeight:1.45, transform:"translateY(-42px)" }}>{card.desc}</p>
        </div>
        );
      })}
    </section>
  );
}

// ════════════════════════════════════════════════════════════
//  섹션 4 — CTA
// ════════════════════════════════════════════════════════════
function CTASection({ isMobile }) {
  return (
    <section id="start" data-screen-label="04 Start"
      style={{
        minHeight: isMobile ? "76vh" : "82vh",
        background: "#f6f0e7",
        color: "#111",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        padding: isMobile ? "72px 24px" : "96px 40px",
      }}>
      <div style={{
        width: "100%",
        maxWidth: 980,
        display: "flex",
        flexDirection: "column",
        alignItems: "center",
        textAlign: "center",
      }}>
        <span style={{
          display: "inline-flex",
          width: "fit-content",
          alignItems: "center",
          borderRadius: 999,
          border: "1px solid rgba(13,16,32,0.28)",
          padding: "6px 18px",
          fontFamily: '"Gowun Batang", serif',
          fontWeight: 700,
          fontSize: 15,
          color: "rgba(13,16,32,0.72)",
          whiteSpace: "nowrap",
        }}>
          START WITH TILOS
        </span>
        <h2 style={{
          marginTop: 30,
          fontFamily: '"Gowun Batang", serif',
          fontWeight: 700,
          fontSize: isMobile ? "clamp(30px,9vw,44px)" : "clamp(42px,4.6vw,66px)",
          lineHeight: 1.18,
          letterSpacing: 0,
          maxWidth: 760,
          wordBreak: "keep-all",
        }}>
          오늘의 불안에 맞는 처방을 하나 골라보세요.
        </h2>
        <p style={{
          marginTop: 24,
          fontFamily: '"Pretendard", sans-serif',
          fontSize: isMobile ? 16 : 18,
          fontWeight: 500,
          lineHeight: 1.75,
          color: "rgba(13,16,32,0.68)",
          maxWidth: 610,
          wordBreak: "keep-all",
        }}>
          숫자가 필요한 날도, 문장이 필요한 아침도, 몸을 다시 세워야 하는 순간도 있습니다.
        </p>
        <div style={{
          display: "flex",
          flexWrap: "wrap",
          justifyContent: "center",
          gap: 12,
          marginTop: 38,
        }}>
          <a href="#apps"
            style={{
              display: "inline-flex",
              alignItems: "center",
              justifyContent: "center",
              minHeight: 48,
              borderRadius: 999,
              background: "#0d1020",
              color: "#fff",
              textDecoration: "none",
              padding: "0 24px",
              fontFamily: '"Pretendard", sans-serif',
              fontWeight: 800,
              fontSize: 15,
              boxShadow: "0 14px 30px rgba(13,16,32,0.22)",
            }}>
            오늘의 처방 고르기
          </a>
          <a href="#apps"
            style={{
              display: "inline-flex",
              alignItems: "center",
              justifyContent: "center",
              minHeight: 48,
              borderRadius: 999,
              border: "1px solid rgba(13,16,32,0.24)",
              color: "#0d1020",
              textDecoration: "none",
              padding: "0 24px",
              fontFamily: '"Pretendard", sans-serif',
              fontWeight: 800,
              fontSize: 15,
              background: "rgba(255,255,255,0.38)",
            }}>
            Tilos 앱 둘러보기
          </a>
        </div>
      </div>
    </section>
  );
}

// ════════════════════════════════════════════════════════════
//  푸터
// ════════════════════════════════════════════════════════════
function Footer() {
  return (
    <footer data-screen-label="05 Footer"
      style={{
        background: "#0d1020",
        color: "#fff",
        padding: "52px clamp(24px,7vw,104px) 34px",
        fontFamily: '"Pretendard", sans-serif',
      }}>
      <div style={{
        display: "flex",
        alignItems: "flex-start",
        justifyContent: "space-between",
        gap: 34,
        flexWrap: "wrap",
      }}>
        <div>
          <strong style={{
            display: "block",
            fontFamily: '"Gowun Batang", serif',
            fontSize: 34,
            lineHeight: 1,
            fontWeight: 700,
          }}>
            Tilos
          </strong>
          <p style={{
            marginTop: 16,
            color: "rgba(255,255,255,0.64)",
            fontSize: 15,
            lineHeight: 1.7,
            maxWidth: 310,
            wordBreak: "keep-all",
          }}>
            불안한 하루에 작은 처방을 건네는 앱들.
          </p>
        </div>
        <nav aria-label="Footer navigation"
          style={{
            display: "flex",
            gap: 22,
            flexWrap: "wrap",
            fontSize: 14,
            fontWeight: 700,
          }}>
          <a href="#why" style={{ color:"rgba(255,255,255,0.78)", textDecoration:"none" }}>Why Tilos</a>
          <a href="#apps" style={{ color:"rgba(255,255,255,0.78)", textDecoration:"none" }}>Our Apps</a>
          <a href="#start" style={{ color:"rgba(255,255,255,0.78)", textDecoration:"none" }}>Start</a>
          <span style={{ color:"rgba(255,255,255,0.78)" }}>Contact</span>
        </nav>
      </div>
      <div style={{
        marginTop: 54,
        paddingTop: 22,
        borderTop: "1px solid rgba(255,255,255,0.12)",
        display: "flex",
        justifyContent: "space-between",
        gap: 18,
        flexWrap: "wrap",
        color: "rgba(255,255,255,0.46)",
        fontSize: 13,
      }}>
        <span>© 2026 Tilos. All rights reserved.</span>
        <span>Small remedies for uncertain days.</span>
      </div>
    </footer>
  );
}

// ════════════════════════════════════════════════════════════
//  루트
// ════════════════════════════════════════════════════════════
function App() {
  const { w, h } = useViewport();
  const isMobile = w <= 768 || h >= w;
  const scale = Math.max(w / STAGE_W, h / STAGE_H);

  return (
    <main id="main-scroll" style={{ overflowX: "hidden", overflowY: "scroll", height: "100vh" }}>
      <HeroSection isMobile={isMobile} scale={scale} />
      <WhyTilosSection isMobile={isMobile} />
      <OurAppsSection isMobile={isMobile} />
      <CTASection isMobile={isMobile} />
      <Footer />
    </main>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
