// 철학자 가로 타임라인 — 메인 앱 (다국어 지원)
const { useState, useEffect, useRef, useMemo, useCallback } = React;

const PHILOSOPHERS = window.PHILOSOPHERS;
const WORLD_EVENTS = window.WORLD_EVENTS;
const ERAS = window.ERAS;
const S = window.UI_STRINGS || {};

// === 언어 선택 바 ===
const LANG_OPTIONS = [
  { code: "en", label: "EN" },
  { code: "ko", label: "한" },
  { code: "ja", label: "日" },
  { code: "zh", label: "中" },
  { code: "es", label: "ES" },
  { code: "fr", label: "FR" },
  { code: "de", label: "DE" },
  { code: "ru", label: "RU" },
];

function LangSwitcher() {
  const currentLang = S.lang || "en";
  const handleSwitch = (code) => {
    if (code === currentLang) return;
    localStorage.setItem('phil-lang', code);
    window.location.href = '../' + code + '/';
  };
  return (
    <div className="lang-switcher">
      {LANG_OPTIONS.map(l => (
        <button
          key={l.code}
          className={`lang-sw-btn ${l.code === currentLang ? 'active' : ''}`}
          onClick={() => handleSwitch(l.code)}
          aria-label={l.code}
        >
          {l.label}
        </button>
      ))}
    </div>
  );
}

const ERA_CUTS_ALL = {
  // 철학 (philosophy)
  ancient: [-2000, 250],
  medieval: [250, 1400],
  renaissance: [1400, 1700],
  enlightenment: [1700, 1800],
  modern19: [1800, 1880],
  modern20: [1880, 2100],
  // 신학 (theology)
  apostolic: [-50, 500],
  reformation: [1400, 1600],
  modern_early: [1600, 1800],
  // 과학 (science)
  sci_ancient: [-700, 500],
  sci_medieval: [500, 1500],
  sci_revolution: [1473, 1700],
  sci_enlightenment: [1700, 1800],
  sci_19th: [1790, 1880],
  sci_modern: [1856, 1945],
  sci_atomic: [1900, 1970],
  sci_contemporary: [1940, 2100],
  // 문학 (literature)
  lit_ancient: [-900, 500],
  lit_medieval: [500, 1400],
  lit_renaissance: [1400, 1650],
  lit_enlightenment: [1650, 1800],
  lit_romantic: [1770, 1850],
  lit_realism: [1820, 1900],
  lit_modern: [1880, 1945],
  lit_contemporary: [1920, 2100],
  // 지도자 (leaders)
  lead_ancient: [-2000, 500],
  lead_medieval: [500, 1500],
  lead_early_modern: [1500, 1789],
  lead_revolution: [1789, 1914],
  lead_world_wars: [1860, 1950],
  lead_cold_war: [1900, 1991],
  lead_contemporary: [1920, 2100],
  // 장군 (generals)
  gen_ancient: [-600, 500],
  gen_medieval: [500, 1500],
  gen_early_modern: [1500, 1789],
  gen_napoleon: [1789, 1870],
  gen_imperial: [1870, 1939],
  gen_wwii: [1939, 1945],
  gen_modern: [1945, 2100],
};
const ERA_CUTS = {};
ERAS.forEach(e => { ERA_CUTS[e.id] = ERA_CUTS_ALL[e.id] || [0, 2100]; });

const LANE_OFFSETS = [-310, 185, -245, 95];
const LANE_CONNECTOR = [130, 185, 65, 95];
const LANE_ABOVE = [true, false, true, false];

function formatYear(y) {
  if (y === null || y === undefined) return "";
  if (y < 0) return `BC ${Math.abs(y)}`;
  return `${y}`;
}

function getPortraitSrc(id) {
  const path = window.location.pathname;
  if (path.includes('/theology/')) return `../../photos/theology/${id}.jpg`;
  if (path.includes('/literature/')) return `../../photos/literacy/${id}.jpg`;
  if (path.includes('/science/')) return `../../photos/scientist/${id}.jpg`;
  if (path.includes('/generals/')) return `../../photos/commander/${id}.jpg`;
  if (path.includes('/leaders/')) return `../../photos/leader/${id}.jpg`;
  return `../photos/philosophy/${id}.jpg`;
}

// === 시대 레이아웃 계산 ===
function computeEraLayout(era) {
  const eraId = era.id;
  const philosophers = PHILOSOPHERS
    .filter(p => p.era === eraId)
    .sort((a, b) => a.year - b.year);

  const [cutLo, cutHi] = ERA_CUTS[eraId];
  const events = WORLD_EVENTS
    .filter(e => e.year >= cutLo && e.year < cutHi)
    .sort((a, b) => a.year - b.year);

  const yearsP = philosophers.map(p => p.year);
  const yearsE = events.map(e => e.year);
  const allYears = [...yearsP, ...yearsE];
  const yMin = allYears.length ? Math.min(...allYears) : cutLo;
  const yMax = allYears.length ? Math.max(...allYears) : cutHi;
  const span = Math.max(1, yMax - yMin);

  const PAD = 380;
  const itemSpace = 240;
  const width = Math.max(1600, PAD * 2 + philosophers.length * itemSpace);

  const yearToX = (year) => {
    const t = (year - yMin) / span;
    return PAD + t * (width - 2 * PAD);
  };

  const NUM_LANES = 4;
  const MIN_SPACING = 320;
  const CROSS_MIN_SPACING = 310;
  const OVERLAP_PAIRS = new Set(['0-2', '2-0', '1-3', '3-1']);
  const laneLastX = new Array(NUM_LANES).fill(-Infinity);
  let nextLane = 0;
  const philosopherLayout = philosophers.map(p => {
    const targetX = yearToX(p.year);
    let chosenLane = -1;
    let chosenX = targetX;
    for (let i = 0; i < NUM_LANES; i++) {
      const l = (nextLane + i) % NUM_LANES;
      if (laneLastX[l] + MIN_SPACING > targetX) continue;
      let crossOk = true;
      for (let cl = 0; cl < NUM_LANES; cl++) {
        if (cl !== l && OVERLAP_PAIRS.has(`${l}-${cl}`)) {
          if (laneLastX[cl] + CROSS_MIN_SPACING > targetX) { crossOk = false; break; }
        }
      }
      if (crossOk) { chosenLane = l; chosenX = targetX; break; }
    }
    if (chosenLane === -1) {
      let bestL = 0, bestEnd = Infinity;
      for (let l = 0; l < NUM_LANES; l++) {
        let maxEnd = laneLastX[l];
        for (let cl = 0; cl < NUM_LANES; cl++) {
          if (cl !== l && OVERLAP_PAIRS.has(`${l}-${cl}`)) maxEnd = Math.max(maxEnd, laneLastX[cl]);
        }
        if (maxEnd < bestEnd) { bestEnd = maxEnd; bestL = l; }
      }
      chosenLane = bestL;
      chosenX = bestEnd + MIN_SPACING;
    }
    laneLastX[chosenLane] = chosenX;
    nextLane = (chosenLane + 1) % NUM_LANES;
    return { ...p, x: chosenX, lane: chosenLane };
  });

  const EVENT_MIN_SPACING = 175;
  const eventRowLastX = [-Infinity, -Infinity];
  const eventLayout = events.map(e => {
    const targetX = yearToX(e.year);
    let row = 0;
    if (eventRowLastX[0] + EVENT_MIN_SPACING > targetX) row = 1;
    let x = targetX;
    if (eventRowLastX[row] + EVENT_MIN_SPACING > x) x = eventRowLastX[row] + EVENT_MIN_SPACING;
    eventRowLastX[row] = x;
    return { ...e, x, row };
  });

  let tickStep;
  if (span > 800) tickStep = 200;
  else if (span > 400) tickStep = 100;
  else if (span > 150) tickStep = 50;
  else tickStep = 25;
  const ticks = [];
  const startTick = Math.ceil(yMin / tickStep) * tickStep;
  for (let y = startTick; y <= yMax; y += tickStep) ticks.push({ year: y, x: yearToX(y) });

  return { width, philosopherLayout, eventLayout, ticks, yMin, yMax };
}

// === Hero 패널 ===
function HeroPanel({ width }) {
  return (
    <div className="panel hero-panel" style={{ width: `${width}px` }} data-screen-label="Hero">
      <div className="hero-eyebrow">{S.heroEyebrow || "A Journey Through Western Thought"}</div>
      <h1 className="hero-title hero-title-en">
        {S.heroTitlePre || "I am "}<em>{S.heroTitleEm || "the philosophy"}</em>
      </h1>
      <p className="hero-sub">
        <span className="hero-sub-lead serif-ko">{S.heroSubLead || ""}</span>
        {S.heroSub1 || ""}<br />
        {S.heroSub2 || ""}
      </p>
      <div className="hero-stats">
        <div className="hero-stat">
          <div className="hero-stat-num serif-en">{PHILOSOPHERS.length}</div>
          <div className="hero-stat-label">{S.statPhilosophers || "Philosophers"}</div>
        </div>
        <div className="hero-stat">
          <div className="hero-stat-num serif-en">{S.statYearsNum || "2.6K"}</div>
          <div className="hero-stat-label">{S.statYears || "Years"}</div>
        </div>
        <div className="hero-stat">
          <div className="hero-stat-num serif-en">{ERAS.length}</div>
          <div className="hero-stat-label">{S.statEras || "Eras"}</div>
        </div>
      </div>
      <div
        className="hero-scroll-indicator"
        onClick={() => window.scrollBy({ top: 480, behavior: "smooth" })}
        role="button"
        tabIndex={0}
        onKeyDown={(e) => {
          if (e.key === "Enter" || e.key === " ") { e.preventDefault(); window.scrollBy({ top: 480, behavior: "smooth" }); }
        }}
      >
        <div className="hsi-label">
          <span>{S.scrollBegin || "Scroll to begin"}</span>
          <span className="hsi-dot">◆</span>
          <span>{S.scrollBeginLocal || ""}</span>
        </div>
        <div className="hsi-track"><div className="hsi-rail"></div><div className="hsi-cursor"></div></div>
        <div className="hsi-chevrons serif-en"><span>›</span><span>›</span><span>›</span><span>›</span><span>›</span></div>
      </div>
    </div>
  );
}

// === 철학자 카드 ===
function PhilosopherCardH({ data, onClick }) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    const obs = new IntersectionObserver(entries => entries.forEach(e => { if (e.isIntersecting) setInView(true); }), { threshold: 0.15 });
    if (ref.current) obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  const lane = data.lane;
  const above = LANE_ABOVE[lane];
  const yOffset = LANE_OFFSETS[lane];
  const connectorH = LANE_CONNECTOR[lane];
  const dotStyle = above ? { top: `calc(100% + ${connectorH - 4.5}px)` } : { top: `${-connectorH - 4.5}px` };
  return (
    <div ref={ref} className={`philosopher-card-h ${above ? "above" : "below"} ${inView ? "in-view" : ""}`}
      style={{ left: `${data.x}px`, top: `calc(50% + ${yOffset}px)`, marginLeft: "-150px", "--connector-h": `${connectorH}px` }}
      onClick={() => onClick(data)} data-philosopher-id={data.id} data-year={data.year}>
      <div className="card-portrait" aria-hidden="true">
        <img src={getPortraitSrc(data.id)} alt="" loading="lazy"
          onError={(e) => { e.currentTarget.parentElement.style.display = 'none'; }} />
      </div>
      <div className="card-school-h">{data.school}</div>
      <div className="card-name-h serif-ko">{data.name}</div>
      <div className="card-name-en-h">{data.nameEn}</div>
      <div className="card-meta-row">
        <span className="card-year-h serif-en">{formatYear(data.year)}</span>
        <span className="card-region-h">{data.region}</span>
      </div>
      <div className="card-spine-dot" style={dotStyle}></div>
    </div>
  );
}

// === 세계 이벤트 마커 ===
function EventMarker({ data }) {
  const ref = useRef(null);
  const [inView, setInView] = useState(false);
  useEffect(() => {
    const obs = new IntersectionObserver(entries => entries.forEach(e => { if (e.isIntersecting) setInView(true); }), { threshold: 0.2 });
    if (ref.current) obs.observe(ref.current);
    return () => obs.disconnect();
  }, []);
  return (
    <div ref={ref} className={`event-marker-h row-${data.row} ${inView ? "in-view" : ""}`} style={{ left: `${data.x}px` }}>
      <div className="event-dot"></div>
      <div className="event-label-h">
        <div className="event-tick"></div>
        <span className="event-year serif-en">{formatYear(data.year)}</span>
        <div className="event-name serif-ko">{data.title}</div>
      </div>
    </div>
  );
}

// === Era 패널 ===
function EraPanel({ era, width, philosopherLayout, eventLayout, ticks, onCardClick }) {
  const headerRef = useRef(null);
  const [headerInView, setHeaderInView] = useState(false);
  useEffect(() => {
    const obs = new IntersectionObserver(entries => entries.forEach(e => { if (e.isIntersecting) setHeaderInView(true); }), { threshold: 0.4 });
    if (headerRef.current) obs.observe(headerRef.current);
    return () => obs.disconnect();
  }, []);
  return (
    <div className="panel era-panel" style={{ width: `${width}px` }} data-screen-label={`Era: ${era.label}`} data-era={era.id}>
      <div className="era-divider"></div>
      <div className="era-spine"></div>
      <div ref={headerRef} className="era-header-h" style={{
        opacity: headerInView ? 1 : 0, transform: headerInView ? "translateY(0)" : "translateY(20px)",
        transition: "opacity 1s cubic-bezier(0.2, 0.7, 0.2, 1), transform 1s cubic-bezier(0.2, 0.7, 0.2, 1)"
      }}>
        <div className="era-meta"><span className="era-meta-line"></span>{era.labelEn} · {era.yearRange}</div>
        <h2 className="era-title-h serif-ko">{era.label}</h2>
        <div className="era-subtitle-h">{era.subtitle}</div>
      </div>
      <div className="era-bg-title serif-en" style={{ opacity: headerInView ? 0.6 : 0, transition: "opacity 1.5s 0.3s ease" }}>{era.labelEn}</div>
      {ticks.map(t => (
        <React.Fragment key={`tick-${t.year}`}>
          <div className="year-tick" style={{ left: `${t.x}px` }}></div>
          <div className="year-tick-label serif-en" style={{ left: `${t.x}px` }}>{formatYear(t.year)}</div>
        </React.Fragment>
      ))}
      {eventLayout.map((e, i) => <EventMarker key={`event-${era.id}-${i}`} data={e} />)}
      {philosopherLayout.map(p => <PhilosopherCardH key={`p-${p.id}`} data={p} onClick={onCardClick} />)}
    </div>
  );
}

// === End 패널 ===
function EndPanel({ width, onBack }) {
  return (
    <div className="panel end-panel" style={{ width: `${width}px` }} data-screen-label="End">
      <div className="end-card">
        <div className="end-eyebrow">{S.endEyebrow || "Fin"}</div>
        <h2 className="end-title serif-ko">
          {S.endTitle1 || ""}<br />{S.endTitle2 || ""}
        </h2>
        <div className="end-divider"></div>
        <p className="end-sub">
          {S.endSub1 || ""}<br />{S.endSub2 || ""}
        </p>
        <button className="end-back" onClick={onBack}>{S.endBack || "← Back to start"}</button>
      </div>
    </div>
  );
}

// === 상단 진행 바 ===
function ProgressBar({ progress }) {
  return (<div className="progress-bar"><div className="progress-bar-fill" style={{ width: `${progress * 100}%` }}></div></div>);
}

// === 좌상단 연도 인디케이터 ===
function YearIndicator({ year, era, visible }) {
  return (
    <div className={`year-indicator-h ${visible ? "visible" : ""}`}>
      <div className="year-indicator-label-h">{S.yearLabel || "Year"}</div>
      <div className="year-indicator-value-h serif-en">{formatYear(year)}</div>
      <div className="year-indicator-era-h">{era || ""}</div>
    </div>
  );
}

// === 우상단 시대 네비 ===
function EraNav({ eras, activeId, onClick, visible }) {
  return (
    <div className={`era-nav ${visible ? "visible" : ""}`}>
      {eras.map((e, i) => (
        <React.Fragment key={e.id}>
          {i > 0 && <div className="era-nav-divider"></div>}
          <button className={`era-nav-btn ${activeId === e.id ? "active" : ""}`} onClick={() => onClick(e.id)}>{e.label}</button>
        </React.Fragment>
      ))}
    </div>
  );
}

function ScrollHint({ visible }) {
  return (
    <div className={`scroll-hint ${visible ? "visible" : ""}`}>
      <div className="scroll-hint-line"></div>
      <span>{S.scrollHint || "Scroll to navigate"}</span>
      <div className="scroll-hint-line"></div>
    </div>
  );
}

// === 모달 — 매거진 스타일 상세 페이지 ===
function PhilosopherModal({ philosopher, onClose }) {
  const [activeQuote, setActiveQuote] = useState(0);
  const contentRef = useRef(null);

  useEffect(() => {
    const onKey = e => { if (e.key === "Escape") onClose(); };
    document.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => { document.removeEventListener("keydown", onKey); document.body.style.overflow = ""; };
  }, [onClose]);

  if (!philosopher) return null;

  const era = ERAS.find(e => e.id === philosopher.era);

  const parseLife = (yearText) => {
    const parts = yearText.split(/[—–-]/);
    if (parts.length < 2) return null;
    const birthStr = parts[0].trim(), deathStr = parts[1].trim();
    const birthBC = birthStr.includes('BC'), deathBC = deathStr.includes('BC');
    const birthY = parseInt(birthStr.replace(/[^\d]/g, ''), 10);
    if (deathStr.includes('present') || deathStr.includes('현재') || deathStr.includes('heute') || deathStr.includes('présent') || deathStr.includes('actualidad') || deathStr.includes('настоящее') || deathStr.includes('現在') || deathStr.includes('至今')) return null;
    const deathY = parseInt(deathStr.replace(/[^\d]/g, ''), 10);
    if (isNaN(birthY) || isNaN(deathY)) return null;
    return (deathBC ? -deathY : deathY) - (birthBC ? -birthY : birthY);
  };
  const lifespan = parseLife(philosopher.yearText);

  const birthYear = philosopher.year;
  const deathApprox = lifespan ? birthYear + lifespan : birthYear + 70;
  const worldEvents = WORLD_EVENTS.filter(e => e.year >= birthYear - 20 && e.year <= deathApprox + 20).slice(0, 5);

  const contemporaries = PHILOSOPHERS.filter(p =>
    p.id !== philosopher.id && p.era === philosopher.era
  ).sort((a, b) => Math.abs(a.year - philosopher.year) - Math.abs(b.year - philosopher.year)).slice(0, 6);

  const heroQuote = philosopher.quotes[0];

  useEffect(() => {
    if (philosopher.quotes.length <= 1) return;
    const timer = setInterval(() => setActiveQuote(prev => (prev + 1) % philosopher.quotes.length), 6000);
    return () => clearInterval(timer);
  }, [philosopher.quotes.length]);

  const toRoman = (n) => {
    const map = [[10,'X'],[9,'IX'],[5,'V'],[4,'IV'],[1,'I']];
    let s = '';
    for (const [val, sym] of map) { while (n >= val) { s += sym; n -= val; } }
    return s;
  };

  // 섹션 번호 계산
  let sn = 1;
  const snLife = String(sn++).padStart(2, '0');
  const snStories = philosopher.anecdotes?.length > 0 ? String(sn++).padStart(2, '0') : null;
  const snThoughts = String(sn++).padStart(2, '0');
  const snQuotes = String(sn++).padStart(2, '0');
  const snWorks = String(sn++).padStart(2, '0');
  const snContext = worldEvents.length > 0 ? String(sn++).padStart(2, '0') : null;
  const snInfluence = philosopher.influence && (philosopher.influence.by?.length > 0 || philosopher.influence.on?.length > 0) ? String(sn++).padStart(2, '0') : null;
  const snContemp = contemporaries.length > 0 ? String(sn++).padStart(2, '0') : null;

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal-content modal-magazine" ref={contentRef} onClick={e => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose} aria-label={S.closeLabel || "Close"}>✕</button>

        {/* ── Hero ── */}
        <div className="mm-hero">
          <div className="mm-hero-bg serif-en">{philosopher.nameEn}</div>
          <figure className="mm-hero-portrait">
          <div className="mm-hero-portrait-frame">
            <div className="mm-hero-portrait-mat">
                <img src={getPortraitSrc(philosopher.id)} alt={philosopher.nameEn} loading="lazy"
                  onError={(e) => { e.currentTarget.closest('.mm-hero-portrait').style.display = 'none'; }} />
              </div>
            </div>
            <figcaption className="mm-hero-portrait-caption serif-en">{S.portraitCaption || "Portrait"}</figcaption>
          </figure>
          <div className="mm-hero-era">
            <span className="mm-era-dot"></span>
            <span className="mm-era-label serif-en">{era?.labelEn}</span>
            <span className="mm-era-sep">·</span>
            <span className="mm-era-label">{era?.label}</span>
            <span className="mm-era-sep">·</span>
            <span className="mm-era-label serif-en">{era?.yearRange}</span>
          </div>
          <div className="mm-hero-school serif-en">{philosopher.school}</div>
          <h2 className="mm-hero-name serif-ko">{philosopher.name}</h2>
          <div className="mm-hero-name-en serif-en">{philosopher.nameEn}</div>

          <div className="mm-meta-chips">
            <div className="mm-chip">
              <span className="mm-chip-icon">&#9711;</span>
              <div><div className="mm-chip-label serif-en">{S.chipLifespan || "Lifespan"}</div><div className="mm-chip-value serif-en">{philosopher.yearText}</div></div>
            </div>
            {lifespan && (
              <div className="mm-chip">
                <span className="mm-chip-icon">&#9201;</span>
                <div><div className="mm-chip-label serif-en">{S.chipAge || "Age"}</div><div className="mm-chip-value serif-en">{lifespan}{S.chipAgeUnit || ""}</div></div>
              </div>
            )}
            <div className="mm-chip">
              <span className="mm-chip-icon">&#9678;</span>
              <div><div className="mm-chip-label serif-en">{S.chipRegion || "Region"}</div><div className="mm-chip-value">{philosopher.region}</div></div>
            </div>
            <div className="mm-chip">
              <span className="mm-chip-icon">&#9998;</span>
              <div><div className="mm-chip-label serif-en">{S.chipWorks || "Works"}</div><div className="mm-chip-value serif-en">{philosopher.works.length}</div></div>
            </div>
          </div>

          {heroQuote && (
            <blockquote className="mm-hero-quote">
              <span className="mm-hq-mark serif-en">"</span>
              <p className="serif-ko">{heroQuote}</p>
            </blockquote>
          )}
        </div>

        {philosopher.keyIdea && (
          <div className="mm-key-idea">
            <div className="mm-ki-label serif-en">{S.coreIdea || "Core Idea"}</div>
            <p className="mm-ki-text serif-ko">{philosopher.keyIdea}</p>
          </div>
        )}

        <div className="mm-divider"><div className="mm-divider-line"></div><span className="mm-divider-diamond">◆</span><div className="mm-divider-line"></div></div>

        {/* ── Life ── */}
        <section className="mm-section">
          <div className="mm-section-header">
            <span className="mm-section-num serif-en">{snLife}</span>
            <div><h3 className="mm-section-title serif-en">{S.secLifeEn || "Life & Legacy"}</h3><div className="mm-section-subtitle">{S.secLifeLocal || ""}</div></div>
          </div>
          {philosopher.biography ? (
            <div className="mm-biography">
              <div className="mm-summary-initial serif-en">{philosopher.biography[0].charAt(0)}</div>
              {philosopher.biography.map((para, i) => (
                <p key={i} className={`mm-bio-para serif-ko ${i === 0 ? 'mm-bio-first' : ''}`}>{i === 0 ? para.slice(1) : para}</p>
              ))}
            </div>
          ) : (
            <div className="mm-summary-block">
              <div className="mm-summary-initial serif-en">{philosopher.summary.charAt(0)}</div>
              <p className="mm-summary serif-ko">{philosopher.summary}</p>
            </div>
          )}
        </section>

        {/* ── Stories ── */}
        {snStories && (
          <section className="mm-section mm-section-dark">
            <div className="mm-section-header">
              <span className="mm-section-num serif-en">{snStories}</span>
              <div><h3 className="mm-section-title serif-en">{S.secStoriesEn || "Stories & Facts"}</h3><div className="mm-section-subtitle">{S.secStoriesLocal || ""}</div></div>
            </div>
            <div className="mm-anecdotes">
              {philosopher.anecdotes.map((a, i) => (
                <div key={i} className="mm-anecdote"><div className="mm-anec-marker serif-en">§</div><p className="mm-anec-text">{a}</p></div>
              ))}
            </div>
          </section>
        )}

        {/* ── Thoughts ── */}
        <section className="mm-section">
          <div className="mm-section-header">
            <span className="mm-section-num serif-en">{snThoughts}</span>
            <div><h3 className="mm-section-title serif-en">{S.secThoughtsEn || "Key Thoughts"}</h3><div className="mm-section-subtitle">{S.secThoughtsLocal || ""}</div></div>
          </div>
          <div className="mm-thoughts">
            {philosopher.thoughts.map((t, i) => (
              <div key={i} className="mm-thought-card"><div className="mm-thought-num serif-en">{toRoman(i + 1)}</div><p className="mm-thought-text">{t}</p></div>
            ))}
          </div>
        </section>

        {/* ── Quotes ── */}
        <section className="mm-section mm-section-dark">
          <div className="mm-section-header">
            <span className="mm-section-num serif-en">{snQuotes}</span>
            <div><h3 className="mm-section-title serif-en">{S.secQuotesEn || "In Their Words"}</h3><div className="mm-section-subtitle">{S.secQuotesLocal || ""}</div></div>
          </div>
          <div className="mm-quotes-showcase">
            {philosopher.quotes.map((q, i) => (
              <div key={i} className={`mm-quote-slide ${i === activeQuote ? 'active' : ''}`}>
                <div className="mm-qs-mark serif-en">"</div>
                <p className="mm-qs-text serif-ko">{q}</p>
                <div className="mm-qs-attr serif-en">— {philosopher.nameEn}</div>
              </div>
            ))}
            {philosopher.quotes.length > 1 && (
              <div className="mm-quote-dots">
                {philosopher.quotes.map((_, i) => (
                  <button key={i} className={`mm-quote-dot ${i === activeQuote ? 'active' : ''}`} onClick={() => setActiveQuote(i)} aria-label={`${i + 1}`} />
                ))}
              </div>
            )}
          </div>
        </section>

        {/* ── Works ── */}
        <section className="mm-section">
          <div className="mm-section-header">
            <span className="mm-section-num serif-en">{snWorks}</span>
            <div><h3 className="mm-section-title serif-en">{S.secWorksEn || "Major Works"}</h3><div className="mm-section-subtitle">{S.secWorksLocal || ""}</div></div>
          </div>
          <div className="mm-works-grid">
            {philosopher.works.map((w, i) => (
              <div key={i} className="mm-work-card"><div className="mm-work-spine"></div>
                <div className="mm-work-body"><div className="mm-work-idx serif-en">{String(i + 1).padStart(2, '0')}</div><div className="mm-work-title serif-ko">{w}</div></div>
              </div>
            ))}
          </div>
        </section>

        {/* ── Context ── */}
        {snContext && (
          <section className="mm-section">
            <div className="mm-section-header">
              <span className="mm-section-num serif-en">{snContext}</span>
              <div><h3 className="mm-section-title serif-en">{S.secContextEn || "Historical Context"}</h3><div className="mm-section-subtitle">{S.secContextLocal || ""}</div></div>
            </div>
            <div className="mm-timeline-mini">
              <div className="mm-timeline-line"></div>
              {worldEvents.map((e, i) => (
                <div key={i} className="mm-timeline-event"><div className="mm-te-dot"></div><div className="mm-te-year serif-en">{formatYear(e.year)}</div><div className="mm-te-title serif-ko">{e.title}</div></div>
              ))}
            </div>
          </section>
        )}

        {/* ── Influence ── */}
        {snInfluence && (
          <section className="mm-section">
            <div className="mm-section-header">
              <span className="mm-section-num serif-en">{snInfluence}</span>
              <div><h3 className="mm-section-title serif-en">{S.secInfluenceEn || "Influence"}</h3><div className="mm-section-subtitle">{S.secInfluenceLocal || ""}</div></div>
            </div>
            <div className="mm-influence">
              {philosopher.influence.by?.length > 0 && (
                <div className="mm-inf-col">
                  <div className="mm-inf-label serif-en">{S.infBy || "Influenced by"}</div>
                  <div className="mm-inf-names">{philosopher.influence.by.map((name, i) => <span key={i} className="mm-inf-tag">{name}</span>)}</div>
                </div>
              )}
              {philosopher.influence.on?.length > 0 && (
                <div className="mm-inf-col">
                  <div className="mm-inf-label serif-en">{S.infOn || "Influenced"}</div>
                  <div className="mm-inf-names">{philosopher.influence.on.map((name, i) => <span key={i} className="mm-inf-tag mm-inf-tag-out">{name}</span>)}</div>
                </div>
              )}
            </div>
          </section>
        )}

        {/* ── Contemporaries ── */}
        {snContemp && (
          <section className="mm-section">
            <div className="mm-section-header">
              <span className="mm-section-num serif-en">{snContemp}</span>
              <div><h3 className="mm-section-title serif-en">{S.secContemporariesEn || "Contemporaries"}</h3><div className="mm-section-subtitle">{S.secContemporariesLocal || ""}</div></div>
            </div>
            <div className="mm-contemporaries">
              {contemporaries.map(c => (
                <div key={c.id} className="mm-contemp-chip">
                  <div className="mm-cc-name serif-ko">{c.name}</div>
                  <div className="mm-cc-meta">
                    <span className="serif-en">{formatYear(c.year)}</span>
                    <span className="mm-cc-sep">·</span>
                    <span className="mm-cc-school serif-en">{c.school.split('·')[0].trim()}</span>
                  </div>
                </div>
              ))}
            </div>
          </section>
        )}

        <div className="mm-footer">
          <div className="mm-footer-line"></div>
          <div className="mm-footer-text serif-en">{philosopher.nameEn} · {philosopher.yearText}</div>
          <div className="mm-footer-sub serif-ko">"{era?.subtitle}"</div>
        </div>
      </div>
    </div>
  );
}

// === 메인 앱 ===
function App() {
  const [selected, setSelected] = useState(null);
  const [scrollProgress, setScrollProgress] = useState(0);
  const [currentYear, setCurrentYear] = useState(null);
  const [currentEra, setCurrentEra] = useState(null);
  const [uiVisible, setUiVisible] = useState(false);
  const [viewport, setViewport] = useState({ w: window.innerWidth, h: window.innerHeight });
  const wrapperRef = useRef(null);
  const trackRef = useRef(null);

  useEffect(() => {
    const onResize = () => setViewport({ w: window.innerWidth, h: window.innerHeight });
    window.addEventListener("resize", onResize);
    return () => window.removeEventListener("resize", onResize);
  }, []);

  const eraLayouts = useMemo(() => ERAS.map(era => ({ era, ...computeEraLayout(era) })), []);

  const panelLayout = useMemo(() => {
    const heroW = viewport.w;
    const endW = Math.min(viewport.w * 0.9, 1200);
    let x = 0;
    const panels = [];
    panels.push({ type: "hero", x, width: heroW }); x += heroW;
    for (const e of eraLayouts) { panels.push({ type: "era", era: e.era, layout: e, x, width: e.width }); x += e.width; }
    panels.push({ type: "end", x, width: endW }); x += endW;
    return { panels, totalWidth: x, heroW, endW };
  }, [eraLayouts, viewport.w]);

  useEffect(() => {
    const scrollDist = panelLayout.totalWidth - viewport.w;
    if (wrapperRef.current) wrapperRef.current.style.height = `${viewport.h + scrollDist}px`;
  }, [panelLayout.totalWidth, viewport.w, viewport.h]);

  useEffect(() => {
    let raf = null;
    const onScroll = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => {
        raf = null;
        const vw = viewport.w;
        const scrollDist = panelLayout.totalWidth - vw;
        const sy = window.scrollY;
        setScrollProgress(scrollDist > 0 ? Math.max(0, Math.min(1, sy / scrollDist)) : 0);
        const tx = Math.max(0, Math.min(scrollDist, sy));
        if (trackRef.current) trackRef.current.style.transform = `translate3d(${-tx}px, 0, 0)`;
        const centerX = tx + vw / 2;
        let currentPanel = null;
        for (const panel of panelLayout.panels) { if (centerX >= panel.x && centerX < panel.x + panel.width) { currentPanel = panel; break; } }
        if (currentPanel?.type === "era") {
          const layout = currentPanel.layout;
          const localX = centerX - currentPanel.x;
          const PAD = 380, innerW = currentPanel.width - 2 * PAD;
          const tt = Math.max(0, Math.min(1, (localX - PAD) / innerW));
          setCurrentYear(Math.round(layout.yMin + tt * (layout.yMax - layout.yMin)));
          setCurrentEra(currentPanel.era);
        } else if (currentPanel?.type === "hero") { setCurrentEra(null); setCurrentYear(null); }
        else if (currentPanel?.type === "end") { setCurrentEra(ERAS[ERAS.length - 1]); setCurrentYear(2000); }
        setUiVisible(!!currentPanel && currentPanel.type !== "hero");
      });
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, [panelLayout, viewport.w]);

  // Touch swipe
  useEffect(() => {
    const pin = document.querySelector('.hscroll-pin');
    if (!pin) return;
    let startX = 0, startY = 0, lastX = 0, lastTime = 0, velocity = 0, isHorizontal = null, momentumRaf = null;
    const onTouchStart = (e) => {
      if (momentumRaf) { cancelAnimationFrame(momentumRaf); momentumRaf = null; }
      const touch = e.touches[0]; startX = touch.clientX; startY = touch.clientY; lastX = startX; lastTime = Date.now(); velocity = 0; isHorizontal = null;
    };
    const onTouchMove = (e) => {
      const touch = e.touches[0]; const currentX = touch.clientX, currentY = touch.clientY, now = Date.now();
      if (isHorizontal === null) { const dx = Math.abs(currentX - startX), dy = Math.abs(currentY - startY); if (dx > 8 || dy > 8) isHorizontal = dx > dy; else return; }
      if (isHorizontal) { e.preventDefault(); const deltaX = currentX - lastX; const dt = Math.max(1, now - lastTime); velocity = velocity * 0.3 + ((deltaX / dt) * 16) * 0.7; window.scrollBy(0, -deltaX); }
      lastX = currentX; lastTime = now;
    };
    const onTouchEnd = () => {
      if (isHorizontal && Math.abs(velocity) > 0.5) { const decelerate = () => { velocity *= 0.96; if (Math.abs(velocity) < 0.3) { momentumRaf = null; return; } window.scrollBy(0, -velocity); momentumRaf = requestAnimationFrame(decelerate); }; momentumRaf = requestAnimationFrame(decelerate); }
      isHorizontal = null;
    };
    pin.addEventListener('touchstart', onTouchStart, { passive: true });
    pin.addEventListener('touchmove', onTouchMove, { passive: false });
    pin.addEventListener('touchend', onTouchEnd, { passive: true });
    pin.addEventListener('touchcancel', onTouchEnd, { passive: true });
    return () => { if (momentumRaf) cancelAnimationFrame(momentumRaf); pin.removeEventListener('touchstart', onTouchStart); pin.removeEventListener('touchmove', onTouchMove); pin.removeEventListener('touchend', onTouchEnd); pin.removeEventListener('touchcancel', onTouchEnd); };
  }, []);

  const scrollToEra = useCallback((eraId) => {
    const panel = panelLayout.panels.find(p => p.type === "era" && p.era.id === eraId);
    if (panel) window.scrollTo({ top: panel.x + 100, behavior: "smooth" });
  }, [panelLayout]);

  return (
    <React.Fragment>
      <ProgressBar progress={scrollProgress} />
      <LangSwitcher />
      <YearIndicator year={currentYear} era={currentEra?.label} visible={uiVisible} />
      <EraNav eras={ERAS} activeId={currentEra?.id} onClick={scrollToEra} visible={uiVisible} />
      <ScrollHint visible={uiVisible} />
      <div ref={wrapperRef} className="hscroll-wrapper">
        <div className="hscroll-pin">
          <div ref={trackRef} className="hscroll-track">
            <HeroPanel width={panelLayout.heroW} />
            {eraLayouts.map(el => <EraPanel key={el.era.id} {...el} onCardClick={setSelected} />)}
            <EndPanel width={panelLayout.endW} onBack={() => window.scrollTo({ top: 0, behavior: "smooth" })} />
          </div>
        </div>
      </div>
      {selected && <PhilosopherModal philosopher={selected} onClose={() => setSelected(null)} />}
    </React.Fragment>
  );
}

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