// landings.jsx — v8 · 캐릭터 중심, 따뜻한 미니멀 배경
//
// 원칙:
//   · 캐릭터가 메인 (크게, 표정 명확)
//   · 배경 = 따뜻한 그라데이션 + 부드러운 atmospheric blob/모양만
//   · 사각형 가구 ❌ → 캐릭터 옆 작은 floating 디테일만
//   · 사이트 정체성은 작은 소품·thought bubble·헤드라인으로

const { Person, PersonStanding, SITE_COLORS, INK } = window;
const FONT = '"Pretendard","Inter",-apple-system,BlinkMacSystemFont,system-ui,sans-serif';

// ── 그라운디드 버전: "차분하지만 단단한" (서양 웰니스 시장용) ─────────────────
// 파스텔의 부드러움은 유지하되 채도·대비·그라데이션 범위를 키워 깊이(무게감)를 줌.
// 같은 사이트별 hue는 유지 → 여전히 한 패밀리. 다만 더 그라운디드하고 자신감 있게.
const SHARED_BG = {
  floor: '#ccb993', floorDark: '#b09a6f',
  wood: '#b39668', woodDark: '#86703f', woodLight: '#cdb88c',
  fabric: '#d8c8a8', fabricSoft: '#e6d8bd', fabricDeep: '#a68d66',
  leaf: '#6e8e58', leafDark: '#506b3e', leafLight: '#9bb87a',
  cream: '#f5efe2',
};
// 사이트별 틴트 (파스텔보다 깊고 단단 — 채도↑, 벽 하단 더 진하게 = 그라운디드)
const SITE_TINTS = {
  talk: { // 깊은 블루그레이
    wallTop: '#dde8f1', wallMid: '#bbd2e5', wallBot: '#98b8d3', glow: '#e8f1f8',
    skyTop: '#dde8f1', skyMid: '#b6cce2', skyBot: '#96b6d2', sun: '#d6e4ee',
  },
  neuro: { // 단단한 피치/테라코타
    wallTop: '#f9dcc2', wallMid: '#f0bb92', wallBot: '#e29e6a', glow: '#fbe2cd',
    skyTop: '#f9d9bc', skyMid: '#f0b486', skyBot: '#e29862', sun: '#ffbf80',
  },
  modality: { // 깊은 세이지
    wallTop: '#e0ebd2', wallMid: '#c4d8b1', wallBot: '#a4bf87', glow: '#ecf3df',
    skyTop: '#e0ebd2', skyMid: '#c2d6ad', skyBot: '#a0be84', sun: '#e3ebac',
  },
  boston: { // 진한 허니골드
    wallTop: '#f7e7bd', wallMid: '#eecd86', wallBot: '#ddb85c', glow: '#faecc1',
    skyTop: '#f7e4b7', skyMid: '#eec882', skyBot: '#ddb55c', sun: '#f6d56c',
  },
};
const SITE_PALETTES = Object.fromEntries(
  Object.entries(window.SITE_PALETTES).map(([k, v]) => [
    k, { ...v, ...SHARED_BG, ...(SITE_TINTS[k] || {}) },
  ])
);

// ─────────────────────────────────────────────────────────────────────────────
// 공통 UI
// ─────────────────────────────────────────────────────────────────────────────
// 사이트별 풀다운 메뉴 정의 (각 5개) — 4 catcher만 메인 nav, About/Contact는 코너로
const SITE_NAV = [
  { key: 'talk', ko: '상담봇캐쳐', en: 'TalkCatcher', file: 'https://agedlearning.com',
    items: [
      { action: 'guide',     ko: '📖 사용 안내',     en: '📖 Guide' },
      { action: 'mechanism', ko: '⚙️ 작동 메커니즘',  en: '⚙️ How it works' },
      { ko: '우울 봇',     en: 'Depression',  href: 'T.html#depression' },
      { ko: '불안 봇',     en: 'Anxiety',     href: 'T.html#anxiety' },
      { ko: '수면 봇',     en: 'Sleep',       href: 'T.html#sleep' },
      { ko: '학습 봇',     en: 'Learning',    href: 'T.html#learning' },
      { ko: '11 봇 전체',  en: 'See all 11 bots', href: 'T.html' },
    ],
  },
  { key: 'boston', ko: '증상판별캐쳐', en: 'SymptomCatcher', file: 'https://agedlearning.com/symptomcatcher.html',
    items: [
      { ko: '증상진단',              en: 'Symptom Screening',     href: 'https://agedlearning.com/symptomcatcher.html' },
      { ko: 'DSM-5-TR 판별진단',     en: 'DSM-5-TR Differential', href: 'https://agedlearning.com/symptom_catcher/dmda/index.html' },
      { ko: '얼굴기반 DSM-5-TR 진단', en: 'Face-based DSM-5-TR',   href: 'https://agedlearning.com/symptom_catcher/face-reading/face-reading-v3.5.html' },
    ],
  },
  { key: 'neuro', ko: '개별증상캐쳐', en: 'TrackCatcher', file: 'https://agedlearning.com/track',
    items: [
      { ko: 'Mood 트래킹',  en: 'Mood tracking',  href: 'N.html#mood' },
      { ko: 'Sleep 트래킹', en: 'Sleep tracking', href: 'N.html#sleep' },
      { ko: 'Focus 트래킹', en: 'Focus tracking', href: 'N.html#focus' },
      { ko: '11 증상 모듈', en: 'See all 11 modules', href: 'N.html#modules' },
      { ko: '데이터 보기',  en: 'View my data',      href: 'N.html#data' },
    ],
  },
  { key: 'modality', ko: '치료방법캐쳐', en: 'ModalityCatcher', file: 'https://agedlearning.com',
    items: [
      { ko: 'CBT-I',   en: 'CBT-I',     href: 'M.html#cbt' },
      { ko: 'MBSR',    en: 'MBSR',      href: 'M.html#mbsr' },
      { ko: 'ACT',     en: 'ACT',       href: 'M.html#act' },
      { ko: 'EMDR',    en: 'EMDR',      href: 'M.html#emdr' },
      { ko: '9 치료법 전체', en: 'See all 9 modalities', href: 'M.html' },
    ],
  },
];

// 3 PROGRAM 탭 (상위 메뉴 prominent)
const PROGRAMS = [
  { key: 'attention', ko: '주의집중',    en: 'Attention',        href: '#attention', color: '#E8A317' },
  { key: 'learning',  ko: '학습',        en: 'Learning',         href: '#learning',  color: '#6B9B5C' },
  { key: 'peak',      ko: '최고수행',    en: 'Peak Performance', href: '#peak',      color: '#4A90C2' },
];

// 코너 유틸리티 링크 (About, Contact, KO/EN, Admin)
const UTILITY_NAV = [
  { key: 'about', ko: '소개', en: 'About',  href: '#about' },
  { key: 'contact', ko: '연락', en: 'Contact', href: '#contact' },
  // 동의서 제거 — 로그인 시 동의 게이트가 처리(beta consent + 가입 동의)
];

// footer 법적 링크 (Stripe 결제 요구 — agedlearning.com/legal/)
const LEGAL_NAV = [
  { ko: '약관', en: 'Terms', href: 'https://agedlearning.com/legal/terms.html' },
  { ko: '개인정보', en: 'Privacy', href: 'https://agedlearning.com/legal/privacy.html' },
  { ko: '환불', en: 'Refunds', href: 'https://agedlearning.com/legal/refunds.html' },
  { ko: '구독', en: 'Subscriptions', href: 'https://agedlearning.com/legal/subscriptions.html' },
  { ko: '연락처', en: 'Contact', href: 'https://agedlearning.com/legal/contact.html' },
];

function ProgramTab({ p, lang }) {
  const [hover, setHover] = React.useState(false);
  return (
    <a href={p.href}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 5,
        padding: '7px 10px',
        minWidth: 110, boxSizing: 'border-box',
        background: hover ? `${p.color}22` : '#fffdf6',
        border: `1.5px solid ${hover ? p.color : INK + '22'}`,
        borderRadius: 999,
        color: hover ? p.color : '#2a2018',
        fontSize: 10.5, fontWeight: 700,
        textDecoration: 'none',
        transition: 'background 0.15s, border-color 0.15s, color 0.15s, transform 0.15s, box-shadow 0.15s',
        whiteSpace: 'nowrap',
        fontFamily: FONT,
        transform: hover ? 'translateY(-1.5px)' : 'translateY(0)',
        boxShadow: hover ? `0 5px 12px ${p.color}33` : `0 2px 0 ${INK}1a`,
        letterSpacing: '-0.005em',
      }}>
      <span style={{
        width: 5, height: 5, borderRadius: 999,
        background: p.color,
        boxShadow: hover ? `0 0 0 2.5px ${p.color}38` : 'none',
        transition: 'box-shadow 0.18s',
        flexShrink: 0,
      }} />
      {lang === 'en' ? p.en : p.ko}
    </a>
  );
}

function NavItem({ s, lang, accent, currentSite, darkMode, onAction }) {
  const [hover, setHover] = React.useState(false);
  const siteColor = (window.SITE_COLORS && window.SITE_COLORS[s.key] && window.SITE_COLORS[s.key].value) || '#9a8763';
  const label = lang === 'en' ? s.en : s.ko;
  const bgIdle = darkMode ? 'rgba(255,255,255,0.08)' : '#fffdf6';
  const bgHover = darkMode ? `${siteColor}33` : `${siteColor}1a`;
  const borderIdle = darkMode ? 'rgba(255,255,255,0.25)' : INK + '22';
  const borderHover = darkMode ? siteColor : siteColor;
  const colorIdle = darkMode ? 'rgba(255,255,255,0.9)' : '#5a4a35';
  const colorHover = darkMode ? '#ffffff' : '#2a2018';
  const shadowIdle = darkMode ? `0 2px 0 rgba(0,0,0,0.3)` : `0 2px 0 ${INK}1a`;
  return (
    <div
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      style={{ position: 'relative' }}>
      <a href={s.file || s.href}
        style={{
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 5,
          padding: '7px 10px',
          width: 132, boxSizing: 'border-box',
          background: hover ? bgHover : bgIdle,
          backdropFilter: darkMode ? 'blur(8px)' : 'none',
          border: `1.5px solid ${hover ? borderHover : borderIdle}`,
          borderRadius: 999,
          color: hover ? colorHover : colorIdle,
          fontSize: 10, fontWeight: 700,
          textDecoration: 'none',
          transition: 'background 0.15s, border-color 0.15s, color 0.15s, transform 0.15s, box-shadow 0.15s',
          whiteSpace: 'nowrap',
          fontFamily: FONT,
          transform: hover ? 'translateY(-1.5px)' : 'translateY(0)',
          boxShadow: hover ? `0 5px 12px ${siteColor}33` : shadowIdle,
          letterSpacing: '-0.005em',
        }}>
        <span style={{
          width: 5, height: 5, borderRadius: 999,
          background: siteColor,
          boxShadow: hover ? `0 0 0 2.5px ${siteColor}38` : 'none',
          transition: 'box-shadow 0.18s',
          flexShrink: 0,
        }} />
        {label}
        {s.items && (
          <span style={{
            fontSize: 7, opacity: 0.5,
            transform: hover ? 'rotate(180deg)' : 'rotate(0)',
            transition: 'transform 0.2s',
            display: 'inline-block', marginLeft: -1,
          }}>▾</span>
        )}
      </a>
      {/* Dropdown */}
      {s.items && (
        <div style={{
          position: 'absolute', top: 'calc(100% + 6px)', left: -4,
          minWidth: 200,
          background: '#ffffff',
          border: `2px solid ${INK}`,
          borderRadius: 14,
          padding: '8px 6px',
          boxShadow: `0 12px 30px rgba(80,50,10,0.18), 0 4px 8px rgba(0,0,0,0.06)`,
          opacity: hover ? 1 : 0,
          visibility: hover ? 'visible' : 'hidden',
          transform: hover ? 'translateY(0)' : 'translateY(-6px)',
          transition: 'opacity 0.18s, transform 0.18s, visibility 0.18s',
          zIndex: 50,
          fontFamily: FONT,
        }}>
          <div style={{
            position: 'absolute', top: -7, left: 26,
            width: 12, height: 12,
            background: '#ffffff',
            borderTop: `2px solid ${INK}`,
            borderLeft: `2px solid ${INK}`,
            transform: 'rotate(45deg)',
          }} />
          {s.items.map((it, i) => {
            const itemStyle = {
              display: 'flex', alignItems: 'center', gap: 8,
              padding: '8px 12px',
              fontSize: 12, fontWeight: 600,
              color: '#2a2018',
              textDecoration: 'none',
              borderRadius: 8,
              transition: 'background 0.12s, color 0.12s, padding 0.14s',
              whiteSpace: 'nowrap',
              position: 'relative', zIndex: 1,
              fontFamily: FONT, cursor: 'pointer',
              border: 0, background: 'transparent', width: '100%', textAlign: 'left',
            };
            const onEnter = (e) => {
              e.currentTarget.style.background = `${siteColor}16`;
              e.currentTarget.style.color = siteColor;
              e.currentTarget.style.paddingLeft = '16px';
            };
            const onLeave = (e) => {
              e.currentTarget.style.background = 'transparent';
              e.currentTarget.style.color = '#2a2018';
              e.currentTarget.style.paddingLeft = '12px';
            };
            const dot = <span style={{ width: 5, height: 5, borderRadius: 999,
              background: siteColor, opacity: 0.7, flexShrink: 0 }} />;
            const label = lang === 'en' ? it.en : it.ko;
            return it.action ? (
              <button key={i} type="button"
                onClick={() => onAction && onAction(it.action)}
                onMouseEnter={onEnter} onMouseLeave={onLeave} style={itemStyle}>
                {dot}{label}
              </button>
            ) : (
              <a key={i} href={it.href}
                onMouseEnter={onEnter} onMouseLeave={onLeave} style={itemStyle}>
                {dot}{label}
              </a>
            );
          })}
        </div>
      )}
    </div>
  );
}

// ThunderNeurofeedback — 지휘봉 스타일 pill (한번 치는 애니메이션)
function ThunderNeurofeedback() {
  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      padding: '5px 12px 5px 10px',
      background: '#fffdf6',
      border: `1.5px solid ${INK}`,
      borderRadius: 999,
      marginTop: 4,
      boxShadow: `0 2px 0 ${INK}1a`,
      fontFamily: '"Fredoka","Pretendard",sans-serif',
      transformOrigin: 'right center',
      animation: 'batonSwing 6s ease-in-out infinite',
    }}>
      <svg width={18} height={10} viewBox="0 0 18 10">
        <path d="M 1,5 Q 3,2 5,5 T 9,5 T 13,5 L 17,5"
          stroke={INK} strokeWidth={1.4} fill="none"
          strokeLinecap="round" />
      </svg>
      <span style={{
        fontSize: 12, fontWeight: 600,
        color: '#1f1d1a',
        letterSpacing: '0.3px',
        lineHeight: 1,
      }}>
        Neurofeedback
      </span>
      <style>{`
        @keyframes batonSwing {
          0%, 100% { transform: rotate(0deg) translateY(0); }
          1%       { transform: rotate(-14deg) translateY(-1px); }
          3%       { transform: rotate(6deg) translateY(0); }
          5%       { transform: rotate(0deg); }
        }
      `}</style>
    </div>
  );
}

function Nav({ siteName, items, ctaLabel, accent, lang, setLang, currentSite, darkMode, onCta, authButtons, ctaColor, ctaSoft, onNavAction }) {
  return (
    <>

      <nav style={{
        position: 'absolute', top: 14, left: 0, right: 0,
        display: 'flex', alignItems: 'center',
        padding: '30px 40px 18px', zIndex: 10, fontFamily: FONT,
      }}>
        <div style={{ flex: '1 1 0', display: 'flex', justifyContent: 'flex-start', minWidth: 0 }}>
          <a href="https://agedlearning.com" style={{
            display: 'flex', alignItems: 'center', gap: 10, textDecoration: 'none',
            flexShrink: 0,
          }}>
            <img src={darkMode ? 'assets/logo-dark.svg' : 'assets/logo.svg'} alt="logo"
              style={{ height: 56, display: 'block', objectFit: 'contain' }} />
          </a>
        </div>

        {/* 메뉴 — 화면 정중앙 정렬 (Home 반칸 오른쪽 오프셋) */}
        <div style={{
          flexShrink: 0, marginLeft: 14,
          display: 'flex', gap: 10, alignItems: 'center',
        }}>
        {currentSite !== 'boston' ? (
          <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
            <a href="https://agedlearning.com"
              onMouseEnter={(e) => {
                e.currentTarget.style.background = darkMode ? 'rgba(255,255,255,0.18)' : '#ffffff';
                e.currentTarget.style.borderColor = accent;
              }}
              onMouseLeave={(e) => {
                e.currentTarget.style.background = darkMode ? 'rgba(255,255,255,0.08)' : '#ffffff99';
                e.currentTarget.style.borderColor = darkMode ? 'rgba(255,255,255,0.25)' : `${INK}22`;
              }}
              style={{
                display: 'inline-flex', alignItems: 'center', gap: 7,
                padding: '8px 15px', borderRadius: 999,
                background: darkMode ? 'rgba(255,255,255,0.08)' : '#ffffff99',
                backdropFilter: 'blur(8px)',
                border: `1.5px solid ${darkMode ? 'rgba(255,255,255,0.25)' : INK + '22'}`,
                fontSize: 12, fontWeight: 700,
                color: darkMode ? '#ffffff' : INK,
                textDecoration: 'none', fontFamily: FONT,
                transition: 'all 0.18s ease', cursor: 'pointer',
              }}>
              <svg width="14" height="14" viewBox="0 0 16 16" fill="none">
                <path d="M2,7 L8,2 L14,7 L14,14 L10,14 L10,10 L6,10 L6,14 L2,14 Z"
                  stroke={darkMode ? '#ffffff' : INK} strokeWidth={1.8} strokeLinejoin="round" fill="none" />
              </svg>
              {lang === 'en' ? 'Home' : '홈'}
            </a>
            {[...SITE_NAV].sort((a, b) =>
              (a.key === currentSite ? 1 : 0) - (b.key === currentSite ? 1 : 0)
            ).map((s) => (
              <NavItem key={s.key}
                s={s.key === currentSite ? s : { ...s, items: undefined }}
                lang={lang} accent={accent} currentSite={currentSite} darkMode={darkMode} onAction={onNavAction} />
            ))}
          </div>
        ) : (
          <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
            {PROGRAMS.map((p) => (
              <ProgramTab key={p.key} p={p} lang={lang} />
            ))}
            {SITE_NAV.map((s) => (
              <NavItem key={s.key} s={s} lang={lang} accent={accent} currentSite={currentSite} onAction={onNavAction} />
            ))}
          </div>
        )}

        </div>

        {/* 우: [Login·Signup·Intake] 윗줄 / [util] 아랫줄 — 좌측정렬 컬럼(util 왼쪽=Login 왼쪽 자동), super 자리 */}
        <div style={{ flex: '1 1 0', display: 'flex', justifyContent: 'flex-end', alignItems: 'flex-start' }}>
          <div style={{ position: 'relative', display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 7, marginRight: 64, transform: 'translateX(32px)' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              {authButtons}
              <button
                onClick={onCta}
                onMouseEnter={(e) => { e.currentTarget.style.transform = 'translateY(-2px)'; e.currentTarget.style.background = '#fff'; }}
                onMouseLeave={(e) => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.background = 'transparent'; }}
                onMouseDown={(e) => { e.currentTarget.style.transform = 'translateY(0)'; }}
                onMouseUp={(e) => { e.currentTarget.style.transform = 'translateY(-2px)'; }}
                style={{
                  padding: '8px 16px', borderRadius: 999,
                  background: 'transparent',
                  color: '#5a4a35',
                  border: `1.5px solid ${INK}22`, fontSize: 12, fontWeight: 800, cursor: 'pointer',
                  fontFamily: FONT,
                  boxShadow: 'none',
                  transition: 'transform 0.18s ease, box-shadow 0.18s ease',
                  whiteSpace: 'nowrap',
                }}>{ctaLabel}</button>
              <SuperButton lang={lang} />
            </div>
            <div style={{ position: 'absolute', top: '100%', left: 0, marginTop: 11, paddingLeft: 8, display: 'flex', alignItems: 'center', gap: 8, fontFamily: FONT }}>
              {UTILITY_NAV.map((u) => (
                <a key={u.key} href={u.href}
                  target={u.external ? '_blank' : undefined} rel={u.external ? 'noopener' : undefined}
                  onMouseEnter={(e) => { e.currentTarget.style.color = accent; }}
                  onMouseLeave={(e) => { e.currentTarget.style.color = darkMode ? 'rgba(255,255,255,0.7)' : '#8a7654'; }}
                  style={{ fontSize: 10, fontWeight: 700, color: darkMode ? 'rgba(255,255,255,0.7)' : '#8a7654', textDecoration: 'none', padding: '3px 6px', transition: 'color 0.15s', cursor: 'pointer', letterSpacing: '0.02em' }}>
                  {lang === 'en' ? u.en : u.ko}
                </a>
              ))}
              <span style={{ width: 1, height: 12, background: darkMode ? 'rgba(255,255,255,0.3)' : `${INK}22` }} />
              {setLang && (
                <>
                  <div style={{ display: 'flex', alignItems: 'center', padding: 2, borderRadius: 999, background: darkMode ? 'rgba(255,255,255,0.10)' : '#ffffff99', border: `1px solid ${darkMode ? 'rgba(255,255,255,0.25)' : INK + '1f'}`, fontSize: 9, fontWeight: 700, backdropFilter: 'blur(6px)' }}>
                    {['KO', 'EN'].map((L) => (
                      <button key={L}
                        onClick={() => { var nl = L.toLowerCase(); setLang(nl); if (window.bnmSetLang) window.bnmSetLang(nl); }}
                        style={{ padding: '2px 7px', borderRadius: 999, border: 0, cursor: 'pointer', background: lang === L.toLowerCase() ? (darkMode ? '#ffffff' : INK) : 'transparent', color: lang === L.toLowerCase() ? (darkMode ? INK : '#fff') : (darkMode ? 'rgba(255,255,255,0.7)' : '#8a7654'), fontFamily: FONT, fontWeight: 700, fontSize: 9, transition: 'all 0.15s' }}>{L}</button>
                    ))}
                  </div>
                  <a href="/admin.html"
                    onMouseEnter={(e) => { e.currentTarget.style.background = darkMode ? 'rgba(255,255,255,0.18)' : '#ffffff'; e.currentTarget.style.borderColor = accent; e.currentTarget.style.color = darkMode ? '#ffffff' : accent; }}
                    onMouseLeave={(e) => { e.currentTarget.style.background = darkMode ? 'rgba(255,255,255,0.10)' : '#ffffff99'; e.currentTarget.style.borderColor = darkMode ? 'rgba(255,255,255,0.25)' : `${INK}1f`; e.currentTarget.style.color = darkMode ? 'rgba(255,255,255,0.7)' : '#8a7654'; }}
                    style={{ display: 'inline-flex', alignItems: 'center', gap: 3, padding: '3px 8px', borderRadius: 999, background: darkMode ? 'rgba(255,255,255,0.10)' : '#ffffff99', border: `1px solid ${darkMode ? 'rgba(255,255,255,0.25)' : INK + '1f'}`, fontSize: 9, fontWeight: 700, color: darkMode ? 'rgba(255,255,255,0.7)' : '#8a7654', textDecoration: 'none', backdropFilter: 'blur(6px)', transition: 'all 0.15s', cursor: 'pointer' }}>
                    <span style={{ width: 4, height: 4, borderRadius: 999, background: accent }} />
                    {lang === 'en' ? 'Admin' : '관리자'}
                  </a>
                </>
              )}
            </div>
          </div>
        </div>
      </nav>
    </>
  );
}

function CornerCopy({ eyebrow, headline, sub, primaryCta, secondaryCta, accent, position = 'left', copyScale = 1, copyOffset = 0 }) {
  const isRight = position === 'right';
  return (
    <div style={{
      position: 'absolute',
      ...(isRight ? { right: 56 + copyOffset } : { left: 56 + copyOffset }),
      top: 130, maxWidth: 460, zIndex: 5,
      fontFamily: FONT,
      textAlign: isRight ? 'right' : 'left',
    }}>
      <div style={{
        fontSize: 12 * copyScale, fontWeight: 700, color: accent,
        letterSpacing: '0.12em', textTransform: 'uppercase',
        marginBottom: 24 * copyScale, display: 'flex', alignItems: 'center', gap: 10,
        justifyContent: isRight ? 'flex-end' : 'flex-start',
      }}>
        {!isRight && <span style={{ width: 24, height: 2, background: accent, borderRadius: 2 }} />}
        {eyebrow}
        {isRight && <span style={{ width: 24, height: 2, background: accent, borderRadius: 2 }} />}
      </div>
      <h1 style={{
        fontSize: 60 * copyScale, lineHeight: 1.08, fontWeight: 800,
        letterSpacing: '-0.03em', margin: 0, color: '#2a2018',
        textWrap: 'pretty',
      }}>{headline}</h1>
      <p style={{
        marginTop: 22 * copyScale, marginBottom: 32 * copyScale,
        fontSize: 16 * copyScale, lineHeight: 1.65, color: '#5a4a35',
        maxWidth: 420, textWrap: 'pretty',
        marginLeft: isRight ? 'auto' : 0,
      }}>{sub}</p>
      <div style={{ display: 'flex', gap: 10, alignItems: 'center',
        justifyContent: isRight ? 'flex-end' : 'flex-start' }}>
        <button style={{
          padding: '14px 26px', borderRadius: 999,
          background: accent, color: '#fff', border: 0,
          fontSize: 14, fontWeight: 700, cursor: 'pointer',
          boxShadow: `0 8px 24px ${accent}40`,
        }}>{primaryCta} →</button>
        <button style={{
          padding: '14px 22px', borderRadius: 999,
          background: 'rgba(255,255,255,0.55)',
          backdropFilter: 'blur(6px)', color: '#2a2018',
          border: `1.5px solid #2a201822`,
          fontSize: 14, fontWeight: 600, cursor: 'pointer',
        }}>{secondaryCta}</button>
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// 따뜻한 배경 — 사이트별 톤. 사각형 가구 없음. 큰 둥근 blob + 카페트 + 부드러운 빛.
function WarmRoom({ site }) {
  const p = { ...SITE_PALETTES[site], id: site };
  return (
    <svg
      viewBox="0 0 1440 900"
      style={{ position: 'absolute', inset: 0, display: 'block', width: '100%', height: '100%' }}
      preserveAspectRatio="xMidYMid slice"
    >
      <defs>
        <linearGradient id={`wall-${site}`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={p.wallTop} />
          <stop offset="55%" stopColor={p.wallMid} />
          <stop offset="100%" stopColor={p.wallBot} />
        </linearGradient>
        <linearGradient id={`floor-${site}`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={p.floor} />
          <stop offset="100%" stopColor={p.floorDark} />
        </linearGradient>
        <radialGradient id={`spot-${site}`} cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor={p.glow} stopOpacity={0.7} />
          <stop offset="100%" stopColor={p.glow} stopOpacity={0} />
        </radialGradient>
      </defs>

      {/* 벽 */}
      <rect x={0} y={0} width={1440} height={720} fill={`url(#wall-${site})`} />
      {/* 바닥 */}
      <rect x={0} y={720} width={1440} height={180} fill={`url(#floor-${site})`} />
      <line x1={0} y1={720} x2={1440} y2={720} stroke={INK} strokeWidth={2.5} opacity={0.35} />

      {/* 부드러운 spot light (좌측) — 따뜻한 빛 */}
      <ellipse cx={300} cy={300} rx={360} ry={260} fill={`url(#spot-${site})`} />
      {/* 부드러운 spot light (우상단) */}
      <ellipse cx={1200} cy={200} rx={300} ry={200} fill={`url(#spot-${site})`} opacity={0.7} />


    </svg>
  );
}

// ═════════════════════════════════════════════════════════════════════════════
// T · 11 봇 + 큰 고객
const TALK_BOTS = [
  { name: 'Depression', exp: 'depression' },
  { name: 'Anxiety',    exp: 'anxiety' },
  { name: 'Sleep',      exp: 'sleep' },
  { name: 'Burnout',    exp: 'burnout' },
  { name: 'PTSD',       exp: 'ptsd' },
  { name: 'OCD',        exp: 'ocd' },
  { name: 'Bipolar',    exp: 'bipolar' },
  { name: 'Autism',     exp: 'autism' },
  { name: 'ADHD',       exp: 'adhd' },
  { name: 'Learning',   exp: 'learning' },
  { name: 'Peak',       exp: 'peak' },
  { name: 'Attention',  exp: 'attention' },
];

function BotInArc({ x, y, bot, size = 86 }) {
  const C = bot.C;
  return (
    <div style={{
      position: 'absolute', left: x, top: y,
      transform: 'translate(-50%, -50%)',
      display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3,
      zIndex: 3, pointerEvents: 'none',
    }}>
      <C size={size} />
      <div style={{
        background: '#ffffff', color: INK,
        padding: '2px 8px', borderRadius: 999,
        fontSize: 10, fontWeight: 800, fontFamily: FONT,
        border: `1.5px solid ${INK}`,
        boxShadow: '0 2px 4px rgba(0,0,0,0.08)',
        whiteSpace: 'nowrap', letterSpacing: '-0.005em',
      }}>{bot.sub}</div>
    </div>
  );
}

function PoseTalk({ p, accent }) {
  // 가운데 큰 고객 + 11 봇 위쪽 반호 (각 봇은 고유 디자인). attention(초롱이)은 히어로서 제외(라벨/돋보기 정리).
  const cx = 920, cy = 720, R = 380;
  const arcBots = (window.BOTS || []).filter((b) => b.key !== 'attention');
  return (
    <>
      {/* 봇 11개 위쪽 반호 */}
      {arcBots.map((bot, i) => {
        const angleDeg = -180 + i * 18;
        const angleRad = angleDeg * Math.PI / 180;
        const x = cx + R * Math.cos(angleRad);
        const y = cy + R * Math.sin(angleRad);
        return (
          <BotInArc key={bot.key}
            x={x} y={y}
            bot={bot}
            size={78}
          />
        );
      })}

      {/* 연결 점선 (고객 → 각 봇) */}
      <svg
        style={{ position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 2 }}
        viewBox="0 0 1440 900"
        preserveAspectRatio="xMidYMid slice"
      >
        {TALK_BOTS.filter((b) => b.exp !== 'attention').map((_, i) => {
          const angleDeg = -180 + i * 18;
          const angleRad = angleDeg * Math.PI / 180;
          const x = cx + R * Math.cos(angleRad);
          const y = cy + R * Math.sin(angleRad);
          return (
            <line key={i}
              x1={cx} y1={cy - 30}
              x2={x} y2={y + 70}
              stroke={accent} strokeWidth={1.5}
              strokeDasharray="3 6" opacity={0.4}
            />
          );
        })}
      </svg>

      {/* 가운데 큰 고객 */}
      <div style={{
        position: 'absolute', left: cx, top: cy - 30,
        transform: 'translate(-50%, -50%)',
        zIndex: 4,
      }}>
        <PersonStanding
          expression="learning"
          lean="center"
          width={210}
          bodyColor={p.fabricDeep}
          armRaise="right"
        />
      </div>
    </>
  );
}

// ═════════════════════════════════════════════════════════════════════════════
// B · 부엌 (미니멀) — 큰 standing 두 캐릭터 + 카운터 partial + 작은 도구
function SceneBostonExtras({ p }) {
  return (
    <svg viewBox="0 0 1440 900"
      style={{ position: 'absolute', inset: 0, display: 'block', width: '100%', height: '100%', pointerEvents: 'none' }}
      preserveAspectRatio="xMidYMid slice"
    >
      {/* 따뜻한 태양 (우상단) — 작게, 예약 카드 위쪽 */}
      <defs>
        <radialGradient id="warm-sun-glow" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor={p.sun} stopOpacity={0.65} />
          <stop offset="60%" stopColor={p.sun} stopOpacity={0.25} />
          <stop offset="100%" stopColor={p.sun} stopOpacity={0} />
        </radialGradient>
      </defs>
      <g transform="translate(1230, 60)">
        <circle cx={70} cy={70} r={130} fill="url(#warm-sun-glow)" />
        <circle cx={70} cy={70} r={56} fill={p.sun} />
        <circle cx={70} cy={70} r={36} fill="#ffe19a" />
        <circle cx={70} cy={70} r={18} fill="#fff1c2" />
      </g>

    </svg>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// B · 오프라인 클리닉 예약 모듈
// 따뜻한 appointment card — 3 프로그램 (Inattention / Learning / Peak)
function OfflineBookingCard({ p, initialProgram = 0, onClose, lang = 'ko' }) {
  const [program, setProgram] = React.useState(initialProgram);
  const [day, setDay] = React.useState(2);
  const [slot, setSlot] = React.useState(2);
  const [mode, setMode] = React.useState('offline');
  const [withTool, setWithTool] = React.useState(false);
  const [videoOpen, setVideoOpen] = React.useState(false);
  React.useEffect(() => { setProgram(initialProgram); }, [initialProgram]);

  const videos = [
    { ko: '뉴로피드백 소개',    en: 'Neurofeedback intro',     dur: '3:42' },
    { ko: 'ADHD 사례 연구',     en: 'ADHD case study',         dur: '7:15' },
    { ko: '난독증 학습 코칭',   en: 'Dyslexia coaching',       dur: '5:28' },
    { ko: '최고수행 훈련',      en: 'Peak performance training', dur: '4:55' },
    { ko: '14년 임상 인터뷰',   en: '14-year clinical interview', dur: '12:30' },
    { ko: '집에서 하는 방법',   en: 'Home training guide',     dur: '6:10' },
  ];

  const programs = [
    { ko: '주의집중', en: 'Attention',       descKo: 'ADHD · 집중력 신경훈련',     descEn: 'ADHD · focus neuro-training',     color: '#E8A317' },
    { ko: '학습',     en: 'Learning',        descKo: '난독·작업기억 회복 코칭',    descEn: 'Reading & working-memory coaching', color: '#6B9B5C' },
    { ko: '최고수행', en: 'Peak Performance', descKo: '학업·운동 멘탈 최적화',     descEn: 'Academic & athletic mental optimization', color: '#4A90C2' },
  ];

  const daysKo = ['월', '화', '수', '목', '금'];
  const daysEn = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'];
  const days = lang === 'en' ? daysEn : daysKo;
  const slots = ['09:30', '11:00', '14:00', '15:30', '17:00', '19:00'];

  // 4주 캘린더 — 평일만 (Mon-Fri × 4주 = 20일)
  const weekGrid = React.useMemo(() => {
    const today = new Date();
    let start = new Date(today);
    // 다음 월요일 찾기
    while (start.getDay() !== 1) start.setDate(start.getDate() + 1);
    const grid = [];
    for (let w = 0; w < 4; w++) {
      for (let d = 0; d < 5; d++) {
        const date = new Date(start);
        date.setDate(start.getDate() + w * 7 + d);
        grid.push(date);
      }
    }
    return grid;
  }, []);

  const selectedDate = weekGrid[day] || weekGrid[0];
  const monthYear = (() => {
    const first = weekGrid[0];
    const last = weekGrid[weekGrid.length - 1];
    if (lang === 'en') {
      if (first.getMonth() === last.getMonth()) {
        return `${first.toLocaleString('en-US', { month: 'long' })} ${first.getFullYear()}`;
      }
      return `${first.toLocaleString('en-US', { month: 'short' })} – ${last.toLocaleString('en-US', { month: 'short' })} ${last.getFullYear()}`;
    }
    if (first.getMonth() === last.getMonth()) {
      return `${first.getFullYear()}년 ${first.getMonth() + 1}월`;
    }
    return `${first.getFullYear()}년 ${first.getMonth() + 1}–${last.getMonth() + 1}월`;
  })();

  const pg = programs[program];
  const pgName  = lang === 'en' ? pg.en   : pg.ko;
  const pgDesc  = lang === 'en' ? pg.descEn : pg.descKo;

  const L = {
    eyebrowOffline: lang === 'en' ? 'In-person clinic' : '오프라인 클리닉',
    eyebrowOnline:  lang === 'en' ? 'Online session'   : '온라인 세션',
    eyebrowTool:    lang === 'en' ? 'Mental health tool' : '멘탈헬스 툴',
    offline:    lang === 'en' ? 'Offline' : '오프라인',
    online:     lang === 'en' ? 'Online'  : '온라인',
    tool:       lang === 'en' ? 'Tools Purchase Questions' : '툴 구매 문의',
    toolDesc:   lang === 'en' ? 'Add neurofeedback kit · Online Tool' : '뉴로피드백 키트 추가 · 온라인 툴',
    toolPrice:  lang === 'en' ? '+$249' : '+₩320,000',
    location:   'BOSTON · MA',
    locationOnline: lang === 'en' ? 'REMOTE · ZOOM' : '원격 · ZOOM',
    locationTool:   lang === 'en' ? 'SHIP WORLDWIDE' : '전세계 배송',
    title:      lang === 'en' ? 'Book a session'   : '세션 예약하기',
    titleTool:  lang === 'en' ? 'Purchase tools'   : '툴 구매하기',
    subtitle:   '',
    subtitleTool: lang === 'en' ? 'Clinically vetted neurofeedback devices & kits' : '임상 검증된 뉴로피드백 기기·키트',
    nextWeek:   lang === 'en' ? 'Next week'        : '다음 주',
    weekTag:    lang === 'en' ? 'Week 2 of Nov ›'  : '11월 둘째 주 ›',
    available:  lang === 'en' ? 'Available times'  : '가능 시간',
    footnote:   lang === 'en'
      ? 'Free 15-min consult · Free changes/cancellation up to 24h before'
      : '무료 15분 예약 · 변경/취소 24h 전까지 무료',
    footnoteTool: lang === 'en'
      ? 'Includes training · 30-day return · Clinician support'
      : '훈련 포함 · 30일 환불 · 임상가 지원',
    ctaSuffix:  lang === 'en' ? 'Book' : '예약',
    watchVideos: lang === 'en' ? 'Watch intro videos' : '동영상 보기',
    minutes:     lang === 'en' ? 'min' : '분',
    ctaTool:    lang === 'en' ? 'Add to cart' : '장바구니',
    dateLabel:  lang === 'en' ? '' : '일',
  };

  return (
    <div style={{
      position: 'relative', width: 392,
      background: '#fffdf6',
      border: `2px solid ${INK}`,
      borderRadius: 22,
      padding: '22px 24px 18px',
      fontFamily: FONT,
      boxShadow: '0 24px 60px rgba(80, 50, 10, 0.22), 0 6px 14px rgba(0,0,0,0.06)',
    }}>
      {onClose && (
        <button onClick={onClose}
          onMouseEnter={(e) => { e.currentTarget.style.background = '#1f1d1a'; e.currentTarget.style.color = '#fff'; e.currentTarget.style.transform = 'scale(1.08)'; }}
          onMouseLeave={(e) => { e.currentTarget.style.background = '#f4ede0'; e.currentTarget.style.color = INK; e.currentTarget.style.transform = 'scale(1)'; }}
          onMouseDown={(e) => { e.currentTarget.style.transform = 'scale(0.94)'; }}
          onMouseUp={(e) => { e.currentTarget.style.transform = 'scale(1.08)'; }}
          style={{
            position: 'absolute', top: 14, right: 14,
            width: 28, height: 28, borderRadius: 999,
            background: '#f4ede0', border: `1.5px solid ${INK}22`,
            color: INK, fontSize: 14, fontWeight: 800,
            cursor: 'pointer', lineHeight: 1,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontFamily: FONT,
            transition: 'background 0.15s, color 0.15s, transform 0.15s',
          }}>×</button>
      )}
      {/* Header strip */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <span style={{ width: 7, height: 7, borderRadius: 999, background: p.accent }} />
          <span style={{ fontSize: 10, fontWeight: 800, color: p.accent,
            letterSpacing: '0.16em', textTransform: 'uppercase' }}>
            {mode === 'online' ? L.eyebrowOnline : L.eyebrowOffline}
          </span>
        </div>
        <span style={{ fontSize: 9, color: '#9a8763', fontWeight: 700, letterSpacing: '0.08em' }}>
          {mode === 'online' ? L.locationOnline : L.location}
        </span>
      </div>

      {/* Mode toggle — Offline / Online */}
      <div style={{
        display: 'flex', alignItems: 'center',
        padding: 3, marginBottom: 10,
        background: '#f4ede0',
        border: `1.5px solid ${INK}1a`,
        borderRadius: 999,
        gap: 0,
      }}>
        {[
          { key: 'offline', label: L.offline, icon: 'building' },
          { key: 'online',  label: L.online,  icon: 'monitor' },
        ].map((m) => {
          const active = mode === m.key;
          return (
            <button key={m.key}
              onClick={() => setMode(m.key)}
              style={{
                flex: 1, padding: '7px 12px',
                background: active ? '#fff' : 'transparent',
                border: 0,
                borderRadius: 999,
                color: active ? INK : '#8a7654',
                fontFamily: FONT, fontSize: 11.5, fontWeight: 700,
                cursor: 'pointer',
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
                boxShadow: active ? `0 2px 6px rgba(31,29,26,0.12)` : 'none',
                transition: 'all 0.15s',
                whiteSpace: 'nowrap',
              }}>
              <svg width={13} height={13} viewBox="0 0 14 14" style={{ flexShrink: 0 }}>
                {m.icon === 'building' && (
                  <g stroke={active ? INK : '#8a7654'} strokeWidth={1.3} fill="none">
                    <rect x={2} y={3} width={10} height={10} rx={1} />
                    <line x1={5} y1={6} x2={5} y2={7.5} />
                    <line x1={9} y1={6} x2={9} y2={7.5} />
                    <line x1={5} y1={10} x2={5} y2={11.5} />
                    <line x1={9} y1={10} x2={9} y2={11.5} />
                  </g>
                )}
                {m.icon === 'monitor' && (
                  <g stroke={active ? INK : '#8a7654'} strokeWidth={1.3} fill="none" strokeLinecap="round">
                    <rect x={1.5} y={3} width={11} height={7} rx={1} />
                    <line x1={4} y1={12} x2={10} y2={12} />
                    <line x1={7} y1={10} x2={7} y2={12} />
                  </g>
                )}
              </svg>
              {m.label}
            </button>
          );
        })}
      </div>

      {/* Tools Purchase 체크박스 — 추가 옵션 */}
      <label style={{
        display: 'flex', alignItems: 'center', gap: 10,
        padding: '9px 12px',
        marginBottom: 14,
        background: withTool ? `${p.accent}14` : '#fffdf6',
        border: `1.5px solid ${withTool ? p.accent : INK + '1f'}`,
        borderRadius: 12,
        cursor: 'pointer',
        fontFamily: FONT,
        transition: 'background 0.15s, border-color 0.15s',
        userSelect: 'none',
      }}>
        <input type="checkbox"
          checked={withTool}
          onChange={(e) => setWithTool(e.target.checked)}
          style={{ display: 'none' }} />
        {/* Custom checkbox */}
        <span style={{
          width: 16, height: 16, borderRadius: 4,
          border: `1.5px solid ${withTool ? p.accent : INK + '44'}`,
          background: withTool ? p.accent : '#fff',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          flexShrink: 0,
          transition: 'all 0.15s',
        }}>
          {withTool && (
            <svg width={10} height={10} viewBox="0 0 10 10">
              <path d="M2,5 L4,7 L8,3" stroke="#fff" strokeWidth={1.8}
                fill="none" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          )}
        </span>
        {/* Cart icon */}
        <svg width={14} height={14} viewBox="0 0 14 14" style={{ flexShrink: 0 }}>
          <g stroke={withTool ? p.accent : '#8a7654'} strokeWidth={1.3} fill="none" strokeLinecap="round" strokeLinejoin="round">
            <path d="M2,3 L4,3 L5,9 L11,9 L12,5 L4.5,5" />
            <circle cx={5.5} cy={11.5} r={1} />
            <circle cx={10.5} cy={11.5} r={1} />
          </g>
        </svg>
        <div style={{ flex: 1 }}>
          <div style={{
            fontSize: 12, fontWeight: 700, color: INK,
            letterSpacing: '-0.005em',
          }}>{L.tool}</div>
          <div style={{ fontSize: 10, color: '#8a7654', marginTop: 1 }}>
            {L.toolDesc}
          </div>
        </div>
        <div style={{
          fontSize: 11, fontWeight: 800, color: withTool ? p.accent : '#8a7654',
        }}>{L.toolPrice}</div>
      </label>

      <div style={{ fontSize: 22, fontWeight: 800, color: INK,
        letterSpacing: '-0.022em', marginBottom: 16, lineHeight: 1.1 }}>
        {L.title}
      </div>

      {/* Program tabs */}
      <div style={{ display: 'flex', gap: 6, marginBottom: 14 }}>
        {programs.map((p2, i) => (
          <button key={p2.en}
            onClick={() => setProgram(i)}
            style={{
              flex: 1, padding: '10px 4px',
              background: program === i ? `${p2.color}1c` : '#fff',
              border: `1.5px solid ${program === i ? p2.color : INK + '1a'}`,
              borderRadius: 12,
              fontFamily: FONT, cursor: 'pointer',
              display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 2,
              transition: 'all 0.14s ease',
            }}>
            <span style={{ fontSize: 12, fontWeight: 800, color: INK,
              letterSpacing: '-0.01em' }}>{lang === 'en' ? p2.en : p2.ko}</span>
            <span style={{ fontSize: 9, color: program === i ? p2.color : '#8a7654',
              fontWeight: 700, letterSpacing: '0.02em' }}>{lang === 'en' ? p2.ko : p2.en}</span>
          </button>
        ))}
      </div>

      {/* Program description */}
      <div style={{
        background: `${pg.color}10`,
        borderLeft: `3px solid ${pg.color}`,
        borderRadius: 6,
        padding: '8px 12px',
        marginBottom: 16,
        fontSize: 12, color: INK, fontWeight: 500, lineHeight: 1.45,
      }}>
        {pgDesc}
      </div>

      {/* Date strip */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        marginBottom: 8 }}>
        <span style={{ fontSize: 11, fontWeight: 800, color: INK,
          letterSpacing: '0.06em' }}>{monthYear}</span>
        <span style={{ fontSize: 10, color: '#9a8763', fontWeight: 700 }}>{lang === 'en' ? 'Next 4 weeks' : '4주간'}</span>
      </div>
      {/* Day-of-week labels */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)',
        gap: 5, marginBottom: 4 }}>
        {days.map((d, i) => (
          <div key={i} style={{
            fontSize: 9, fontWeight: 800, color: '#8a7654',
            letterSpacing: '0.04em', textAlign: 'center',
          }}>{d}</div>
        ))}
      </div>
      {/* 4 주 × 5 평일 그리드 */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 1fr)',
        gap: 5, marginBottom: 16 }}>
        {weekGrid.map((date, i) => {
          const isSelected = day === i;
          const isMonthBoundary = i > 0 && weekGrid[i - 1].getMonth() !== date.getMonth();
          return (
            <button key={i}
              onClick={() => setDay(i)}
              onMouseEnter={(e) => { if (!isSelected) e.currentTarget.style.background = `${INK}10`; }}
              onMouseLeave={(e) => { if (!isSelected) e.currentTarget.style.background = '#fff'; }}
              style={{
                padding: '8px 0',
                background: isSelected ? INK : '#fff',
                border: `1.5px solid ${isSelected ? INK : INK + '1f'}`,
                borderRadius: 10,
                cursor: 'pointer', fontFamily: FONT,
                display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 1,
                transition: 'all 0.12s',
                position: 'relative',
              }}>
              {isMonthBoundary && (
                <span style={{
                  position: 'absolute', top: -2, right: 4,
                  fontSize: 7, fontWeight: 800, color: p.accent,
                }}>{lang === 'en' ? date.toLocaleString('en-US', { month: 'short' }) : `${date.getMonth() + 1}월`}</span>
              )}
              <span style={{ fontSize: 15, color: isSelected ? '#fff' : INK,
                fontWeight: 800, lineHeight: 1 }}>{date.getDate()}</span>
            </button>
          );
        })}
      </div>

      {/* Time slots */}
      <div style={{ fontSize: 10, fontWeight: 800, color: INK, opacity: 0.55,
        letterSpacing: '0.1em', textTransform: 'uppercase', marginBottom: 8 }}>
        {L.available}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr',
        gap: 6, marginBottom: 16 }}>
        {slots.map((s, i) => {
          const disabled = i === 1;  // 한 슬롯은 마감으로 표시 (현실감)
          return (
            <button key={s}
              onClick={() => !disabled && setSlot(i)}
              disabled={disabled}
              style={{
                padding: '8px 0',
                background: disabled
                  ? '#f4ede0'
                  : (slot === i ? p.accent : '#fff'),
                border: `1.5px solid ${disabled
                  ? INK + '15'
                  : (slot === i ? p.accent : INK + '1f')}`,
                borderRadius: 999,
                cursor: disabled ? 'not-allowed' : 'pointer',
                fontFamily: FONT,
                fontSize: 12, fontWeight: 700,
                color: disabled
                  ? '#b0a48a'
                  : (slot === i ? '#fff' : INK),
                textDecoration: disabled ? 'line-through' : 'none',
              }}>
              {s}
            </button>
          );
        })}
      </div>

      {/* CTA */}
      <button
        onMouseEnter={(e) => { e.currentTarget.style.transform = 'translateY(-2px)'; e.currentTarget.style.boxShadow = '0 12px 28px rgba(31,29,26,0.32)'; }}
        onMouseLeave={(e) => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = '0 8px 20px rgba(31,29,26,0.22)'; }}
        onMouseDown={(e) => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = '0 3px 8px rgba(31,29,26,0.32)'; }}
        onMouseUp={(e) => { e.currentTarget.style.transform = 'translateY(-2px)'; e.currentTarget.style.boxShadow = '0 12px 28px rgba(31,29,26,0.32)'; }}
        style={{
        width: '100%', padding: '14px',
        background: INK, color: '#fff',
        border: 0, borderRadius: 14,
        fontFamily: FONT, fontSize: 13, fontWeight: 800,
        cursor: 'pointer', letterSpacing: '-0.005em',
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
        boxShadow: '0 8px 20px rgba(31,29,26,0.22)',
        transition: 'transform 0.18s ease, box-shadow 0.18s ease',
      }}>
        {pgName} · {mode === 'online' ? L.online : L.offline}{withTool ? ' + ' + L.tool : ''} · {days[day % 5]} {selectedDate.getMonth() + 1}/{selectedDate.getDate()} {slots[slot]} {L.ctaSuffix}
        <span style={{ fontSize: 14 }}>→</span>
      </button>

      {/* Footnote */}
      <div style={{ marginTop: 10, fontSize: 10, color: '#9a8763',
        textAlign: 'center', fontWeight: 500, lineHeight: 1.5 }}>
        {L.footnote}
      </div>

      {/* Video list — collapsible */}
      <div style={{ marginTop: 14, borderTop: `1px dashed ${INK}22`, paddingTop: 12 }}>
        <button onClick={() => setVideoOpen(!videoOpen)}
          style={{
            width: '100%', padding: '6px 4px',
            background: 'transparent', border: 0,
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            cursor: 'pointer', fontFamily: FONT,
          }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
            <svg width={14} height={14} viewBox="0 0 14 14">
              <circle cx={7} cy={7} r={6} stroke={p.accent} strokeWidth={1.4} fill="none" />
              <path d="M5.5,4.5 L9.5,7 L5.5,9.5 Z" fill={p.accent} />
            </svg>
            <span style={{ fontSize: 11.5, fontWeight: 700, color: INK,
              letterSpacing: '-0.005em' }}>{L.watchVideos}</span>
            <span style={{
              fontSize: 9, fontWeight: 700, color: '#fff',
              background: p.accent, padding: '2px 6px', borderRadius: 999,
            }}>{videos.length}</span>
          </div>
          <span style={{
            fontSize: 10, color: '#8a7654',
            transform: videoOpen ? 'rotate(180deg)' : 'rotate(0)',
            transition: 'transform 0.2s',
          }}>▾</span>
        </button>
        {videoOpen && (
          <div style={{
            marginTop: 8, maxHeight: 168, overflowY: 'auto',
            border: `1px solid ${INK}1a`, borderRadius: 10,
            background: '#fffdf6',
          }}>
            {videos.map((v, i) => (
              <a key={i} href={`#video-${i}`}
                onMouseEnter={(e) => { e.currentTarget.style.background = `${p.accent}10`; }}
                onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}
                style={{
                  display: 'flex', alignItems: 'center', gap: 10,
                  padding: '8px 12px',
                  borderBottom: i < videos.length - 1 ? `1px solid ${INK}10` : 0,
                  textDecoration: 'none',
                  color: INK,
                  cursor: 'pointer',
                  transition: 'background 0.12s',
                }}>
                {/* Play icon */}
                <div style={{
                  width: 24, height: 24, borderRadius: 999,
                  background: `${p.accent}1f`,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  flexShrink: 0,
                }}>
                  <svg width={10} height={10} viewBox="0 0 10 10">
                    <path d="M3,2 L8,5 L3,8 Z" fill={p.accent} />
                  </svg>
                </div>
                {/* Title */}
                <span style={{
                  flex: 1, fontSize: 11.5, fontWeight: 600,
                  color: INK, letterSpacing: '-0.005em',
                }}>{lang === 'en' ? v.en : v.ko}</span>
                {/* Duration */}
                <span style={{
                  fontSize: 10, fontWeight: 700, color: '#8a7654',
                  letterSpacing: '0.02em',
                }}>{v.dur}</span>
              </a>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// 가슴 명찰 — Decision · Training, 각각 독립 호버/클릭
function ChestBadge({ accent, onBook, lang = 'en' }) {
  const [hoverL, setHoverL] = React.useState(false);
  const [hoverR, setHoverR] = React.useState(false);
  const [pressL, setPressL] = React.useState(false);
  const [pressR, setPressR] = React.useState(false);
  const anyHover = hoverL || hoverR;

  return (
    <div style={{
      position: 'absolute',
      left: '50%', top: '52%',
      transform: `translate(-50%, ${anyHover ? '-53%' : '-50%'}) rotate(-2deg)`,
      display: 'flex', alignItems: 'stretch',
      border: `2px solid ${INK}`,
      borderRadius: 6,
      overflow: 'hidden',
      boxShadow: anyHover
        ? `0 5px 0 ${INK}35, 0 9px 18px rgba(0,0,0,0.20)`
        : `0 3px 0 ${INK}30, 0 5px 12px rgba(0,0,0,0.15)`,
      fontFamily: FONT,
      background: '#fff',
      zIndex: 3,
      transition: 'transform 0.18s ease, box-shadow 0.18s ease',
      userSelect: 'none',
    }}>
      {/* Decision half */}
      <button
        onClick={(e) => { e.stopPropagation(); onBook && onBook(); }}
        onMouseEnter={() => setHoverL(true)}
        onMouseLeave={() => { setHoverL(false); setPressL(false); }}
        onMouseDown={() => setPressL(true)}
        onMouseUp={() => setPressL(false)}
        style={{
          padding: '5px 11px 5px 10px',
          background: accent,
          color: '#fff',
          display: 'flex', alignItems: 'center', gap: 5,
          fontSize: 9, fontWeight: 800,
          letterSpacing: '0.05em',
          border: 0, cursor: 'pointer',
          fontFamily: FONT,
          filter: hoverL ? 'brightness(1.18) saturate(1.1)' : 'brightness(1)',
          transform: pressL ? 'scale(0.96)' : (hoverL ? 'scale(1.04)' : 'scale(1)'),
          boxShadow: hoverL ? `inset 0 0 0 1.5px #ffffff66` : 'none',
          transition: 'filter 0.15s, transform 0.15s, box-shadow 0.15s',
        }}>
        <svg width={10} height={10} viewBox="0 0 10 10" style={{ flexShrink: 0 }}>
          <path d="M2,5 L4.5,7.5 L8,3" stroke="#fff" strokeWidth={1.7}
            fill="none" strokeLinecap="round" strokeLinejoin="round" />
        </svg>
        {lang === 'ko' ? '판별' : 'DECISION'}
      </button>

      {/* Training half */}
      <button
        onClick={(e) => { e.stopPropagation(); onBook && onBook(); }}
        onMouseEnter={() => setHoverR(true)}
        onMouseLeave={() => { setHoverR(false); setPressR(false); }}
        onMouseDown={() => setPressR(true)}
        onMouseUp={() => setPressR(false)}
        style={{
          padding: '5px 11px 5px 10px',
          background: hoverR ? `${accent}22` : '#fff',
          color: hoverR ? accent : INK,
          borderLeft: `2px solid ${INK}`,
          borderTop: 0, borderRight: 0, borderBottom: 0,
          display: 'flex', alignItems: 'center', gap: 5,
          fontSize: 9, fontWeight: 800,
          letterSpacing: '0.05em',
          cursor: 'pointer',
          fontFamily: FONT,
          transform: pressR ? 'scale(0.96)' : (hoverR ? 'scale(1.04)' : 'scale(1)'),
          transition: 'background 0.15s, color 0.15s, transform 0.15s',
        }}>
        <svg width={12} height={10} viewBox="0 0 12 10" style={{ flexShrink: 0 }}>
          <path d="M1,6 L3,6 L4,3 L6,8 L7,5 L9,5 L10,3 L11,6"
            stroke={accent} strokeWidth={1.7} fill="none"
            strokeLinecap="round" strokeLinejoin="round" />
        </svg>
        {lang === 'ko' ? '훈련' : 'TRAINING'}
      </button>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// 뉴로피드백 발판 — 심플한 명판 디스크 (NEUROFEEDBACK 글씨 새김)
function NeuroFootplate({ accent }) {
  return (
    <svg width={206} height={42} viewBox="0 0 206 42"
      style={{
        position: 'absolute',
        bottom: 0, left: '50%',
        transform: 'translateX(-50%)',
        pointerEvents: 'none',
        overflow: 'visible',
        zIndex: 1,
      }}>
      {/* 그림자 */}
      <ellipse cx={103} cy={40} rx={78} ry={1.8} fill="rgba(31,29,26,0.14)" />

      {/* 실제 EEG 신호 — 부드러운 베지에 곡선 */}
      <path d="M8,14 C 12,14 14,11 18,14 S 24,17 28,14 S 33,9 38,14 S 44,18 48,14 S 53,6 58,14 S 64,21 68,14 S 74,12 78,14 S 84,17 88,14 S 94,11 98,14 S 105,3 110,14 S 117,22 122,14 S 128,12 132,14 S 138,17 142,14 S 148,11 152,14 S 158,17 162,14 S 168,7 172,12 S 180,18 184,14 S 190,11 194,14 L 198,14"
        stroke={accent} strokeWidth={1.5} fill="none"
        strokeLinecap="round" strokeLinejoin="round" opacity={0.9} />

      {/* 양끝 전극 dot */}
      <circle cx={8} cy={14} r={2.5} fill={accent} stroke={INK} strokeWidth={1} />
      <circle cx={198} cy={14} r={2.5} fill={accent} stroke={INK} strokeWidth={1} />

      {/* NEUROFEEDBACK 워드마크 — 작고 세련되게 */}
      <text x={103} y={32} fontSize={9.5} fontWeight={500}
        fill="#6e5b3f" fontFamily='"Fredoka","Pretendard",sans-serif'
        textAnchor="middle" letterSpacing="4">
        NEUROFEEDBACK
      </text>
    </svg>
  );
}

// 작은 가슴 타겟 — Attention 캐릭터 전용
function TinyChestTarget({ accent }) {
  return (
    <svg width={28} height={28} viewBox="0 0 28 28"
      style={{
        position: 'absolute',
        left: '50%', top: '40%',
        transform: 'translate(-50%, -50%) rotate(-4deg)',
        zIndex: 4,
        pointerEvents: 'none',
        filter: `drop-shadow(0 2px 3px rgba(31,29,26,0.18))`,
      }}>
      {/* outer */}
      <circle cx={14} cy={14} r={11.5}
        stroke={INK} strokeWidth={1.8} fill="#fffdf6" />
      {/* ring 1 */}
      <circle cx={14} cy={14} r={8.5}
        stroke={INK} strokeWidth={1.2} fill={accent} fillOpacity={0.22} />
      {/* ring 2 */}
      <circle cx={14} cy={14} r={5.2}
        stroke={INK} strokeWidth={1.2} fill={accent} fillOpacity={0.6} />
      {/* center dot */}
      <circle cx={14} cy={14} r={2.2}
        fill={accent} stroke={INK} strokeWidth={0.9} />
      {/* tiny arrow */}
      <line x1={24} y1={3} x2={15} y2={12}
        stroke={INK} strokeWidth={1.6} strokeLinecap="round" />
      <path d="M22,1 L25,2 L26,5 Z"
        fill={INK} stroke={INK} strokeWidth={1} strokeLinejoin="round" />
    </svg>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// N · 11 봇 시계 — Peak Performance 메타포
// 시침=상담가, 분침=고객. 11개 봇이 1~11시 위치, 12시는 PEAK 목표.
// 실시간 시계 — 시침/분침이 현재 시각에 따라 움직임.
function BotsPeakClock({ p, lang = 'ko' }) {
  const W = 280, H = 280;
  const cx = W / 2, cy = W / 2;
  const R = 100;

  const BOTS = window.BOTS || [];
  const angleOf = (h) => -Math.PI / 2 + (h / 12) * Math.PI * 2;

  // 실시간
  const [now, setNow] = React.useState(() => new Date());
  React.useEffect(() => {
    const id = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(id);
  }, []);

  const hh = now.getHours() % 12;
  const mm = now.getMinutes();
  const ss = now.getSeconds();
  // 시침(상담가) — 시 + 분 보정
  const counselorA = -Math.PI / 2 + ((hh + mm / 60) / 12) * Math.PI * 2;
  // 분침(고객) — 분 + 초 보정
  const clientA = -Math.PI / 2 + ((mm + ss / 60) / 60) * Math.PI * 2;

  const minutes = Array.from({ length: 60 }, (_, i) => i);

  return (
    <div style={{
      position: 'absolute', left: '50%', top: 122, zIndex: 3,
      transform: 'translateX(-50%)',
      width: W, height: H, fontFamily: FONT,
    }}>
      {/* 바닥 SVG — 표적 + 화살 */}
      <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`}
        style={{ display: 'block', overflow: 'visible',
          position: 'absolute', inset: 0 }}>
        <defs>
          <radialGradient id="targetGlow" cx="50%" cy="50%" r="50%">
            <stop offset="0%" stopColor={p.accent} stopOpacity={0.18} />
            <stop offset="100%" stopColor={p.accent} stopOpacity={0} />
          </radialGradient>
        </defs>
        {/* 부드러운 외광 */}
        <circle cx={cx} cy={cy} r={R + 60} fill="url(#targetGlow)" />

        {/* 표적 링 — 4겹 동심원 (테두리 없이) */}
        <circle cx={cx} cy={cy} r={R + 12} fill="#ffffff" />
        <circle cx={cx} cy={cy} r={R - 6} fill="none"
          stroke={p.accent} strokeWidth={1.4} opacity={0.45} />
        <circle cx={cx} cy={cy} r={R - 28} fill={p.accent} fillOpacity={0.08}
          stroke={p.accent} strokeWidth={1.4} opacity={0.55} />
        <circle cx={cx} cy={cy} r={R - 50} fill={p.accent} fillOpacity={0.18}
          stroke={p.accent} strokeWidth={1.4} opacity={0.7} />
        {/* 중앙 불스아이 + DSM5-TR 워터마크 */}
        <circle cx={cx} cy={cy} r={R - 72} fill={p.accent}
          stroke={INK} strokeWidth={1.8} />
        <text x={cx} y={cy + 4} fontSize={9} fontWeight={800}
          fill="#ffffff" fillOpacity={0.7} textAnchor="middle"
          fontFamily={FONT} letterSpacing="0.14em">DSM5-TR</text>

        {/* 12시 — PEAK 마커 (봇 아이콘과 동일한 크기/톤) */}
        <g transform={`translate(${cx}, ${cy - R})`}>
          <circle cx={0} cy={0} r={18} fill="#ffffff"
            stroke={INK} strokeWidth={2} />
          <polygon
            points="0,-10 3,-3 10,-3 4.5,1.5 6.5,9 0,4.5 -6.5,9 -4.5,1.5 -10,-3 -3,-3"
            fill={p.accent} stroke={INK} strokeWidth={1.5}
            strokeLinejoin="round" />
        </g>

      </svg>

      {/* 봇 아이콘 레이어 — 1~11시 위치 */}
      {BOTS.map((bot, i) => {
        const h = i + 1;
        const a = angleOf(h);
        const cosA = Math.cos(a), sinA = Math.sin(a);
        const x = cx + cosA * R;
        const y = cy + sinA * R;
        const size = 42;
        // 라벨 위치 — 아이콘 바깥으로
        const lr = R + 48;
        const lx = cx + cosA * lr;
        const ly = cy + sinA * lr;
        let align = 'center';
        if (cosA > 0.35) align = 'left';
        else if (cosA < -0.35) align = 'right';
        const BotC = bot.C;
        return (
          <React.Fragment key={bot.key}>
            <div style={{
              position: 'absolute',
              left: x - size / 2,
              top: y - size * 0.55,
              width: size,
              height: size * 1.1,
              pointerEvents: 'none',
            }}>
              {BotC && <BotC size={size} />}
            </div>
            <div style={{
              position: 'absolute',
              left: lx - 40,
              top: ly - 8,
              width: 80,
              fontSize: 10,
              fontWeight: 700,
              color: INK,
              opacity: 0.75,
              textAlign: align,
              fontFamily: FONT,
              letterSpacing: '-0.005em',
              pointerEvents: 'none',
            }}>{bot.sub}</div>
          </React.Fragment>
        );
      })}

      {/* 상단 SVG — 시계 바늘 + 중심핀 (봇 위에 떠 있어야 함) */}
      <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`}
        style={{ display: 'block', overflow: 'visible',
          position: 'absolute', inset: 0, pointerEvents: 'none' }}>
        {/* 시침 — 상담가 (티어드롭 셔이프, 따뜻한 accent) */}
        <g transform={`translate(${cx}, ${cy}) rotate(${counselorA * 180 / Math.PI + 90})`}>
          <path d={`M -4,10 Q -2,2 -2,-${R * 0.55} Q 0,-${R * 0.60} 2,-${R * 0.55} Q 2,2 4,10 Z`}
            fill={p.accent} stroke={p.accent} strokeWidth={1}
            strokeLinejoin="round" opacity={0.95} />
        </g>

        {/* 분침 — 고객 (수 섥어 더 긴 티어드롭) */}
        <g transform={`translate(${cx}, ${cy}) rotate(${clientA * 180 / Math.PI + 90})`}>
          <path d={`M -2.5,8 Q -1.2,2 -1.2,-${R * 0.86} Q 0,-${R * 0.90} 1.2,-${R * 0.86} Q 1.2,2 2.5,8 Z`}
            fill={p.accent} stroke={p.accent} strokeWidth={0.5}
            strokeLinejoin="round" opacity={0.7} />
        </g>

        {/* 중심 핀 */}
        <circle cx={cx} cy={cy} r={6.5} fill={INK} />
        <circle cx={cx} cy={cy} r={2.8} fill={p.accent} />
      </svg>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// B · Peak Performance — 시계 메타포 (참고용, 현재 미사용)
// 시침=상담가, 분침=고객. 11개 핵심 영역이 1~11시 위치, 12시는 PEAK 목표.
function PeakClock({ boxW, accent, lang = 'ko' }) {
  const W = boxW, H = 280;
  const cx = W / 2, cy = 132;
  const R = 72;

  const items = lang === 'en' ? [
    'Breath', 'Focus', 'Image', 'Recover', 'Belief',
    'Routine', 'Sleep', 'Energy', 'Drive', 'Talk', 'Press'
  ] : [
    '호흡', '집중', '시각화', '회복', '자신감',
    '루틴', '수면', '에너지', '동기', '토크', '압박'
  ];

  // 시계 각도: 12시 = -π/2 (위), 시계방향 증가
  const angleOf = (h) => -Math.PI / 2 + (h / 12) * Math.PI * 2;

  // 시침(상담가) — 11시 부근
  const counselorA = angleOf(10.7);
  // 분침(고객) — 1시 부근
  const clientA = angleOf(1.3);

  // 미세 분 단위 틱(60개)
  const minutes = Array.from({ length: 60 }, (_, i) => i);

  return (
    <div style={{
      position: 'relative', width: W, height: H,
    }}>
      <svg width={W} height={H} viewBox={`0 0 ${W} ${H}`}
        style={{ overflow: 'visible', display: 'block' }}>
        {/* 후광 */}
        <circle cx={cx} cy={cy} r={R + 22} fill={accent} fillOpacity={0.05} />
        {/* 시계판 */}
        <circle cx={cx} cy={cy} r={R + 8} fill="#fffdf6"
          stroke={INK} strokeWidth={2.5} />
        {/* 내부 점선 링 */}
        <circle cx={cx} cy={cy} r={R - 14} fill="none"
          stroke={accent} strokeWidth={1} strokeDasharray="2 4" opacity={0.5} />

        {/* 분 단위 미세 틱 */}
        {minutes.map(m => {
          const a = -Math.PI / 2 + (m / 60) * Math.PI * 2;
          const isHour = m % 5 === 0;
          const r1 = isHour ? R - 3 : R + 1;
          const r2 = R + 6;
          return (
            <line key={m}
              x1={cx + Math.cos(a) * r1} y1={cy + Math.sin(a) * r1}
              x2={cx + Math.cos(a) * r2} y2={cy + Math.sin(a) * r2}
              stroke={INK} strokeWidth={isHour ? 1.4 : 0.6}
              opacity={isHour ? 1 : 0.35} />
          );
        })}

        {/* 11개 영역 — 1~11시 위치 */}
        {[1,2,3,4,5,6,7,8,9,10,11].map(h => {
          const a = angleOf(h);
          const cosA = Math.cos(a), sinA = Math.sin(a);
          const x = cx + cosA * R;
          const y = cy + sinA * R;
          // 라벨 위치 — 시계 바깥
          const lr = R + 21;
          const lx = cx + cosA * lr;
          const ly = cy + sinA * lr;
          // 라벨 정렬
          let anchor = 'middle';
          if (cosA > 0.3) anchor = 'start';
          else if (cosA < -0.3) anchor = 'end';
          return (
            <g key={h}>
              {/* 숫자 원 */}
              <circle cx={x} cy={y} r={9.5} fill="#fffdf6"
                stroke={INK} strokeWidth={1.6} />
              <text x={x} y={y + 3.3} fontSize={9.5} fontWeight={800}
                fill={INK} textAnchor="middle" fontFamily={FONT}>{h}</text>
              {/* 영역 라벨 */}
              <text x={lx} y={ly + 2.8} fontSize={7.5} fontWeight={700}
                fill={INK} fillOpacity={0.72} textAnchor={anchor}
                fontFamily={FONT} letterSpacing="-0.01em">
                {items[h - 1]}
              </text>
            </g>
          );
        })}

        {/* 12시 — PEAK 마커 (별) */}
        <g transform={`translate(${cx}, ${cy - R - 4})`}>
          {/* 빛 */}
          <g opacity={0.7}>
            {[-1, 0, 1].map(k => (
              <line key={k} x1={k * 12} y1={-20} x2={k * 12} y2={-13}
                stroke={accent} strokeWidth={1.5} strokeLinecap="round"
                opacity={0.6} />
            ))}
          </g>
          <circle cx={0} cy={0} r={16} fill={accent} fillOpacity={0.16} />
          {/* 별 */}
          <polygon
            points="0,-13 3.8,-4.2 13.5,-4.2 5.7,1.8 8.8,11 0,5.3 -8.8,11 -5.7,1.8 -13.5,-4.2 -3.8,-4.2"
            fill={accent} stroke={INK} strokeWidth={2}
            strokeLinejoin="round" />
        </g>
        <text x={cx} y={cy - R - 25} fontSize={10} fontWeight={800}
          fill={INK} textAnchor="middle" fontFamily={FONT}
          letterSpacing="0.22em">PEAK</text>

        {/* 시침 — 상담가 (짧고 굵게, 11시 방향) */}
        <line x1={cx} y1={cy}
          x2={cx + Math.cos(counselorA) * (R * 0.50)}
          y2={cy + Math.sin(counselorA) * (R * 0.50)}
          stroke={INK} strokeWidth={6.5} strokeLinecap="round" />
        {/* 상담가 머리 (안경 — 신뢰감) */}
        <g transform={`translate(${cx + Math.cos(counselorA) * (R * 0.55)}, ${cy + Math.sin(counselorA) * (R * 0.55)})`}>
          <circle cx={0} cy={0} r={11} fill={accent}
            stroke={INK} strokeWidth={2} />
          <circle cx={-3.2} cy={-1} r={2.4}
            fill="#fffdf6" stroke={INK} strokeWidth={1.2} />
          <circle cx={3.2} cy={-1} r={2.4}
            fill="#fffdf6" stroke={INK} strokeWidth={1.2} />
          <line x1={-0.8} y1={-1} x2={0.8} y2={-1}
            stroke={INK} strokeWidth={1.2} />
          <path d="M-3,3.5 Q0,5.2 3,3.5" stroke={INK} strokeWidth={1.2}
            fill="none" strokeLinecap="round" />
        </g>

        {/* 분침 — 고객 (길고 가늘게, 1시 방향) */}
        <line x1={cx} y1={cy}
          x2={cx + Math.cos(clientA) * (R * 0.78)}
          y2={cy + Math.sin(clientA) * (R * 0.78)}
          stroke={INK} strokeWidth={3.5} strokeLinecap="round" />
        {/* 고객 머리 */}
        <g transform={`translate(${cx + Math.cos(clientA) * (R * 0.84)}, ${cy + Math.sin(clientA) * (R * 0.84)})`}>
          <circle cx={0} cy={0} r={9} fill="#fffdf6"
            stroke={INK} strokeWidth={2} />
          <circle cx={-2.6} cy={-1} r={1} fill={INK} />
          <circle cx={2.6} cy={-1} r={1} fill={INK} />
          <path d="M-2.5,2.8 Q0,4.5 2.5,2.8" stroke={INK} strokeWidth={1.1}
            fill="none" strokeLinecap="round" />
        </g>

        {/* 중심 핀 */}
        <circle cx={cx} cy={cy} r={5.5} fill={INK} />
        <circle cx={cx} cy={cy} r={2} fill={accent} />

        {/* 범례 — 하단 */}
        <g transform={`translate(${cx}, 248)`}>
          {/* 상담가 */}
          <g transform="translate(-58, 0)">
            <rect x={-18} y={-3.5} width={14} height={6} rx={3}
              fill={INK} />
            <circle cx={2} cy={0} r={6} fill={accent}
              stroke={INK} strokeWidth={1.5} />
            <circle cx={0.5} cy={-0.5} r={1.1}
              fill="#fffdf6" stroke={INK} strokeWidth={0.6} />
            <circle cx={3.5} cy={-0.5} r={1.1}
              fill="#fffdf6" stroke={INK} strokeWidth={0.6} />
            <text x={12} y={2.5} fontSize={9} fontWeight={700}
              fill={INK} fontFamily={FONT}>
              {lang === 'en' ? 'Therapist' : '상담가'}
            </text>
            <text x={12} y={13} fontSize={6.5} fontWeight={600}
              fill={INK} fillOpacity={0.55} fontFamily={FONT}
              letterSpacing="0.08em">
              {lang === 'en' ? 'HOUR HAND' : '시침'}
            </text>
          </g>
          {/* 고객 */}
          <g transform="translate(34, 0)">
            <rect x={-20} y={-2} width={18} height={3} rx={1.5}
              fill={INK} />
            <circle cx={4} cy={0} r={5} fill="#fffdf6"
              stroke={INK} strokeWidth={1.5} />
            <circle cx={2.6} cy={-0.5} r={0.6} fill={INK} />
            <circle cx={5.4} cy={-0.5} r={0.6} fill={INK} />
            <text x={12} y={2.5} fontSize={9} fontWeight={700}
              fill={INK} fontFamily={FONT}>
              {lang === 'en' ? 'Client' : '고객'}
            </text>
            <text x={12} y={13} fontSize={6.5} fontWeight={600}
              fill={INK} fillOpacity={0.55} fontFamily={FONT}
              letterSpacing="0.08em">
              {lang === 'en' ? 'MIN HAND' : '분침'}
            </text>
          </g>
        </g>
      </svg>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// B · 에피소드 카드 — 오프라인 캐릭터 + 관련 온라인 도구를 한 풍경에 통합
function EpisodeCard({ kind, onBook, lang = 'ko' }) {
  const config = {
    inattention: {
      label: { ko: '주의집중', en: 'Attention' },
      en: 'Attention',
      desc: { ko: 'ADHD · 집중력 신경훈련', en: 'ADHD · Focus neuro-training' },
      tag: { ko: '60분 · 1:1 임상', en: '60min · 1:1 clinical' },
      accent: '#E8A317', bodyColor: '#a87a3a',
      expression: 'learning',
      tools: { talk: true, neuro: true, modality: true, boston: true },
    },
    learning: {
      label: { ko: '학습', en: 'Learning' },
      en: 'Learning',
      desc: { ko: '난독·작업기억 회복 코칭', en: 'Dyslexia & working memory coaching' },
      tag: { ko: '50분 · 1:1 임상', en: '50min · 1:1 clinical' },
      accent: '#6B9B5C', bodyColor: '#a8c188',
      expression: 'learning', role: 'therapist', props: 'book',
      tools: { talk: true, neuro: true, modality: true, boston: true },
    },
    peak: {
      label: { ko: '최고수행', en: 'Peak Performance' },
      en: 'Peak Performance',
      desc: { ko: '학업·운동 멘탈 최적화', en: 'Academic & athletic mental optimization' },
      tag: { ko: '60분 · 1:1 임상', en: '60min · 1:1 clinical' },
      accent: '#4A90C2', bodyColor: '#5c7587',
      expression: 'performance', armRaise: 'right', props: 'headphones',
      tools: { talk: true, neuro: true, modality: true, boston: true },
    },
  };
  const c = config[kind];
  const charW = 170;
  const boxW = charW + 60;

  const toolMeta = {
    talk:     { ko: '상담봇',   en: 'Talk',   file: 'https://agedlearning.com', note: '대화' },
    boston:   { ko: '증상결정', en: 'Decide', file: 'https://agedlearning.com', note: '통합' },
    neuro:    { ko: '개별증상', en: 'Track',  file: 'https://agedlearning.com/track', note: '트래킹' },
    modality: { ko: '치료방법', en: 'Method', file: 'https://agedlearning.com', note: '매칭' },
  };
  const toolOrder = ['talk', 'boston', 'neuro', 'modality'];

  return (
    <div style={{
      width: boxW + 36, padding: '20px 18px 18px',
      background: '#fffdf6',
      border: `2px solid ${INK}`,
      borderRadius: 22,
      boxShadow: `0 8px 0 ${INK}1c, 0 14px 32px rgba(80, 50, 10, 0.10)`,
      fontFamily: FONT,
      display: 'flex', flexDirection: 'column', alignItems: 'center',
    }}>
      {/* 헤더 — 프로그램 이름 (eyebrow 제거, 깔끔한 영어 톤) */}
      <div style={{ textAlign: 'center', marginBottom: 6, minHeight: 96 }}>
        <div style={{
          display: 'inline-flex', alignItems: 'center', gap: 6,
          marginBottom: 8,
        }}>
          <span style={{ width: 6, height: 6, borderRadius: 999, background: c.accent }} />
          <span style={{
            width: 18, height: 1.5, background: c.accent, borderRadius: 1,
          }} />
        </div>
        <div style={{ fontSize: 22, fontWeight: 700, color: INK,
          letterSpacing: '-0.022em', lineHeight: 1.15 }}>
          {c.label[lang] || c.label.ko}
        </div>
        <div style={{ fontSize: 12, color: '#6e5b3f', marginTop: 6,
          fontWeight: 400, lineHeight: 1.4 }}>
          {c.desc[lang] || c.desc.ko}
        </div>
      </div>

      {/* 캐릭터 + 발판 + props — scene visual */}
      <div style={{ position: 'relative', width: boxW, height: 280,
        display: 'flex', justifyContent: 'center', alignItems: 'flex-end',
        marginBottom: 4 }}>
        {/* 뉴로피드백 발판 — 캐릭터 발 밑 */}
        <NeuroFootplate accent={c.accent} />
        {/* 캐릭터 (발판 위에 올라서도록 약간 위로) */}
        <div style={{ position: 'relative', zIndex: 2, marginBottom: 28 }}>
          <PersonStanding
            expression={c.expression}
            lean="center"
            width={charW}
            bodyColor={c.bodyColor}
            armRaise={c.armRaise}
            walking={c.walking}
            role={c.role}
          />
        </div>
        {/* 가슴 명찰 — Decision · Training (각각 독립 호버/클릭) */}
        <ChestBadge accent={c.accent} onBook={onBook} lang={lang} />
        {/* Attention 전용 — 작은 가슴 타겟 */}
        {kind === 'inattention' && <TinyChestTarget accent={c.accent} />}
        <svg style={{
          position: 'absolute', top: 0, left: 0, right: 0, bottom: 0,
          pointerEvents: 'none', overflow: 'visible',
        }} viewBox={`0 0 ${boxW} 270`} preserveAspectRatio="xMidYMax meet">
          {c.props === 'thoughts' && (
            <g>
              <circle cx={26} cy={32} r={16} fill="#fff" stroke={INK} strokeWidth={2.5} />
              <text x={26} y={39} fontSize={18} fontWeight={800} fill={INK}
                textAnchor="middle" fontFamily={FONT}>?</text>
              <circle cx={8} cy={62} r={5} fill="#fff" stroke={INK} strokeWidth={2} />

              <circle cx={boxW - 32} cy={18} r={12} fill="#fff" stroke={INK} strokeWidth={2.5} />
              <text x={boxW - 32} y={24} fontSize={14} fontWeight={800} fill={c.accent}
                textAnchor="middle" fontFamily={FONT}>!</text>

              <circle cx={boxW - 16} cy={74} r={10} fill="#fff" stroke={INK} strokeWidth={2.5} />
              <path d={`M${boxW - 20},70 L${boxW - 16},78 L${boxW - 12},70 Z`}
                fill={c.accent} stroke="none" />
            </g>
          )}
          {c.props === 'target' && (
            <g transform={`translate(${boxW/2 - 28}, 178)`}>
              {/* drop shadow */}
              <ellipse cx={28} cy={56} rx={28} ry={3} fill="rgba(31,29,26,0.16)" />
              {/* faint focus ring */}
              <circle cx={28} cy={26} r={32}
                stroke={c.accent} strokeWidth={1} fill="none"
                strokeDasharray="2 5" opacity={0.28} />
              {/* bullseye outer */}
              <circle cx={28} cy={26} r={26}
                stroke={INK} strokeWidth={2.5} fill="#fffdf6" />
              {/* rings */}
              <circle cx={28} cy={26} r={19}
                stroke={INK} strokeWidth={1.5} fill={c.accent} fillOpacity={0.15} />
              <circle cx={28} cy={26} r={13}
                stroke={INK} strokeWidth={1.5} fill="#fffdf6" />
              <circle cx={28} cy={26} r={7}
                stroke={INK} strokeWidth={1.5} fill={c.accent} fillOpacity={0.55} />
              {/* center dot */}
              <circle cx={28} cy={26} r={3}
                fill={c.accent} stroke={INK} strokeWidth={1.2} />
              {/* arrow shaft */}
              <line x1={54} y1={4} x2={30} y2={24}
                stroke={INK} strokeWidth={2.5} strokeLinecap="round" />
              {/* arrow fletching */}
              <path d="M52,1 L55,4 L58,1 L55,7 Z"
                fill={INK} stroke={INK} strokeWidth={1.2} strokeLinejoin="round" />
              {/* arrow head */}
              <path d="M30,24 L35,20 L35,24 L40,24 Z"
                fill={INK} stroke={INK} strokeWidth={1.2} strokeLinejoin="round" />
            </g>
          )}
          {c.props === 'book' && (
            <g transform={`translate(${boxW/2 - 48}, 154)`}>
              <ellipse cx={48} cy={58} rx={52} ry={4} fill="rgba(31,29,26,0.15)" />
              <path d="M2,10 Q2,4 8,4 L46,4 L48,48 L8,54 Q2,54 2,48 Z"
                stroke={INK} strokeWidth={3} fill="#fff" strokeLinejoin="round" />
              <path d="M48,4 L88,4 Q94,4 94,10 L94,48 Q94,54 88,54 L48,48 Z"
                stroke={INK} strokeWidth={3} fill={c.accent} strokeLinejoin="round" />
              <line x1={48} y1={4} x2={48} y2={48} stroke={INK} strokeWidth={3} />
              <line x1={12} y1={18} x2={40} y2={18} stroke={INK} strokeWidth={1.5} opacity={0.55} />
              <line x1={12} y1={26} x2={40} y2={26} stroke={INK} strokeWidth={1.5} opacity={0.55} />
              <line x1={12} y1={34} x2={36} y2={34} stroke={INK} strokeWidth={1.5} opacity={0.55} />
              <line x1={56} y1={18} x2={86} y2={18} stroke="#fff" strokeWidth={1.5} opacity={0.75} />
              <line x1={56} y1={26} x2={86} y2={26} stroke="#fff" strokeWidth={1.5} opacity={0.75} />
              <line x1={56} y1={34} x2={80} y2={34} stroke="#fff" strokeWidth={1.5} opacity={0.75} />
            </g>
          )}
          {c.props === 'headphones' && (
            <>
              <g transform={`translate(${boxW/2 - 52}, 16)`}>
                <path d="M14,52 Q14,6 52,6 Q90,6 90,52"
                  stroke={INK} strokeWidth={5.5} fill="none" strokeLinecap="round" />
                <rect x={2} y={48} width={20} height={30} rx={6}
                  stroke={INK} strokeWidth={3} fill={c.accent} />
                <rect x={82} y={48} width={20} height={30} rx={6}
                  stroke={INK} strokeWidth={3} fill={c.accent} />
              </g>
              <g transform={`translate(${boxW - 30}, 36)`}>
                <path d="M0,0 L10,-9 L8,3 L18,-5"
                  stroke={c.accent} strokeWidth={3.5} fill="none"
                  strokeLinecap="round" strokeLinejoin="round" />
              </g>
            </>
          )}
        </svg>
      </div>

      {/* 지원 온라인 도구 — 4개 칩, 관련 도구만 활성 */}
      <div style={{
        width: '100%', marginTop: 6, marginBottom: 12,
        paddingTop: 12, borderTop: `1.5px dashed ${INK}1f`,
      }}>
        <div style={{
          fontSize: 9, fontWeight: 700, color: '#8a7654',
          letterSpacing: '0.16em', textTransform: 'uppercase',
          marginBottom: 8, textAlign: 'center',
        }}>{lang === 'en' ? 'Tools used together' : '함께 쓰는 온라인'}</div>
        <div style={{ display: 'flex', gap: 14, justifyContent: 'center' }}>
          {toolOrder.map(key => {
            const active = c.tools[key];
            const site = SITE_COLORS[key];
            const t = toolMeta[key];

            const Icon = () => {
              if (key === 'talk') return (
                <path d="M3,5 Q3,2 6,2 L14,2 Q17,2 17,5 L17,11 Q17,14 14,14 L9,14 L6,17 L7,14 L6,14 Q3,14 3,11 Z"
                  stroke="#fff" strokeWidth={1.7} fill="none" strokeLinejoin="round" />
              );
              if (key === 'boston') return (
                <g>
                  <rect x={3} y={4} width={14} height={14} rx={2}
                    stroke="#fff" strokeWidth={1.7} fill="none" />
                  <rect x={7} y={2} width={6} height={3} rx={1}
                    stroke="#fff" strokeWidth={1.7} fill="none" />
                  <line x1={6} y1={9} x2={14} y2={9} stroke="#fff" strokeWidth={1.4} />
                  <line x1={6} y1={12} x2={12} y2={12} stroke="#fff" strokeWidth={1.4} />
                </g>
              );
              if (key === 'neuro') return (
                <path d="M3,14 L7,9 L10,11 L14,5 L17,7"
                  stroke="#fff" strokeWidth={2} fill="none"
                  strokeLinecap="round" strokeLinejoin="round" />
              );
              if (key === 'modality') return (
                <g>
                  <circle cx={5} cy={5} r={2.5} stroke="#fff" strokeWidth={1.7} fill="none" />
                  <circle cx={15} cy={5} r={2.5} stroke="#fff" strokeWidth={1.7} fill="none" />
                  <circle cx={10} cy={14} r={2.5} stroke="#fff" strokeWidth={1.7} fill="none" />
                  <line x1={6} y1={7} x2={9} y2={12} stroke="#fff" strokeWidth={1.4} />
                  <line x1={14} y1={7} x2={11} y2={12} stroke="#fff" strokeWidth={1.4} />
                </g>
              );
              return null;
            };

            return (
              <a key={key} href={t.file} target="_blank" rel="noopener"
                title={`${t.ko} · ${t.note}`}
                onMouseEnter={(e) => {
                  e.currentTarget.style.transform = 'translateY(-5px)';
                  const ring = e.currentTarget.querySelector('div');
                  if (ring) {
                    ring.style.boxShadow = `0 7px 0 ${INK}55, 0 0 0 6px ${site.value}33, 0 10px 18px ${site.value}66`;
                  }
                  const lbl = e.currentTarget.querySelector('span');
                  if (lbl) { lbl.style.opacity = 1; lbl.style.fontWeight = 800; }
                }}
                onMouseLeave={(e) => {
                  e.currentTarget.style.transform = 'translateY(0)';
                  const ring = e.currentTarget.querySelector('div');
                  if (ring) {
                    ring.style.boxShadow = `0 3px 0 ${INK}40, 0 0 0 3px ${site.value}1f`;
                  }
                  const lbl = e.currentTarget.querySelector('span');
                  if (lbl) { lbl.style.opacity = 0.85; lbl.style.fontWeight = 600; }
                }}
                onMouseDown={(e) => {
                  e.currentTarget.style.transform = 'translateY(-1px)';
                  const ring = e.currentTarget.querySelector('div');
                  if (ring) ring.style.boxShadow = `0 1px 0 ${INK}55, 0 0 0 4px ${site.value}40`;
                }}
                style={{
                  textDecoration: 'none',
                  display: 'flex', flexDirection: 'column',
                  alignItems: 'center', gap: 4,
                  cursor: 'pointer',
                  opacity: 1,
                  transition: 'transform 0.18s ease',
                }}>
                <div style={{
                  width: 42, height: 42, borderRadius: '50%',
                  background: site.value,
                  border: `2px solid ${INK}`,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  boxShadow: `0 3px 0 ${INK}40, 0 0 0 3px ${site.value}1f`,
                  flexShrink: 0,
                  transition: 'box-shadow 0.18s ease',
                }}>
                  <svg viewBox="0 0 20 20" width={20} height={20}>
                    <Icon />
                  </svg>
                </div>
                <span style={{
                  fontSize: 10, fontWeight: 600, color: INK,
                  letterSpacing: '-0.005em', fontFamily: FONT,
                  opacity: 0.85,
                }}>{lang === 'en' ? t.en : t.ko}</span>
              </a>
            );
          })}
        </div>
      </div>

      {/* 예약 CTA — 작고 부담 없게 */}
      <button onClick={onBook}
        onMouseEnter={(e) => {
          e.currentTarget.style.background = c.accent;
          e.currentTarget.style.color = '#fff';
          e.currentTarget.style.transform = 'translateY(-2px)';
          e.currentTarget.style.boxShadow = `0 6px 16px ${c.accent}66`;
        }}
        onMouseLeave={(e) => {
          e.currentTarget.style.background = 'transparent';
          e.currentTarget.style.color = c.accent;
          e.currentTarget.style.transform = 'translateY(0)';
          e.currentTarget.style.boxShadow = 'none';
        }}
        onMouseDown={(e) => {
          e.currentTarget.style.transform = 'translateY(0)';
          e.currentTarget.style.boxShadow = `0 2px 5px ${c.accent}55`;
        }}
        onMouseUp={(e) => {
          e.currentTarget.style.transform = 'translateY(-2px)';
          e.currentTarget.style.boxShadow = `0 6px 16px ${c.accent}66`;
        }}
        style={{
          marginTop: 4, padding: '8px 18px',
          alignSelf: 'center',
          background: 'transparent', color: c.accent,
          border: `1.5px solid ${c.accent}`,
          borderRadius: 999,
          fontFamily: FONT, fontSize: 12, fontWeight: 700,
          cursor: 'pointer', letterSpacing: '-0.005em',
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
          transition: 'background 0.18s ease, color 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease',
        }}
      >
        {lang === 'en' ? 'Book Session →' : '세션 예약 →'}
      </button>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// 작은 ONLINE 상품 카드 — 토픽별 캐릭터+미니 UI로 4개 시스템 차별화
function OnlineProductCard({ siteKey }) {
  const meta = {
    talk: {
      ko: '상담봇캐쳐', en: 'TalkCatcher', file: 'https://agedlearning.com',
      tagline: '11명의 봇 · 24/7 대화',
      expression: 'anxiety', bodyColor: '#a8bccd',
      lean: 'right', armRaise: null,
    },
    boston: {
      ko: '증상판별캐쳐', en: 'BostonNeuroMind', file: 'https://agedlearning.com',
      tagline: '14년 통합 임상 매칭',
      expression: 'learning', bodyColor: '#e3c180',
      lean: 'center', role: 'therapist',
    },
    neuro: {
      ko: '증상별캐쳐', en: 'NeuroCatchers', file: 'https://agedlearning.com/track',
      tagline: '매일 패턴 트래킹',
      expression: 'performance', bodyColor: '#e8a472',
      lean: 'left',
    },
    modality: {
      ko: '훈련법캐쳐', en: 'ModalityCatcher', file: 'https://agedlearning.com',
      tagline: 'CBT·MBSR 맞춤 매칭',
      expression: 'happy', bodyColor: '#c0d3b3',
      lean: 'right',
    },
  }[siteKey];
  const site = SITE_COLORS[siteKey];
  const charW = 96;

  // 토픽별 비주얼 props
  const TopicVisual = () => {
    if (siteKey === 'talk') {
      // 옆에 채팅 말풍선
      return (
        <g transform="translate(108, 16)">
          <path d="M0,12 Q0,4 8,4 L52,4 Q60,4 60,12 L60,30 Q60,38 52,38 L20,38 L12,46 L14,38 L8,38 Q0,38 0,30 Z"
            stroke={INK} strokeWidth={2.5} fill="#fff" strokeLinejoin="round" />
          <circle cx={18} cy={21} r={2.5} fill={site.value} />
          <circle cx={30} cy={21} r={2.5} fill={site.value} />
          <circle cx={42} cy={21} r={2.5} fill={site.value} />
        </g>
      );
    }
    if (siteKey === 'boston') {
      // 옆에 클립보드/레시피
      return (
        <g transform="translate(108, 14)">
          <rect x={0} y={8} width={56} height={66} rx={6}
            stroke={INK} strokeWidth={2.5} fill="#fff" />
          <rect x={18} y={0} width={20} height={14} rx={3}
            stroke={INK} strokeWidth={2.5} fill={site.value} />
          <line x1={8} y1={26} x2={48} y2={26} stroke={INK} strokeWidth={1.5} opacity={0.45} />
          <line x1={8} y1={36} x2={48} y2={36} stroke={INK} strokeWidth={1.5} opacity={0.45} />
          <line x1={8} y1={46} x2={42} y2={46} stroke={INK} strokeWidth={1.5} opacity={0.45} />
          <circle cx={12} cy={58} r={3} stroke={site.value} strokeWidth={2} fill="none" />
          <path d="M10,58 L12,60 L15,55" stroke={site.value} strokeWidth={2}
            fill="none" strokeLinecap="round" strokeLinejoin="round" />
          <line x1={20} y1={58} x2={48} y2={58} stroke={INK} strokeWidth={1.5} opacity={0.45} />
        </g>
      );
    }
    if (siteKey === 'neuro') {
      // 옆에 차트
      return (
        <g transform="translate(108, 22)">
          <rect x={0} y={0} width={64} height={50} rx={6}
            stroke={INK} strokeWidth={2.5} fill="#fff" />
          <path d="M6,40 L18,28 L26,32 L38,18 L52,22 L58,14"
            stroke={site.value} strokeWidth={2.8} fill="none"
            strokeLinecap="round" strokeLinejoin="round" />
          <circle cx={58} cy={14} r={3} fill={site.value} stroke={INK} strokeWidth={1.5} />
          <line x1={6} y1={44} x2={58} y2={44} stroke={INK} strokeWidth={1} opacity={0.3} />
        </g>
      );
    }
    if (siteKey === 'modality') {
      // 옆에 매칭/방법 다이어그램
      return (
        <g transform="translate(110, 18)">
          <circle cx={12} cy={12} r={9} stroke={INK} strokeWidth={2.5} fill={site.value} />
          <text x={12} y={16} fontSize={10} fontWeight={800} fill="#fff"
            textAnchor="middle" fontFamily={FONT}>A</text>
          <circle cx={50} cy={12} r={9} stroke={INK} strokeWidth={2.5} fill="#fff" />
          <text x={50} y={16} fontSize={10} fontWeight={800} fill={INK}
            textAnchor="middle" fontFamily={FONT}>?</text>
          <circle cx={12} cy={50} r={9} stroke={INK} strokeWidth={2.5} fill="#fff" />
          <text x={12} y={54} fontSize={10} fontWeight={800} fill={INK}
            textAnchor="middle" fontFamily={FONT}>B</text>
          <circle cx={50} cy={50} r={9} stroke={INK} strokeWidth={2.5} fill="#fff" />
          <text x={50} y={54} fontSize={10} fontWeight={800} fill={INK}
            textAnchor="middle" fontFamily={FONT}>C</text>
          <line x1={21} y1={12} x2={41} y2={12} stroke={site.value} strokeWidth={2.5} strokeDasharray="3 3" />
          <line x1={12} y1={21} x2={12} y2={41} stroke={INK} strokeWidth={1.5} opacity={0.4} />
          <line x1={50} y1={21} x2={50} y2={41} stroke={INK} strokeWidth={1.5} opacity={0.4} />
        </g>
      );
    }
    return null;
  };

  return (
    <a href={meta.file} target="_blank" rel="noopener"
      style={{
        textDecoration: 'none',
        width: 180, height: 210,
        background: '#fffdf6',
        border: `2px solid ${INK}`,
        borderRadius: 16,
        boxShadow: `0 4px 0 ${INK}1a, 0 8px 18px rgba(80,50,10,0.07)`,
        overflow: 'hidden',
        fontFamily: FONT,
        display: 'flex', flexDirection: 'column',
        cursor: 'pointer',
        transition: 'transform 0.16s ease',
      }}
      onMouseEnter={(e) => e.currentTarget.style.transform = 'translateY(-3px)'}
      onMouseLeave={(e) => e.currentTarget.style.transform = 'translateY(0)'}
    >
      {/* 헤더: site color bar */}
      <div style={{
        background: site.value,
        padding: '7px 12px',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        color: '#fff',
      }}>
        <span style={{ fontSize: 10, fontWeight: 800, letterSpacing: '0.06em' }}>
          {meta.en}
        </span>
        <span style={{ fontSize: 11, opacity: 0.85 }}>→</span>
      </div>

      {/* 캐릭터 + 토픽 비주얼 */}
      <div style={{
        flex: 1, position: 'relative',
        background: `${site.value}0e`,
        display: 'flex', alignItems: 'flex-end', justifyContent: 'flex-start',
        paddingLeft: 6, overflow: 'hidden',
      }}>
        <PersonStanding
          expression={meta.expression}
          lean={meta.lean}
          width={charW}
          bodyColor={meta.bodyColor}
          role={meta.role}
          style={{ marginBottom: -8 }}
        />
        <svg style={{
          position: 'absolute', top: 0, left: 0, right: 0, bottom: 0,
          overflow: 'visible', pointerEvents: 'none',
        }} viewBox="0 0 190 160" preserveAspectRatio="xMidYMid meet">
          <TopicVisual />
        </svg>
      </div>

      {/* 풋터: ko 이름 + tagline */}
      <div style={{
        padding: '10px 12px 11px',
        background: '#fffdf6',
        borderTop: `1.5px solid ${INK}1a`,
      }}>
        <div style={{ fontSize: 14, fontWeight: 800, color: INK,
          letterSpacing: '-0.02em', lineHeight: 1.1 }}>{meta.ko}</div>
        <div style={{ fontSize: 10.5, color: '#6e5b3f', marginTop: 3,
          fontWeight: 500, lineHeight: 1.3 }}>{meta.tagline}</div>
      </div>
    </a>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// 예약 모달 — backdrop + OfflineBookingCard
function BookingModal({ open, onClose, initialProgram, p, lang = 'ko' }) {
  if (!open) return null;
  return (
    <div style={{
      position: 'absolute', inset: 0, zIndex: 100,
      background: 'rgba(40, 30, 10, 0.45)',
      backdropFilter: 'blur(6px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
    }} onClick={onClose}>
      <div onClick={(e) => e.stopPropagation()}>
        <OfflineBookingCard p={p} initialProgram={initialProgram} onClose={onClose} lang={lang} />
      </div>
    </div>
  );
}

function SmallBoat({ label, color, width = 240 }) {
  const h = 90;
  return (
    <div style={{
      width, height: h, position: 'relative',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      cursor: 'pointer',
    }}>
      <svg viewBox={`0 0 ${width} ${h}`} width={width} height={h}
        style={{ display: 'block', overflow: 'visible', position: 'absolute', inset: 0 }}>
        <ellipse cx={width/2} cy={h - 6} rx={width/2 - 12} ry={5} fill="rgba(31,29,26,0.15)" />
        {/* 그림자 레이어 (버튼 그림자) */}
        <path d={`M14,16 L${width-14},16 Q${width-30},${h-8} ${width-50},${h-4} L50,${h-4} Q30,${h-8} 14,16 Z`}
          fill="rgba(31,29,26,0.35)" />
        {/* 메인 버튼 */}
        <path d={`M10,8 L${width-10},8 Q${width-30},${h-12} ${width-50},${h-8} L50,${h-8} Q30,${h-12} 10,8 Z`}
          stroke={INK} strokeWidth={4.5} fill={color} strokeLinejoin="round" />
        {/* 위쌄 하이라이트 */}
        <path d={`M16,10 L${width-16},10`}
          stroke="rgba(255,255,255,0.45)" strokeWidth={3} strokeLinecap="round" />
      </svg>
      <div style={{
        position: 'relative', zIndex: 2,
        display: 'flex', alignItems: 'center', gap: 6,
        fontFamily: FONT,
        marginTop: -10,
      }}>
        <span style={{
          fontSize: 14, fontWeight: 800, color: '#ffffff',
          letterSpacing: '-0.005em',
          textShadow: '0 1px 1px rgba(0,0,0,0.18)',
        }}>{label}</span>
        <span style={{
          color: '#ffffff', opacity: 0.9, fontSize: 13, fontWeight: 800,
        }}>→</span>
      </div>
    </div>
  );
}

// 5개 옵션 메달 (사주 · 관상 · 손금 · 타로 · MBTI)
function Medal({ label, sub, color, symbol, size = 160, rotate = 0 }) {
  return (
    <div style={{
      width: size,
      transform: `rotate(${rotate}deg)`,
      display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 10,
    }}>
      {/* 메달 본체 */}
      <div style={{
        width: size, height: size, borderRadius: '50%',
        background: color,
        border: `5px solid ${INK}`,
        boxShadow: `0 12px 28px rgba(0,0,0,0.18), inset 0 -8px 0 rgba(0,0,0,0.08)`,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        position: 'relative',
      }}>
        {/* 메달 안쪽 라인 */}
        <div style={{
          width: size - 28, height: size - 28, borderRadius: '50%',
          border: `2px dashed ${INK}55`,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <span style={{
            fontSize: size * 0.4, fontWeight: 800, color: INK,
            fontFamily: 'system-ui, "Apple SD Gothic Neo", serif',
            lineHeight: 1,
          }}>{symbol}</span>
        </div>
        {/* 작은 리본 (상단) */}
        <div style={{
          position: 'absolute', top: -16, left: '50%',
          transform: 'translateX(-50%)',
          width: 30, height: 22,
          background: INK,
          clipPath: 'polygon(0 0, 100% 0, 80% 100%, 50% 70%, 20% 100%)',
        }} />
      </div>
      {/* 라벨 */}
      <div style={{ textAlign: 'center', fontFamily: FONT }}>
        <div style={{ fontSize: 15, fontWeight: 800, color: INK, letterSpacing: '-0.01em' }}>{label}</div>
        <div style={{ fontSize: 11, color: '#5a4a35', marginTop: 2, letterSpacing: '0.05em', textTransform: 'uppercase' }}>{sub}</div>
      </div>
    </div>
  );
}

function InsightFish({ fish, lang }) {
  const [hover, setHover] = React.useState(false);
  const [press, setPress] = React.useState(false);
  const scale = press ? 0.94 : (hover ? 1.18 : 1);
  return (
    <g
      transform={`translate(${fish.x}, 28) scale(${scale})`}
      style={{
        cursor: 'pointer',
        transition: 'transform 0.18s cubic-bezier(0.34, 1.56, 0.64, 1)',
      }}
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => { setHover(false); setPress(false); }}
      onMouseDown={() => setPress(true)}
      onMouseUp={() => setPress(false)}
    >
      {/* glow ring on hover */}
      {hover && (
        <ellipse cx={4} cy={0} rx={32} ry={16}
          fill={fish.color} opacity={0.22} />
      )}
      {/* 몸 */}
      <path d="M-22,0 Q-18,-10 0,-10 Q18,-10 22,0 Q18,10 0,10 Q-18,10 -22,0 Z"
        stroke={INK} strokeWidth={hover ? 2.5 : 2}
        fill={fish.color} strokeLinejoin="round" />
      {/* 꼬리 */}
      <path d="M22,0 L34,-8 L31,0 L34,8 Z"
        stroke={INK} strokeWidth={hover ? 2.5 : 2}
        fill={fish.color} strokeLinejoin="round" />
      {/* 눈 */}
      <circle cx={10} cy={-2} r={hover ? 2.3 : 1.8} fill={INK} />
      {hover && (
        <circle cx={10.5} cy={-2.5} r={0.7} fill="#fff" />
      )}
      {/* 라벨 */}
      <text x={0} y={-18} fontFamily={FONT}
        fontSize={hover ? 11 : 10}
        fontWeight={hover ? 900 : 800}
        fill={INK} textAnchor="middle"
        style={{ transition: 'font-size 0.18s' }}>
        {fish.name[lang] || fish.name.ko}
      </text>
    </g>
  );
}

// 큰 천둥 헤로 — 애니메이션 번개가 사이트 톱을 지배
function BigThunderHero() {
  return (
    <div style={{
      position: 'absolute', top: 70, left: '50%',
      transform: 'translateX(-50%)', zIndex: 3,
      width: 920, height: 240,
      pointerEvents: 'none',
    }}>
      <svg viewBox="0 0 920 240" width={920} height={240}
        style={{ display: 'block', overflow: 'visible' }}>
        <defs>
          <linearGradient id="bolt-grad-main" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="#FFE066" stopOpacity="1" />
            <stop offset="50%" stopColor="#FFD23F" stopOpacity="1" />
            <stop offset="100%" stopColor="#E8A317" stopOpacity="1" />
          </linearGradient>
          <linearGradient id="bolt-grad-side" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="#FFD23F" stopOpacity="0.95" />
            <stop offset="100%" stopColor="#E89417" stopOpacity="0.95" />
          </linearGradient>
          <radialGradient id="flash-aura" cx="50%" cy="50%" r="50%">
            <stop offset="0%" stopColor="#FFE066" stopOpacity="0.45" />
            <stop offset="60%" stopColor="#FFD23F" stopOpacity="0.18" />
            <stop offset="100%" stopColor="#FFD23F" stopOpacity="0" />
          </radialGradient>
          <filter id="bolt-glow">
            <feGaussianBlur stdDeviation="2" result="blur"/>
            <feMerge>
              <feMergeNode in="blur"/>
              <feMergeNode in="SourceGraphic"/>
            </feMerge>
          </filter>
        </defs>

        {/* 배경 플래시 후광 (펄스) */}
        <ellipse cx={460} cy={130} rx={460} ry={110}
          fill="url(#flash-aura)" className="thunder-aura" />

        {/* 구름 띠 (탑) */}
        <ellipse cx={460} cy={6} rx={380} ry={6} fill="rgba(31,29,26,0.22)" />
        <ellipse cx={300} cy={10} rx={90} ry={7} fill="rgba(31,29,26,0.18)" />
        <ellipse cx={620} cy={10} rx={90} ry={7} fill="rgba(31,29,26,0.18)" />
        <ellipse cx={160} cy={12} rx={70} ry={5} fill="rgba(31,29,26,0.12)" />
        <ellipse cx={760} cy={12} rx={70} ry={5} fill="rgba(31,29,26,0.12)" />

        {/* 메인 큰 번개 — 가운데 */}
        <path d="M 462,12 L 416,90 L 454,90 L 428,184 L 504,76 L 466,76 L 510,12 Z"
          fill="url(#bolt-grad-main)" stroke={INK} strokeWidth={3} strokeLinejoin="round"
          filter="url(#bolt-glow)" className="bolt bolt-main" />

        {/* 사이드 큰 번개 — 좌/우 */}
        <path d="M 300,16 L 268,80 L 294,80 L 278,144 L 332,72 L 302,72 L 332,16 Z"
          fill="url(#bolt-grad-side)" stroke={INK} strokeWidth={2.5} strokeLinejoin="round"
          className="bolt bolt-left" />
        <path d="M 620,16 L 594,76 L 614,76 L 600,138 L 650,68 L 622,68 L 650,16 Z"
          fill="url(#bolt-grad-side)" stroke={INK} strokeWidth={2.5} strokeLinejoin="round"
          className="bolt bolt-right" />

        {/* 더 멀리 작은 번개 */}
        <path d="M 140,24 L 124,66 L 138,66 L 128,104 L 156,58 L 142,58 L 156,24 Z"
          fill="#F5A623" stroke={INK} strokeWidth={2} strokeLinejoin="round"
          className="bolt bolt-far-l" />
        <path d="M 780,22 L 766,60 L 778,60 L 770,98 L 794,54 L 780,54 L 794,22 Z"
          fill="#F5A623" stroke={INK} strokeWidth={2} strokeLinejoin="round"
          className="bolt bolt-far-r" />

        {/* 스파크 도트 */}
        <circle cx={462} cy={198} r={5} fill="#FFE066" stroke={INK} strokeWidth={1.5}
          className="spark spark-main" />
        <circle cx={284} cy={152} r={3.5} fill="#FFB627" stroke={INK} strokeWidth={1.2}
          className="spark spark-left" />
        <circle cx={606} cy={148} r={3.5} fill="#FFB627" stroke={INK} strokeWidth={1.2}
          className="spark spark-right" />
        <circle cx={130} cy={112} r={2.5} fill="#F5A623"
          className="spark spark-far-l" />
        <circle cx={798} cy={108} r={2.5} fill="#F5A623"
          className="spark spark-far-r" />
      </svg>

      <style>{`
        @keyframes thunderFlashMain {
          0%, 8%, 100%   { opacity: 0; }
          1%             { opacity: 1; }
          3%             { opacity: 0.2; }
          4%, 6%         { opacity: 1; }
          7%             { opacity: 0.4; }
        }
        @keyframes thunderFlashSide {
          0%, 22%, 35%, 100% { opacity: 0; }
          20%, 22%           { opacity: 1; }
          24%                { opacity: 0.3; }
          25%, 27%           { opacity: 0.9; }
        }
        @keyframes thunderFlashFar {
          0%, 50%, 62%, 100% { opacity: 0; }
          48%, 50%           { opacity: 1; }
          52%                { opacity: 0.4; }
          54%, 56%           { opacity: 0.85; }
        }
        @keyframes auraPulse {
          0%, 100%       { opacity: 0.05; }
          1%, 4%, 6%     { opacity: 0.85; }
          20%, 22%, 26%  { opacity: 0.6; }
          48%, 50%, 54%  { opacity: 0.45; }
        }
        .thunder-aura { animation: auraPulse 5s ease-in-out infinite; }
        .bolt-main { animation: thunderFlashMain 5s ease-in-out infinite; }
        .bolt-left { animation: thunderFlashSide 5s ease-in-out infinite; }
        .bolt-right { animation: thunderFlashSide 5s ease-in-out infinite 0.18s; }
        .bolt-far-l { animation: thunderFlashFar 5s ease-in-out infinite; }
        .bolt-far-r { animation: thunderFlashFar 5s ease-in-out infinite 0.12s; }
        .spark-main { animation: thunderFlashMain 5s ease-in-out infinite 0.04s; }
        .spark-left { animation: thunderFlashSide 5s ease-in-out infinite 0.08s; }
        .spark-right { animation: thunderFlashSide 5s ease-in-out infinite 0.22s; }
        .spark-far-l { animation: thunderFlashFar 5s ease-in-out infinite 0.06s; }
        .spark-far-r { animation: thunderFlashFar 5s ease-in-out infinite 0.16s; }
      `}</style>
    </div>
  );
}

// ThunderBaton — 지휘봉 모양, 대각선 배치 + strike 모션
function ThunderBaton() {
  const wandTint = '#bda77c';   // 소프트 웜레 taupe
  const wandLine = `${INK}55`;   // 흐린 있크 아웃라인
  return (
    <div style={{
      position: 'absolute', top: 102, left: 50,
      zIndex: 3, pointerEvents: 'none',
      transformOrigin: '15px 20px',
      animation: 'batonStrike 6s ease-in-out infinite',
      opacity: 0.85,
    }}>
      <svg width={210} height={40} viewBox="0 0 210 40"
        style={{ display: 'block', overflow: 'visible' }}>
        {/* Handle — 흐린 둘근 쪽 */}
        <rect x={3} y={11} width={24} height={18} rx={9}
          fill={wandTint} fillOpacity={0.28}
          stroke={wandLine} strokeWidth={1.2} />
        <line x1={9} y1={14} x2={9} y2={26} stroke={wandLine} strokeWidth={0.8} />
        <line x1={15} y1={14} x2={15} y2={26} stroke={wandLine} strokeWidth={0.8} />
        <line x1={21} y1={14} x2={21} y2={26} stroke={wandLine} strokeWidth={0.8} />

        {/* Shaft — 귀엽고 둘근, 글씨 들어감 */}
        <rect x={26} y={7} width={166} height={26} rx={13}
          fill={wandTint} fillOpacity={0.15}
          stroke={wandLine} strokeWidth={1.3} />

        {/* Tip — 앞구의 공 */}
        <circle cx={196} cy={20} r={6}
          fill={wandTint} fillOpacity={0.32}
          stroke={wandLine} strokeWidth={1.4} />
        <circle cx={196} cy={20} r={2}
          fill={INK} opacity={0.55} />

        {/* Neurofeedback — 봉 안에 */}
        <text x={110} y={24} fontSize={12.5} fontWeight={600}
          fill="#1f1d1a" fontFamily='"Fredoka","Pretendard",sans-serif'
          textAnchor="middle" letterSpacing="0.5"
          opacity={0.7}>
          Neurofeedback
        </text>
      </svg>
      <style>{`
        @keyframes batonStrike {
          0%, 22%, 100% { transform: rotate(-22deg); }
          4%  { transform: rotate(-22deg); }
          6%  { transform: rotate(16deg);  }
          10% { transform: rotate(-30deg); }
          16% { transform: rotate(-22deg); }
        }
      `}</style>
    </div>
  );
}

// 뇌파 strike — 로고 코너에서 3 캐릭터를 향해 비스듬히 치는 EEG 신호
function NeuroFeedbackStrike() {
  const origin = { x: 132, y: 90 };
  const targets = [
    { x: 432,  y: 380, color: '#E8A317', delay: 0.45 },  // Attention
    { x: 720,  y: 380, color: '#6B9B5C', delay: 0.75 },  // Learning
    { x: 1008, y: 380, color: '#4A90C2', delay: 1.05 },  // Peak Performance
  ];

  // EEG 같은 wavy path 생성 — 길이 length, x축 방향
  const buildEegPath = (length) => {
    const seg = 14;
    const n = Math.floor(length / seg);
    let d = "M 0,0";
    for (let i = 1; i <= n; i++) {
      const x = i * seg;
      const isSpike = (i % 5 === 0);
      const sign = (i % 2 === 0) ? 1 : -1;
      const amp = isSpike ? 9 : 3.5;
      const ctrlX = x - seg / 2;
      const ctrlY = sign * amp;
      d += ` Q ${ctrlX},${ctrlY} ${x},0`;
    }
    return d;
  };

  const strikes = targets.map((t) => {
    const dx = t.x - origin.x;
    const dy = t.y - origin.y;
    const angle = Math.atan2(dy, dx) * 180 / Math.PI;
    const length = 230;  // 짧게 고정 — 캐릭터까지 안 닿고 짤막한 strike
    return { ...t, length, angle, path: buildEegPath(length) };
  });

  return (
    <div style={{
      position: 'absolute', top: 0, left: 0,
      width: '100%', height: 500, zIndex: 2,
      pointerEvents: 'none',
    }}>
      <svg viewBox="0 0 1440 500" width="100%" height={500}
        style={{ display: 'block', overflow: 'visible' }}
        preserveAspectRatio="xMinYMin meet">
        {/* 발생 origin 작은 펄스 */}
        <circle cx={origin.x} cy={origin.y} r={3}
          fill="#1f1d1a" opacity={0} className="nfs-origin" />
        {strikes.map((s, i) => (
          <g key={i} transform={`translate(${origin.x},${origin.y}) rotate(${s.angle})`}>
            <path d={s.path}
              stroke={s.color} strokeWidth={1.8} fill="none"
              strokeLinecap="round"
              strokeDasharray={s.length}
              strokeDashoffset={s.length}
              opacity={0}
              style={{
                animation: `nfStrike-${i} 6s ease-out infinite ${s.delay}s`,
              }} />
            {/* target tip */}
            <circle cx={s.length} cy={0} r={4}
              fill={s.color} stroke="#1f1d1a" strokeWidth={1.2}
              opacity={0}
              style={{
                animation: `nfTip-${i} 6s ease-out infinite ${s.delay}s`,
              }} />
          </g>
        ))}
      </svg>
      <style>{`
        ${strikes.map((s, i) => `
          @keyframes nfStrike-${i} {
            0%   { stroke-dashoffset: ${s.length}; opacity: 0; }
            3%   { opacity: 0.95; }
            18%  { stroke-dashoffset: 0; opacity: 0.95; }
            32%  { opacity: 0.55; }
            48%  { opacity: 0; }
            100% { stroke-dashoffset: ${s.length}; opacity: 0; }
          }
          @keyframes nfTip-${i} {
            0%, 18%, 100% { opacity: 0; transform: scale(1); }
            20%, 24%      { opacity: 1; transform: scale(1.6); }
            32%           { opacity: 0.6; transform: scale(1.1); }
            45%           { opacity: 0; }
          }
        `).join('\n')}
        @keyframes nfOrigin {
          0%, 100% { opacity: 0; transform: scale(1); }
          0%, 3%, 35%, 70%   { opacity: 0.5; transform: scale(1); }
          1%, 36%, 71%       { opacity: 1; transform: scale(1.6); }
        }
        .nfs-origin { animation: nfOrigin 6s ease-in-out infinite; transform-origin: center; transform-box: fill-box; }
      `}</style>
    </div>
  );
}

function PoseBoston({ p, lang }) {
  const [bookingOpen, setBookingOpen] = React.useState(false);
  const [bookingProgram, setBookingProgram] = React.useState(0);
  const openBooking = (i) => { setBookingProgram(i); setBookingOpen(true); };

  const insights = [
    { name: { ko: '사주', en: 'Saju' },        color: '#E8A317', x: 110 },
    { name: { ko: '관상', en: 'Face' },        color: '#6B9B5C', x: 320 },
    { name: { ko: '손금', en: 'Palm' },        color: '#F47C3C', x: 530 },
    { name: { ko: '타로', en: 'Tarot' },       color: '#4A90C2', x: 740 },
    { name: { ko: '성격', en: 'Character' }, color: '#9B7CC2', x: 950 },
  ];

  return (
    <>
      {/* (지휘봉 제거 — 로고에서 직접 천둥) */}

      {/* ─── 가운데 헤로 텍스트 — 카드 바로 위 ─── */}
      <div style={{
        position: 'absolute', top: 174, left: '50%',
        transform: 'translateX(-50%)', zIndex: 5,
        textAlign: 'center', fontFamily: FONT,
        display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8,
      }}>
        <div style={{
          fontSize: 11.5, fontWeight: 700, color: p.accent,
          letterSpacing: '0.24em', textTransform: 'uppercase',
          whiteSpace: 'nowrap',
        }}>
          {lang === 'en'
            ? 'Neurofeedback · Integrated Neuro Care'
            : '뉴로피드백 · 통합 신경 케어'}
        </div>
        <svg viewBox="0 0 220 8" width={220} height={8}
          style={{ display: 'block' }}>
          <path d="M 4,4 Q 14,1 24,4 T 44,4 T 64,4 T 84,4 T 104,4 T 124,4 T 144,4 T 164,4 T 184,4 T 204,4 L 216,4"
            stroke={p.accent} strokeWidth={1.1} fill="none"
            strokeLinecap="round" opacity={0.55} />
        </svg>
      </div>

      {/* ─── 뇌파 천둥 strike — 로고에서 3 캐릭터로 비스듬히 ─── */}
      <NeuroFeedbackStrike />

      {/* ─── 3 EPISODE 카드 ─── */}
      <div style={{
        position: 'absolute', bottom: 100, left: '50%',
        transform: 'translateX(-50%)',
        display: 'flex', gap: 22, zIndex: 4, alignItems: 'flex-end',
      }}>
        <EpisodeCard kind="inattention" onBook={() => openBooking(0)} lang={lang} />
        <EpisodeCard kind="learning"    onBook={() => openBooking(1)} lang={lang} />
        <EpisodeCard kind="peak"        onBook={() => openBooking(2)} lang={lang} />
      </div>

      {/* ─── 통찰 5 strip (Saju · Face · Palm · Tarot · Character) ─── */}
      <div style={{
        position: 'absolute', bottom: 18, left: '50%',
        transform: 'translateX(-50%)',
        width: 1060, zIndex: 3, fontFamily: FONT,
      }}>
        <div style={{
          display: 'flex', alignItems: 'center', gap: 10,
          marginBottom: 2, paddingLeft: 4,
          fontSize: 9, fontWeight: 800, color: '#6e5b3f',
          letterSpacing: '0.18em', textTransform: 'uppercase',
        }}>
          <span>{lang === 'en' ? 'Insight bonus' : '통찰 보너스 · Insight'}</span>
          <span style={{ flex: 1, height: 1, background: `${INK}1f` }} />
        </div>
        <svg viewBox="0 0 1060 60" width="100%" style={{ display: 'block', overflow: 'visible' }}>
          <path d="M0,46 Q60,40 120,46 T240,46 T360,46 T480,46 T600,46 T720,46 T840,46 T960,46 T1060,46"
            stroke="#7aaad0" strokeWidth={2} fill="none" strokeLinecap="round" opacity={0.45} />
          {insights.map((f) => (
            <InsightFish key={f.name.en} fish={f} lang={lang} />
          ))}
        </svg>
      </div>

      {/* 예약 모달 */}
      <BookingModal
        open={bookingOpen}
        onClose={() => setBookingOpen(false)}
        initialProgram={bookingProgram}
        p={p}
        lang={lang}
      />
    </>
  );
}

// 5개 메달 코너 요소 (B 하단 우측에 작게 — 재미용 사이드 옵션)
// 작은 물고기 SVG
function Fish({ color, size = 56 }) {
  return (
    <svg viewBox="0 0 80 50" width={size} height={size * 50/80} style={{ display: 'block' }}>
      {/* 몸 */}
      <path d="M10,25 Q14,8 38,8 Q60,8 66,25 Q60,42 38,42 Q14,42 10,25 Z"
        stroke={INK} strokeWidth={2.5} fill={color} strokeLinejoin="round" />
      {/* 꼬리 */}
      <path d="M66,25 L78,12 L74,25 L78,38 Z"
        stroke={INK} strokeWidth={2.5} fill={color} strokeLinejoin="round" />
      {/* 눈 */}
      <circle cx={48} cy={22} r={2.5} fill={INK} />
      {/* 비늘 패턴 (작은 호 1개) */}
      <path d="M26,25 Q34,22 42,25" stroke={INK} strokeWidth={1.2} fill="none" opacity={0.4} />
      {/* 입 (작은 점) */}
      <circle cx={16} cy={26} r={1.2} fill={INK} />
    </svg>
  );
}

function FiveMedalsCorner({ p }) {
  const fish = [
    { name: '도미',  sub: 'Sea bream', color: '#f5b48a' },
    { name: '광어',  sub: 'Flounder',  color: '#c8d9c0' },
    { name: '연어',  sub: 'Salmon',    color: '#f59c7c' },
    { name: '고등어', sub: 'Mackerel', color: '#7ba6c8' },
    { name: '참치',  sub: 'Tuna',      color: '#b88abb' },
  ];
  return (
    <div style={{
      position: 'absolute', right: 32, bottom: 30, zIndex: 6,
      background: '#ffffff', border: `2px solid ${INK}`, borderRadius: 18,
      padding: '12px 14px 14px',
      boxShadow: '0 10px 28px rgba(0,0,0,0.10)',
      fontFamily: FONT,
      transform: 'rotate(-2deg)',
    }}>
      <div style={{
        fontSize: 9, fontWeight: 800, color: p.accent,
        letterSpacing: '0.12em', textTransform: 'uppercase',
        marginBottom: 10,
        display: 'flex', alignItems: 'center', gap: 6,
      }}>
        <span>오늘의 물고기 · Today's Catch</span>
        <span style={{ flex: 1, height: 1, background: `${INK}22` }} />
      </div>
      <div style={{ display: 'flex', gap: 10, alignItems: 'flex-end' }}>
        {fish.map((f) => (
          <div key={f.name} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3 }}>
            <Fish color={f.color} size={50} />
            <div style={{ fontSize: 10, fontWeight: 700, color: INK, letterSpacing: '-0.005em' }}>{f.name}</div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ═════════════════════════════════════════════════════════════════════════════
// N · 트래킹 — 큰 standing 두 캐릭터 + floating 작은 차트 카드
function SceneNeuroExtras({ p, lang = 'en' }) {
  return (
    <>
      {/* 부드러운 atmospheric ring — 옅게, 대화 방해 안 됨 */}
      <svg viewBox="0 0 1440 900"
        style={{ position: 'absolute', inset: 0, display: 'block', width: '100%', height: '100%', pointerEvents: 'none' }}
        preserveAspectRatio="xMidYMid slice"
      >
        <g transform="translate(720, 530)" opacity={0.35}>
          <circle cx={0} cy={0} r={300} stroke={p.accent} strokeWidth={2.5} fill="none" strokeDasharray="3 12" opacity={0.4} />
          <circle cx={0} cy={0} r={210} stroke={p.accent} strokeWidth={2} fill="none" strokeDasharray="2 10" opacity={0.35} />
        </g>
      </svg>
      {/* 우측: 11 봇 시계 — Peak Performance 메타포 */}
      <BotsPeakClock p={p} />

      {/* 화살 애니메이션 — 로고 → 표적 (3단계 시퀀스) */}
      <style>{`
        @keyframes arrowStep {
          0%   { opacity: 0; transform: translate(0px, 0px) rotate(20deg); }
          10%  { opacity: 1; transform: translate(0px, 0px) rotate(20deg); }
          40%  { opacity: 1; transform: translate(120px, 42px) rotate(17deg); }
          70%  { opacity: 1; transform: translate(260px, 90px) rotate(13deg); }
          88%  { opacity: 1; transform: translate(260px, 90px) rotate(13deg); }
          95%  { opacity: 0; transform: translate(260px, 90px) rotate(13deg); }
          100% { opacity: 0; transform: translate(0px, 0px) rotate(20deg); }
        }
      `}</style>
      <div style={{
        position: 'absolute', left: 180, top: 120, zIndex: 5,
        width: 90, height: 18,
        animation: 'arrowStep 6s ease-in-out infinite',
        pointerEvents: 'none',
      }}>
        <svg viewBox="0 0 90 18" width="90" height="18" overflow="visible">
          {/* 화살대 */}
          <line x1={6} y1={9} x2={78} y2={9}
            stroke={INK} strokeWidth={2.5} strokeLinecap="round" />
          {/* 화살촉 */}
          <polygon points="86,9 76,3 78,9 76,15"
            fill={INK} stroke={INK} strokeWidth={1.5} strokeLinejoin="round" />
          {/* 깃털 */}
          <path d="M6,9 L-4,3 L0,9 L-4,15 Z"
            fill={p.accent} stroke={INK} strokeWidth={1.3} strokeLinejoin="round" />
          {/* 모션 라인 */}
          <line x1={-12} y1={5} x2={-4} y2={5}
            stroke={INK} strokeWidth={1.2} strokeLinecap="round" opacity={0.3} />
          <line x1={-14} y1={9} x2={-6} y2={9}
            stroke={INK} strokeWidth={1.2} strokeLinecap="round" opacity={0.22} />
          <line x1={-12} y1={13} x2={-4} y2={13}
            stroke={INK} strokeWidth={1.2} strokeLinecap="round" opacity={0.3} />
        </svg>
      </div>

    </>
  );
}

function PoseNeuro({ p, lang = 'en' }) {
  const charW = 250;
  return (
    <>
      {/* 작은 카우치 (중앙) */}
      <div style={{ position: 'absolute', bottom: 50, left: '50%',
        transform: 'translateX(-50%)',
        width: 580, zIndex: 1 }}>
        <svg viewBox="0 0 580 200" width="100%" style={{ display: 'block' }}>
          <ellipse cx={290} cy={194} rx={270} ry={6} fill="rgba(31,29,26,0.18)" />
          <path d="M30,190 L30,70 Q30,28 80,28 L500,28 Q550,28 550,70 L550,190 Z"
            stroke={INK} strokeWidth={5} fill={p.fabric} strokeLinejoin="round" />
          <line x1={290} y1={50} x2={290} y2={170}
            stroke={INK} strokeWidth={2.5} strokeDasharray="4 6" opacity={0.4} />
        </svg>
      </div>

      {/* 두 캐릭터 — 중앙 정렬, 위 표적 바라봄 */}
      <div style={{ position: 'absolute', bottom: 90, left: '50%',
        transform: 'translate(-110%, 0)', zIndex: 4 }}>
        <Person expression="performance" lean="center" width={charW}
          bodyColor={p.fabricDeep} initial="N" initialColor={p.accent}
          role="therapist" seated />
      </div>
      <div style={{ position: 'absolute', bottom: 90, left: '50%',
        transform: 'translate(10%, 0)', zIndex: 4 }}>
        <Person expression="learning" lean="center" width={charW}
          bodyColor={p.cream} seated />
      </div>

      {/* 상담가 말풍선 */}
      <div style={{
        position: 'absolute', top: 432, left: 140,
        zIndex: 6, width: 240, height: 96,
      }}>
        <svg viewBox="0 0 240 96" width="240" height="96"
          style={{ position: 'absolute', inset: 0, overflow: 'visible',
            filter: 'drop-shadow(0 4px 8px rgba(0,0,0,0.08))' }}>
          {/* 본체 + 오른쪽 하단 꼬리 (상담가 머리로) */}
          <path d="M 20,6 L 220,6 Q 234,6 234,20 L 234,68 Q 234,82 220,82 L 190,82 L 218,100 L 165,82 L 20,82 Q 6,82 6,68 L 6,20 Q 6,6 20,6 Z"
            fill="#ffffff" stroke={INK} strokeWidth={2.5}
            strokeLinejoin="round" />
        </svg>
        <div style={{
          position: 'relative', padding: '20px 22px 0',
          fontFamily: FONT, fontSize: 14, fontWeight: 600,
          color: INK, lineHeight: 1.45, textAlign: 'center',
        }}>{lang === 'ko' ? '지금 어떤 증상인지\n함께 알아볼까요?'.split('\n').map((t, i) => <React.Fragment key={i}>{i > 0 && <br/>}{t}</React.Fragment>) : (<>Let's find out what<br/>symptoms you have.</>)}</div>
      </div>

      {/* 고객 말풍선 */}
      <div style={{
        position: 'absolute', top: 432, right: 140,
        zIndex: 6, width: 240, height: 96,
      }}>
        <svg viewBox="0 0 240 96" width="240" height="96"
          style={{ position: 'absolute', inset: 0, overflow: 'visible',
            filter: 'drop-shadow(0 4px 8px rgba(0,0,0,0.08))' }}>
          {/* 본체 + 왼쪽 하단 꼬리 (고객 머리로) */}
          <path d="M 20,6 L 220,6 Q 234,6 234,20 L 234,68 Q 234,82 220,82 L 75,82 L 22,100 L 50,82 L 20,82 Q 6,82 6,68 L 6,20 Q 6,6 20,6 Z"
            fill="#ffffff" stroke={INK} strokeWidth={2.5}
            strokeLinejoin="round" />
        </svg>
        <div style={{
          position: 'relative', padding: '28px 22px 0',
          fontFamily: FONT, fontSize: 15, fontWeight: 700,
          color: INK, lineHeight: 1.45, textAlign: 'center',
        }}>{lang === 'ko' ? '네, 정말 궁금해요!' : 'Yes, I’m really curious!'}</div>
      </div>
    </>
  );
}

// 1인용 세라피 의자 (마주봄)
// 1인용 안락 의자 — 비대칭 등받이 (한쪽만 높은 등받이 → 의자 방향성 분명)
// facing='right' = 등받이 왼쪽, 오른쪽 열림 (캐릭터가 오른쪽 봄)
// facing='left' = 좌우 반전
function TherapyChair({ facing = 'right', color, width = 320 }) {
  const flip = facing === 'left';
  return (
    <svg viewBox="0 0 300 280" width={width} style={{ display: 'block',
      transform: flip ? 'scaleX(-1)' : 'none' }}
      preserveAspectRatio="xMidYMid meet">
      {/* 그림자 */}
      <ellipse cx={150} cy={268} rx={130} ry={7} fill="rgba(31,29,26,0.18)" />
      {/* 본체 — 왼쪽 등받이 크게, 오른쪽은 낮은 팔걸이로 열려있음 */}
      <path
        d="M30,260 L30,80 Q30,30 80,30 L160,30 Q200,30 200,100 Q220,160 270,170 Q286,176 286,200 L286,260 Z"
        stroke={INK} strokeWidth={5} fill={color} strokeLinejoin="round"
      />
      {/* 좌석 라인 — 안락한 쿠션 구분 */}
      <line x1={50} y1={190} x2={272} y2={190}
        stroke={INK} strokeWidth={3} opacity={0.45} strokeDasharray="4 6" />
      {/* 의자 다리 */}
      <line x1={50} y1={260} x2={50} y2={274} stroke={INK} strokeWidth={4} strokeLinecap="round" />
      <line x1={270} y1={260} x2={270} y2={274} stroke={INK} strokeWidth={4} strokeLinecap="round" />
    </svg>
  );
}

// ═════════════════════════════════════════════════════════════════════════════
// M · 큰 sitting 두 캐릭터 + thought bubble (옆에 크게)
// M · 9 치료기제 모달리티 그리드 (우측)
// ═════════════════════════════════════════════════════════════════
// M · 상담사를 위한 modality 매칭 — 증상 선택 → 근거 기반 추천 3개
const MODALITY_MATRIX = {
  depression: [
    { name: 'CBT',  desc: '인지행동치료',   color: '#5a8acc', match: 92, evidence: 3 },
    { name: 'BA',   desc: '행동활성화',     color: '#9bb88a', match: 86, evidence: 3 },
    { name: 'IPT',  desc: '대인관계치료',   color: '#bca6c8', match: 78, evidence: 3 },
  ],
  anxiety: [
    { name: 'CBT',       desc: '인지행동치료', color: '#5a8acc', match: 94, evidence: 3 },
    { name: 'Exposure',  desc: '노출치료',     color: '#f5a857', match: 88, evidence: 3 },
    { name: 'MBSR',      desc: '마음챙김',     color: '#9bcfc4', match: 75, evidence: 2 },
  ],
  sleep: [
    { name: 'CBT-I',     desc: '불면증 CBT',   color: '#5a8acc', match: 95, evidence: 3 },
    { name: 'Hygiene',   desc: '수면 위생',    color: '#a8c6db', match: 72, evidence: 2 },
    { name: 'MBSR',      desc: '마음챙김',     color: '#9bcfc4', match: 68, evidence: 2 },
  ],
  burnout: [
    { name: 'ACT',       desc: '수용전념치료', color: '#f5d878', match: 88, evidence: 2 },
    { name: 'MBSR',      desc: '마음챙김',     color: '#9bcfc4', match: 82, evidence: 2 },
    { name: 'BA',        desc: '행동활성화',   color: '#9bb88a', match: 70, evidence: 2 },
  ],
  ptsd: [
    { name: 'EMDR',      desc: '안구운동',     color: '#bca6c8', match: 91, evidence: 3 },
    { name: 'PE',        desc: '지속노출',     color: '#f5a857', match: 89, evidence: 3 },
    { name: 'CPT',       desc: '인지처리',     color: '#5a8acc', match: 85, evidence: 3 },
  ],
  ocd: [
    { name: 'ERP',       desc: '노출반응방지', color: '#f5a857', match: 96, evidence: 3 },
    { name: 'CBT',       desc: '인지행동치료', color: '#5a8acc', match: 82, evidence: 3 },
    { name: 'ACT',       desc: '수용전념치료', color: '#f5d878', match: 68, evidence: 2 },
  ],
  bipolar: [
    { name: 'IPSRT',     desc: '대인사회리듬', color: '#bca6c8', match: 84, evidence: 2 },
    { name: 'CBT',       desc: '인지행동치료', color: '#5a8acc', match: 80, evidence: 3 },
    { name: 'PsyEd',     desc: '심리교육',     color: '#a8c6db', match: 76, evidence: 3 },
  ],
  autism: [
    { name: 'CBT-Adapt', desc: '맞춤 CBT',     color: '#5a8acc', match: 84, evidence: 2 },
    { name: 'Social',    desc: '사회기술훈련', color: '#9bb88a', match: 82, evidence: 2 },
    { name: 'OT',        desc: '작업치료',     color: '#f3c39a', match: 72, evidence: 2 },
  ],
  adhd: [
    { name: 'Behavior',  desc: '행동치료',     color: '#9bb88a', match: 88, evidence: 3 },
    { name: 'CBT-A',     desc: '성인 CBT',     color: '#5a8acc', match: 82, evidence: 3 },
    { name: 'Coaching',  desc: '코칭',         color: '#f5d878', match: 70, evidence: 2 },
  ],
  learning: [
    { name: 'Skills',    desc: '기술훈련',     color: '#9bb88a', match: 86, evidence: 2 },
    { name: 'Tutoring',  desc: '학습지도',     color: '#a8c6db', match: 78, evidence: 2 },
    { name: 'Coaching',  desc: '코칭',         color: '#f5d878', match: 70, evidence: 2 },
  ],
  peak: [
    { name: 'MBSR',      desc: '마음챙김',     color: '#9bcfc4', match: 86, evidence: 2 },
    { name: 'ACT',       desc: '수용전념치료', color: '#f5d878', match: 80, evidence: 2 },
    { name: 'Sports',    desc: '스포츠 심리',  color: '#f5a857', match: 78, evidence: 2 },
  ],
};

function TherapistThoughts({ accent, lang = 'en' }) {
  // 오른쪽 패널 비움 — 새 아이디어 받기 전 깨끗한 캔버스
  return null;
}

function ModalityGlyph({ abbr, c }) {
  const s = { fill: 'none', stroke: c, strokeWidth: 6, strokeLinecap: 'round', strokeLinejoin: 'round' };
  const wrap = (kids) => (
    <svg width={84} height={84} viewBox="0 0 96 96" style={{ display: 'block', overflow: 'visible' }}>{kids}</svg>
  );
  if (abbr === 'CBT') return wrap(<>
    <rect x={16} y={18} width={64} height={44} rx={14} style={s} />
    <path d="M30,62 L26,74 L42,62" style={s} />
    <path d="M62,40 A14 14 0 1 0 60,52" style={s} />
    <path d="M54,46 L61,53 L67,47" style={s} />
  </>);
  if (abbr === 'MBSR') return wrap(<>
    <circle cx={48} cy={48} r={5} fill={c} />
    <circle cx={48} cy={48} r={17} style={s} />
    <circle cx={48} cy={48} r={30} style={s} />
  </>);
  if (abbr === 'ACT') return wrap(<>
    <path d="M16,38 L70,38" style={s} />
    <path d="M58,28 L72,38 L58,48" style={s} />
    <path d="M16,66 Q28,56 40,66 T64,66" style={s} />
  </>);
  if (abbr === 'EMDR') return wrap(<>
    <path d="M14,46 Q48,18 82,46 Q48,74 14,46 Z" style={s} />
    <circle cx={48} cy={46} r={9} style={s} />
    <circle cx={48} cy={46} r={2.5} fill={c} />
    <path d="M22,84 L74,84" style={s} />
    <path d="M30,78 L22,84 L30,90" style={s} />
    <path d="M66,78 L74,84 L66,90" style={s} />
  </>);
  if (abbr === 'DBT') return wrap(<>
    <path d="M16,40 L80,40" style={s} />
    <path d="M40,40 L48,58 L56,40" style={s} />
    <circle cx={16} cy={40} r={6} fill={c} />
    <circle cx={80} cy={40} r={6} fill={c} />
  </>);
  if (abbr === 'ERP') return wrap(<>
    <path d="M16,80 L16,66 L36,66 L36,52 L56,52 L56,38 L76,38" style={s} />
    <path d="M76,16 l3,7 7,1 -5,5 1,7 -6,-3 -6,3 1,-7 -5,-5 7,-1 z" style={{ ...s, strokeWidth: 4 }} />
  </>);
  if (abbr === 'IPT') return wrap(<>
    <circle cx={37} cy={48} r={22} style={s} />
    <circle cx={59} cy={48} r={22} style={s} />
  </>);
  return wrap(<>
    <circle cx={48} cy={48} r={13} style={s} />
    <path d="M48,16 L48,26 M48,70 L48,80 M16,48 L26,48 M70,48 L80,48 M26,26 L33,33 M70,70 L63,63 M70,26 L63,33 M26,70 L33,63" style={s} />
  </>);
}

function ModalitySpark({ x, y, sz, d, color }) {
  return (
    <div style={{ position: 'absolute', left: x, top: y, width: sz, height: sz, marginLeft: -sz / 2, marginTop: -sz / 2,
      animation: `mSpark 2.6s ${d}s ease-in-out infinite`, pointerEvents: 'none',
      filter: `drop-shadow(0 0 4px ${color})` }}>
      <svg width={sz} height={sz} viewBox="0 0 24 24" style={{ display: 'block' }}>
        <path d="M12,0 Q13.5,9 24,12 Q13.5,15 12,24 Q10.5,15 0,12 Q10.5,9 12,0 Z" fill={color} />
      </svg>
    </div>
  );
}

function PoseModality({ p, accent, lang = 'en' }) {
  const MODALITIES = [
    { abbr: 'CBT',  ko: '인지행동치료',         en: 'Cognitive Behavioral',          what: '생각의 습관을 알아차리고, 다시 씁니다.', whatEn: 'Notice thought habits, and rewrite them.',     color: '#4f8fd6', best: '불안 · 우울',      bestEn: 'Anxiety · Depression' },
    { abbr: 'MBSR', ko: '마음챙김 스트레스 완화', en: 'Mindfulness-Based Reduction',    what: '판단 없이, 지금 이 순간에 머무릅니다.',  whatEn: 'Rest in the present, without judgment.',       color: '#56c4b2', best: '번아웃 · 스트레스', bestEn: 'Burnout · Stress' },
    { abbr: 'ACT',  ko: '수용전념치료',         en: 'Acceptance & Commitment',       what: '받아들이고, 가치를 향해 나아갑니다.',   whatEn: 'Accept what is, move toward what matters.',    color: '#d99a2b', best: '번아웃 · 불안',    bestEn: 'Burnout · Anxiety' },
    { abbr: 'EMDR', ko: '안구운동 민감소실',     en: 'Eye Movement Reprocessing',     what: '기억의 무게를 천천히 덜어냅니다.',     whatEn: 'Gently lift the weight of memory.',            color: '#9b78c4', best: 'PTSD · 트라우마',   bestEn: 'PTSD · Trauma' },
    { abbr: 'DBT',  ko: '변증법적 행동치료',     en: 'Dialectical Behavior',          what: '격한 감정의 파도를 균형 있게 다룹니다.', whatEn: 'Ride intense emotional waves, in balance.',    color: '#86cd6d', best: '감정조절 · 충동',  bestEn: 'Emotion · Impulse' },
    { abbr: 'ERP',  ko: '노출 및 반응방지',      en: 'Exposure & Response Prevention', what: '두려움과 한 걸음씩 마주섭니다.',      whatEn: 'Face the fear, one step at a time.',           color: '#df8246', best: '강박 · 공포',      bestEn: 'OCD · Phobia' },
    { abbr: 'IPT',  ko: '대인관계치료',         en: 'Interpersonal Therapy',         what: '관계의 매듭을 다시 잇습니다.',        whatEn: 'Mend the knots in your relationships.',        color: '#cf6f93', best: '우울 · 관계',      bestEn: 'Depression · Relationships' },
    { abbr: 'BA',   ko: '행동활성화',           en: 'Behavioral Activation',         what: '작은 행동으로 다시 움직입니다.',       whatEn: 'Get moving again, one small act.',             color: '#93cf78', best: '우울 · 무기력',    bestEn: 'Depression · Low energy' },
  ];
  const [idx, setIdx] = React.useState(0);
  const [paused, setPaused] = React.useState(false);
  React.useEffect(() => {
    if (paused) return;
    const id = setInterval(() => setIdx((i) => (i + 1) % MODALITIES.length), 3800);
    return () => clearInterval(id);
  }, [paused]);
  const m = MODALITIES[idx];
  const isKo = lang !== 'en';

  const sparks = [
    { x: 96, y: 150, s: 13, d: 0 },
    { x: 300, y: 176, s: 10, d: 0.5 },
    { x: 70, y: 320, s: 16, d: 0.9 },
    { x: 322, y: 350, s: 12, d: 0.3 },
    { x: 108, y: 470, s: 10, d: 1.1 },
    { x: 296, y: 470, s: 14, d: 0.7 },
    { x: 190, y: 96, s: 11, d: 1.3 },
  ];
  return (
    <>
      {/* 공유 바닥 그림자 — 캐릭터+거울을 한 바닥에 */}
      <div style={{ position: 'absolute', left: 150, bottom: 64, width: 660, height: 50, zIndex: 1,
        pointerEvents: 'none', borderRadius: '50%',
        background: 'radial-gradient(ellipse at center, rgba(31,29,26,0.15), rgba(31,29,26,0) 70%)' }} />

      {/* 왼쪽 — 해리포터풍 마법사 (거울 곁에서 주문을 거는) */}
      <div style={{ position: 'absolute', left: 110, bottom: 96, zIndex: 6 }}>
        <div style={{ position: 'relative', width: 228 }}>
          <PersonStanding expression="learning" lean="right" width={228}
            bodyColor="#34524a" armRaise="right" />

          {/* 얼굴 좌표(0 0 240 380)에 맞춘 오버레이 */}
          <svg viewBox="0 0 240 380" width={228} height={228 * 380 / 240}
            style={{ position: 'absolute', left: 0, top: 0, overflow: 'visible', pointerEvents: 'none' }}>
            {/* 마법 학원 목도리 — 골드+틸 */}
            <path d="M96,114 Q120,128 146,114 L151,129 Q120,143 91,129 Z"
              fill="#b9924f" stroke={INK} strokeWidth={2.6} strokeLinejoin="round" />
            <path d="M99,121 Q120,132 143,121" fill="none" stroke="#34524a" strokeWidth={2.4} />
            <path d="M126,130 L140,176 L126,182 L114,174 L118,130 Z"
              fill="#b9924f" stroke={INK} strokeWidth={2.4} strokeLinejoin="round" />
            <path d="M118,150 L135,156 M117,164 L132,170" stroke="#34524a" strokeWidth={2.4} />

            {/* 마법사 모자 */}
            <path d="M 78,24 Q 70,-18 104,-58 Q 150,-6 162,24 Q 120,34 78,24 Z"
              fill="#3a5a48" stroke={INK} strokeWidth={3} strokeLinejoin="round" />
            <path d="M 84,20 Q 120,30 156,16 L 153,6 Q 120,20 87,9 Z"
              fill="#c19a64" stroke={INK} strokeWidth={2.4} strokeLinejoin="round" />
            <rect x={112} y={11} width={14} height={12} rx={2} fill="#d9b24a" stroke={INK} strokeWidth={2} />
            <ellipse cx={120} cy={28} rx={56} ry={13} fill="#2c463a" stroke={INK} strokeWidth={3} />
            <ellipse cx={120} cy={25} rx={56} ry={11} fill="#3a5a48" stroke={INK} strokeWidth={2.4} />
            <path d="M112,-28 l2.6,6 6.4,0.6 -4.8,4.4 1.3,6.4 -5.5,-3.2 -5.5,3.2 1.3,-6.4 -4.8,-4.4 6.4,-0.6 z"
              fill="#e7c766" stroke={INK} strokeWidth={1} strokeLinejoin="round" />
            <path d="M92,2 a6.5,6.5 0 1 1 -3,-8.4 a5,5 0 1 0 3,8.4 z" fill="#e7c766" stroke={INK} strokeWidth={1} />
            <circle cx={132} cy={-8} r={2.4} fill="#e7c766" />

            {/* 번개 흉터 */}
            <path d="M138,42 l3,5 -3.5,2 4,6" fill="none" stroke="#7a2418" strokeWidth={2.2} strokeLinecap="round" strokeLinejoin="round" />

            {/* 동그란 안경 */}
            <circle cx={104} cy={64} r={12} fill="#ffffff" fillOpacity={0.16} stroke={INK} strokeWidth={3} />
            <circle cx={136} cy={64} r={12} fill="#ffffff" fillOpacity={0.16} stroke={INK} strokeWidth={3} />
            <path d="M116,64 Q120,60 124,64" fill="none" stroke={INK} strokeWidth={3} strokeLinecap="round" />
            <path d="M92,62 L86,60 M148,62 L154,60" stroke={INK} strokeWidth={3} strokeLinecap="round" />

            {/* 마법 지팡이 */}
            <line x1={176} y1={50} x2={224} y2={6} stroke="#7a684a" strokeWidth={6} strokeLinecap="round" />
            <line x1={176} y1={50} x2={222} y2={8} stroke="#a89465" strokeWidth={2.4} strokeLinecap="round" />
            <path d="M226,-10 l1.8,9 9,1.8 -9,1.8 -1.8,9 -1.8,-9 -9,-1.8 9,-1.8 z" fill="#e7c766" stroke={INK} strokeWidth={1}>
              <animateTransform attributeName="transform" type="rotate" from="0 226 4" to="360 226 4" dur="7s" repeatCount="indefinite" />
            </path>
            {/* 캐스팅 반짝임 — 지팡이 끝에서 거울로 */}
            <circle cx={244} cy={-4} r={2.4} fill="#f1d27a" style={{ animation: 'mSpark 2.4s 0.2s ease-in-out infinite' }} />
            <circle cx={238} cy={14} r={1.8} fill="#f1d27a" style={{ animation: 'mSpark 2.4s 1.1s ease-in-out infinite' }} />
          </svg>
        </div>
      </div>

      {/* 소망의 거울 — 슬림 선버스트 + 마법 돌기 */}
      <div
        onMouseEnter={() => setPaused(true)}
        onMouseLeave={() => setPaused(false)}
        style={{ position: 'absolute', left: 432, top: 116, width: 408, height: 620, zIndex: 5,
          filter: 'drop-shadow(0 10px 0 rgba(31,29,26,0.09))' }}>

        <svg width={408} height={620} viewBox="0 0 408 620"
          style={{ display: 'block', overflow: 'visible' }}>
          <defs>
            <clipPath id="mGlassClip">
              <circle cx={204} cy={296} r={156} />
            </clipPath>
            <path id="mInscArc" d="M 86,213 A 144 144 0 0 1 322,213" fill="none" />
          </defs>

          {/* 가는 햇살 — 가시가 직접 들락날락(물결) */}
          {Array.from({ length: 24 }).map((_, i) => {
            const a = (i * 15) * Math.PI / 180;
            const long = i % 2 === 0;
            const r0 = 162;
            const rMin = long ? 214 : 188;
            const rMax = long ? 252 : 210;
            const hw = (long ? 1.7 : 1.1) * Math.PI / 180;
            const ca = Math.cos(a), sa = Math.sin(a);
            const xa = (204 + Math.cos(a - hw) * r0).toFixed(1), ya = (296 + Math.sin(a - hw) * r0).toFixed(1);
            const xb = (204 + Math.cos(a + hw) * r0).toFixed(1), yb = (296 + Math.sin(a + hw) * r0).toFixed(1);
            const tip = (r) => `${(204 + ca * r).toFixed(1)},${(296 + sa * r).toFixed(1)}`;
            const dMin = `M${xa},${ya} L${tip(rMin)} L${xb},${yb} Z`;
            const dMax = `M${xa},${ya} L${tip(rMax)} L${xb},${yb} Z`;
            return <path key={'ray' + i}
              fill={long ? '#b89a5c' : '#a89465'} stroke={INK} strokeWidth={1.4} strokeLinejoin="round" d={dMin}>
              <animate attributeName="d" dur="4s" begin={long ? '0s' : '-2s'} repeatCount="indefinite"
                calcMode="spline" keyTimes="0;0.5;1" keySplines="0.45 0 0.55 1;0.45 0 0.55 1"
                values={`${dMin};${dMax};${dMin}`} />
            </path>;
          })}

          {/* 슬림 골드 링 + 비드 */}
          <circle cx={204} cy={296} r={166} fill="#a89465" stroke={INK} strokeWidth={2.6} />
          <circle cx={204} cy={296} r={156} fill="#34524a" stroke={INK} strokeWidth={2.4} />
          {Array.from({ length: 40 }).map((_, i) => {
            const a = (i * 9) * Math.PI / 180;
            return <circle key={'bd' + i} cx={(204 + Math.cos(a) * 161).toFixed(1)} cy={(296 + Math.sin(a) * 161).toFixed(1)} r={1.3} fill="#7a684a" />;
          })}

          {/* 마법 돌기 — 들어갔다 나왔다 맥동 */}
          {Array.from({ length: 8 }).map((_, i) => {
            const a = (i * 45) * Math.PI / 180;
            const bx = (204 + Math.cos(a) * 166).toFixed(1), by = (296 + Math.sin(a) * 166).toFixed(1);
            const dx = (Math.cos(a) * 8).toFixed(1), dy = (Math.sin(a) * 8).toFixed(1);
            return <g key={'bo' + i}>
              <animateTransform attributeName="transform" type="translate"
                values={`0 0; ${dx} ${dy}; 0 0`} keyTimes="0;0.5;1"
                dur="2.8s" begin={`${(i * 0.34).toFixed(2)}s`} repeatCount="indefinite"
                calcMode="spline" keySplines="0.45 0 0.55 1; 0.45 0 0.55 1" />
              <circle cx={bx} cy={by} r={6.5} fill="#c7b58e" stroke={INK} strokeWidth={2} />
              <circle cx={bx} cy={by} r={2.6} fill={m.color} />
            </g>;
          })}

          {/* 안쪽 게일라인 */}
          <circle cx={204} cy={296} r={148} fill="none" stroke="#c9d8d2" strokeWidth={1.1} opacity={0.32} />

          {/* 유리 광택 + 스윕 */}
          <g clipPath="url(#mGlassClip)">
            <path d="M118,170 L162,170 L96,346 L74,346 Z" fill="#f6faf2" opacity={0.08} />
            <path d="M172,166 L188,166 L120,372 L106,372 Z" fill="#f6faf2" opacity={0.05} />
            <rect className="mirror-sweep" x={-150} y={130} width={104} height={340}
              fill="#f6faf2" opacity={0.15} transform="skewX(-16)" />
          </g>

          {/* 아치 각인 */}
          <text fill="#d8b66e" fontFamily="Georgia, 'Times New Roman', serif" fontStyle="italic"
            fontSize="12" fontWeight="600" letterSpacing="0.3" opacity="0.92">
            <textPath href="#mInscArc" startOffset="50%" textAnchor="middle">{isKo ? '거울아, 거울아 — 나에게 맞는 길은?' : 'Mirror, mirror — which path is mine?'}</textPath>
          </text>
        </svg>

        {/* 거울 속 — 치료기법 reveal (한/영) — 단순화 */}
        <div style={{ position: 'absolute', left: 72, top: 186, width: 264, height: 220,
          display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
          textAlign: 'center', padding: '0 20px', pointerEvents: 'none', fontFamily: FONT }}>
          <div key={'rv-' + idx} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center',
            opacity: 1, animation: 'mReveal 0.6s cubic-bezier(0.4,0,0.2,1)' }}>
            <div style={{ width: 70, height: 70, borderRadius: 999,
              background: `${m.color}24`, border: `2px solid ${m.color}`,
              boxShadow: `0 0 18px ${m.color}30`,
              display: 'flex', alignItems: 'center', justifyContent: 'center', marginBottom: 13 }}>
              <ModalityGlyph abbr={m.abbr} c={m.color} />
            </div>
            <div style={{ fontSize: 46, fontWeight: 800, color: m.color, lineHeight: 1,
              letterSpacing: '-0.02em', textShadow: `0 2px 20px ${m.color}55` }}>{m.abbr}</div>
            <div style={{ fontSize: isKo ? 15 : 13, fontWeight: 700, color: '#f2e7cf', marginTop: 10,
              whiteSpace: isKo ? 'nowrap' : 'normal', maxWidth: 186, lineHeight: 1.3,
              textShadow: '0 1px 10px rgba(18,28,26,0.45)' }}>{isKo ? m.ko : m.en}</div>
            <div style={{ fontSize: 12.5, fontWeight: 500, color: 'rgba(242,231,207,0.8)', lineHeight: 1.55,
              marginTop: 9, maxWidth: 184, textWrap: 'balance' }}>{isKo ? m.what : m.whatEn}</div>
          </div>
        </div>

        {/* 진행 룬 */}
        <div style={{ position: 'absolute', left: 0, right: 0, top: 438,
          display: 'flex', justifyContent: 'center', gap: 9, zIndex: 7 }}>
          {MODALITIES.map((mm, i) => {
            const on = i === idx;
            return (
              <button key={mm.abbr}
                onClick={() => setIdx(i)}
                title={mm.abbr}
                style={{ width: on ? 24 : 8, height: 8, borderRadius: 999,
                  border: 0, cursor: 'pointer', padding: 0,
                  background: on ? mm.color : 'rgba(246,250,242,0.32)',
                  transition: 'all 0.3s ease' }} />
            );
          })}
        </div>
      </div>

      <style>{`
        @keyframes mReveal {
          0%   { clip-path: inset(0 100% 0 0); transform: translateX(-12px); }
          100% { clip-path: inset(0 0 0 0); transform: translateX(0); }
        }
        @keyframes mSpark {
          0%, 100% { opacity: 0; transform: scale(0.4) rotate(0deg); }
          50%      { opacity: 0.9; transform: scale(1) rotate(45deg); }
        }
        .mirror-sweep { animation: mSweep 1.0s cubic-bezier(0.4,0,0.2,1) 1; }
        @keyframes mSweep {
          0%   { transform: translateX(0) skewX(-16deg); opacity: 0; }
          25%  { opacity: 1; }
          100% { transform: translateX(600px) skewX(-16deg); opacity: 0; }
        }
        @keyframes mFlow { to { stroke-dashoffset: -10.5; } }
      `}</style>
    </>
  );
}

// ═════════════════════════════════════════════════════════════════════════════
// Site Hero
function SiteHero({ siteKey, config, pose, extras, hideCorner, onCta, authButtons, overlay, ctaColor, ctaSoft, onNavAction, lang: langProp, setLang: setLangProp }) {
  const [langState, setLangState] = React.useState(typeof window !== 'undefined' && window.bnmGetLang ? window.bnmGetLang() : 'en');
  const lang = langProp != null ? langProp : langState;
  const setLang = setLangProp || setLangState;
  const site = SITE_COLORS[siteKey];
  const p = { ...SITE_PALETTES[siteKey], id: siteKey };
  const c = config[lang] || config;
  return (
    <div style={{ width: '100%', height: '100%', position: 'relative', overflow: 'hidden', background: p.wallTop }}>
      <WarmRoom site={siteKey} />
      <TalkLegalFooter lang={lang} />
      {extras && extras(p, lang)}
      <Nav siteName={site.name} items={c.nav} ctaLabel={c.navCta} accent={site.value}
        lang={lang} setLang={setLang} currentSite={siteKey}
        onCta={onCta} authButtons={authButtons} ctaColor={ctaColor} ctaSoft={ctaSoft} onNavAction={onNavAction} />
      {overlay}
      {!hideCorner && (
        <CornerCopy
          eyebrow={c.eyebrow}
          headline={c.headline}
          sub={c.sub}
          primaryCta={c.primaryCta}
          secondaryCta={c.secondaryCta}
          accent={site.value}
          position={c.copyPosition || 'left'}
          copyScale={siteKey === 'modality' ? 0.85 : 1}
          copyOffset={siteKey === 'modality' ? 72 : 0}
        />
      )}
      {pose({ p, accent: site.value, lang })}
    </div>
  );
}

const CONFIGS = {
  talk: {
    ko: {
      nav: ['서비스', '세라피스트', '봇', '리뷰'],
      navCta: '예약',
      copyPosition: 'left',
      eyebrow: 'T · 11개의 마음 동반자',
      headline: (<><span style={{ color: SITE_COLORS.talk.value }}>11</span>명의<br />마음 친구.</>),
      sub: '주제마다 한 명씩 — 불안, 수면, 번아웃, 학습까지. 11명의 봇이 당신과 한 팀입니다.',
      primaryCta: '대화 시작',
      secondaryCta: '봇 만나보기',
    },
    en: {
      nav: ['Service', 'Therapists', 'Bots', 'Reviews'],
      navCta: 'Intake',
      copyPosition: 'left',
      eyebrow: 'T · 11 mind companions',
      headline: (<><span style={{ color: SITE_COLORS.talk.value }}>11</span> bots,<br />one team.</>),
      sub: 'One bot per topic — anxiety, sleep, burnout, learning. 11 companions, always on your side.',
      primaryCta: 'Start a chat',
      secondaryCta: 'Meet the bots',
    },
  },
  boston: {
    ko: {
      nav: ['리서치', '프로그램', '임상의', '소개'],
      navCta: '예약',
      copyPosition: 'left',
      eyebrow: 'B · 전페포괄 임상',
      headline: (<>전체를 함께<br />가는 <span style={{ color: SITE_COLORS.boston.value }}>레시피</span>.</>),
      sub: '단편이 아닌 통합. ADHD · Autism · Sleep · Bipolar — 모든 재료를 한 그릇에 담는 14년 임상 노하우로.',
      primaryCta: '예약',
      secondaryCta: '연구 결과 →',
    },
    en: {
      nav: ['Research', 'Programs', 'Clinicians', 'About'],
      navCta: 'Intake',
      copyPosition: 'left',
      eyebrow: 'B · Whole-person clinical',
      headline: (<>The full <span style={{ color: SITE_COLORS.boston.value }}>recipe</span><br />for the mind.</>),
      sub: 'Not pieces — the whole. ADHD · Autism · Sleep · Bipolar, 14 years of clinical know-how in one place.',
      primaryCta: 'Intake',
      secondaryCta: 'See research →',
    },
  },
  neuro: {
    ko: {
      nav: ['작동 원리', '세라피스트용', '사용자용', '가격'],
      navCta: '예약',
      copyPosition: 'left',
      eyebrow: 'N · 증상포착 · 패턴 훈련',
      headline: (<>패턴을<br /><span style={{ color: SITE_COLORS.neuro.value }}>먼저 봅니다</span>.</>),
      sub: '매일의 신호를 측정하고, 점들을 연결하고, 함께 훈련합니다. 변화의 작은 흐름도 catch하게.',
      primaryCta: '훈련 시작',
      secondaryCta: '데이터 보기',
    },
    en: {
      nav: ['How it works', 'For therapists', 'For you', 'Pricing'],
      navCta: 'Intake',
      copyPosition: 'left',
      eyebrow: 'N · Symptom & pattern training',
      headline: (<>See the <span style={{ color: SITE_COLORS.neuro.value }}>pattern</span><br />before it grows.</>),
      sub: 'Measure daily signals, connect the dots, train together. Catch every small shift early.',
      primaryCta: 'Start training',
      secondaryCta: 'View data',
    },
  },
  modality: {
    ko: {
      nav: ['방법', '코치', '사례', '시작'],
      navCta: '예약',
      copyPosition: 'right',
      eyebrow: 'M · 치료기제 매칭',
      headline: (<><span style={{ color: SITE_COLORS.modality.value }}>당신</span>에게<br />맞는 방법.</>),
      sub: 'CBT · MBSR · ACT · EMDR — 데이터와 임상 경험으로 매칭. 추측이 아닌 근거로 시작합니다.',
      primaryCta: '맞춤 치료 찾기',
      secondaryCta: '사례 보기',
    },
    en: {
      nav: ['Method', 'Coaches', 'Stories', 'Start'],
      navCta: 'Intake',
      copyPosition: 'right',
      eyebrow: 'M · Modality matching',
      headline: (<>The right path<br />for <span style={{ color: SITE_COLORS.modality.value }}>you</span>.</>),
      sub: 'CBT · MBSR · ACT · EMDR — matched by data and clinical experience. Evidence, not guesswork.',
      primaryCta: 'Find your match',
      secondaryCta: 'See stories',
    },
  },
};

function TalkBotRentalCard({ accent, lang = 'en' }) {
  // 3개 슬롯, 각 슬롯에 봇 idx + percent
  const [slots, setSlots] = React.useState([
    { idx: 8, pct: 100 }, // ADHD 100%
    { idx: null, pct: 0 },
    { idx: null, pct: 0 },
  ]);
  const [openSlot, setOpenSlot] = React.useState(null);
  const BOTS = window.BOTS || [];
  const PERCENT_OPTIONS = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
  // 카드 3장: 용량 캡 + 엔진 등급 묶음. cap=게이지 상한, tier=결제 등급(card.* 시드 연결).
  const PLAN_OPTIONS = [
    { tier: 'light',    cap: 100, price: '$9',  ko: '라이트',   en: 'Light',    dko: '일상 대화',      den: 'Everyday chat' },
    { tier: 'standard', cap: 150, price: '$15', ko: '스탠다드', en: 'Standard', dko: '전문 상담 수준', den: 'Pro counseling', hot: true },
    { tier: 'pro',      cap: 200, price: '$25', ko: '프로',     en: 'Pro',      dko: '심층 전문 분석', den: 'Deep analysis' },
  ];
  const [planCap, setPlanCap] = React.useState(150);
  const [planTier, setPlanTier] = React.useState('standard');
  const MAX_TOTAL = planCap; // 선택 플랜 캡 — 게이지·슬롯상한·enable 기준
  const totalPct = slots.reduce((a, s) => a + (s.pct || 0), 0);
  const ready = totalPct >= MAX_TOTAL; // 선택 플랜 캡 도달 시 채팅 시작 가능
  const usedIdxs = slots.map(s => s.idx).filter(x => x !== null);
  const primary = slots.find(s => s.idx !== null && s.pct > 0);
  const primaryBot = primary ? BOTS[primary.idx] : null;

  // 플랜 전환: 캡 낮추면 초과분을 슬롯 순서대로 깎아 캡에 맞춤(과배분 방지).
  const selectPlan = (cap) => {
    setPlanCap(cap);
    setSlots(prev => {
      let remaining = cap;
      return prev.map(s => {
        const p = Math.min(s.pct || 0, remaining);
        remaining -= p;
        return { ...s, pct: p };
      });
    });
  };

  const setSlotPct = (slotIdx, pct) => {
    setSlots(prev => {
      const cur = prev[slotIdx].pct;
      const next = cur === pct ? 0 : pct;
      const otherPct = totalPct - cur;
      if (otherPct + next > MAX_TOTAL) return prev;
      return prev.map((s, i) => i === slotIdx ? { ...s, pct: next } : s);
    });
  };
  const setSlotBot = (slotIdx, botIdx) => {
    setSlots(prev => prev.map((s, i) => i === slotIdx ? { ...s, idx: botIdx } : s));
    setOpenSlot(null);
  };

  const greetingByKey = {
    depression: { en: 'Hey, I\'m here whenever heaviness lingers.', ko: '무거운 마음이 머물 때 언제든 곁에 있을게요.' },
    anxiety:    { en: 'Take a slow breath — I\'ll breathe with you.', ko: '천천히 숨 한 번 — 같이 호흡할게요.' },
    sleep:      { en: 'Rough night? Tell me how you slept.', ko: '잠 못 이루셨나요? 어젯밤 어떠셨어요?' },
    burnout:    { en: 'Your tired is real. Let\'s slow down together.', ko: '당신의 피로는 진짜예요. 천천히 가요.' },
    ptsd:       { en: 'You are safe here. Pace is yours.', ko: '여기는 안전해요. 속도는 당신이 정해요.' },
    ocd:        { en: 'A thought is just a thought. Want to look at one?', ko: '생각은 그저 생각이에요. 같이 들여다볼까요?' },
    bipolar:    { en: 'How is your mood today, in your words?', ko: '오늘 기분은 당신의 말로 어떤가요?' },
    autism:     { en: 'No mask needed. Let\'s talk your way.', ko: '가면 벗어도 돼요. 당신의 방식으로 이야기해요.' },
    adhd:       { en: 'One small step at a time. What\'s on your mind?', ko: '한 번에 한 걸음씩. 어떤 생각이 떠올랐어요?' },
    learning:   { en: 'Curious about something? Let\'s explore.', ko: '궁금한 거 있어요? 함께 파헤쳐봐요.' },
    peak:       { en: 'Ready for your top form? Tell me your goal.', ko: '최고의 컨디션 가즈아. 목표가 뭐예요?' },
  };
  const greet = primaryBot && (greetingByKey[primaryBot.key] || {})[lang] ||
    (lang === 'en' ? 'Hello! How are you today?' : '안녕! 오늘 어때요?');

  // 3 프리셋 팩 — B.html의 3 프로그램 탭과 비슷한 위치/스타일
  const findIdx = (key) => BOTS.findIndex(b => b.key === key);
  const PRESETS = [
    {
      key: 'anxiety-pack',
      ko: '불안 패키지', en: 'Anxiety Pack',
      color: '#9bb88a',
      slots: [
        { idx: findIdx('anxiety'), pct: 100 },
        { idx: findIdx('sleep'),   pct: 50 },
        { idx: findIdx('burnout'), pct: 30 },
      ],
    },
    {
      key: 'focus-pack',
      ko: '집중 패키지', en: 'Focus Pack',
      color: '#f5a857',
      slots: [
        { idx: findIdx('adhd'),     pct: 100 },
        { idx: findIdx('learning'), pct: 50 },
        { idx: findIdx('peak'),     pct: 50 },
      ],
    },
    {
      key: 'mood-pack',
      ko: '기분 패키지', en: 'Mood Pack',
      color: '#bca6c8',
      slots: [
        { idx: findIdx('depression'), pct: 100 },
        { idx: findIdx('bipolar'),    pct: 50 },
        { idx: findIdx('ptsd'),       pct: 50 },
      ],
    },
  ];
  const applyPreset = (preset) => {
    setSlots(preset.slots);
    setOpenSlot(null);
  };

  return (
    <div style={{
      position: 'absolute', left: 56, top: 130,
      width: 380, zIndex: 5,
      fontFamily: FONT,
    }}>
      {/* 헤더 */}
      <div style={{
        fontSize: 12, fontWeight: 800, color: accent,
        letterSpacing: '0.18em', textTransform: 'uppercase',
        marginBottom: 10, display: 'flex', alignItems: 'center', gap: 10,
      }}>
        <span style={{ width: 24, height: 2, background: accent, borderRadius: 2 }} />
        {lang === 'en' ? 'Bot Rental' : '봇 렌탈'}
      </div>

      <h1 style={{
        fontSize: 30, lineHeight: 1.15, fontWeight: 800,
        color: INK, marginTop: 0, marginBottom: 8,
        letterSpacing: '-0.025em',
      }}>{lang === 'en' ? (<>3 bots · up to <span style={{ color: accent }}>200%</span></>)
        : (<>봇 3개 · 최대 <span style={{ color: accent }}>200%</span></>)}</h1>
      <p style={{
        fontSize: 12, lineHeight: 1.45, color: '#5a4a35',
        marginTop: 0, marginBottom: 12, fontWeight: 500,
      }}>{lang === 'en'
        ? 'Each 10–100%. Monthly · 24/7 · web & mobile.'
        : '각 10–100% 강도. 월 단위 · 24/7 · 웹 & 모바일.'}</p>

      {/* 3 프리셋 팩 버튼 — B.html 프로그램 탭과 비슷한 위치 */}
      <div style={{ display: 'flex', gap: 6, marginBottom: 12 }}>
        {PRESETS.map(preset => (
          <button key={preset.key}
            onClick={() => applyPreset(preset)}
            onMouseEnter={(e) => {
              e.currentTarget.style.background = preset.color;
              e.currentTarget.style.color = '#ffffff';
              e.currentTarget.style.borderColor = preset.color;
              e.currentTarget.style.transform = 'translateY(-1.5px)';
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.background = '#ffffff';
              e.currentTarget.style.color = INK;
              e.currentTarget.style.borderColor = INK + '22';
              e.currentTarget.style.transform = 'translateY(0)';
            }}
            style={{
              flex: 1,
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 5,
              padding: '7px 8px',
              background: '#ffffff',
              border: `1.5px solid ${INK}22`,
              borderRadius: 999,
              color: INK,
              fontSize: 10, fontWeight: 700,
              cursor: 'pointer', fontFamily: FONT,
              transition: 'all 0.18s ease',
              whiteSpace: 'nowrap',
              boxShadow: `0 1.5px 0 ${INK}14`,
              letterSpacing: '-0.005em',
            }}>
            <span style={{
              width: 6, height: 6, borderRadius: 999,
              background: preset.color, flexShrink: 0,
            }} />
            {lang === 'en' ? preset.en : preset.ko}
          </button>
        ))}
      </div>

      {/* 3개 슬롯 — 가로 일렬 */}
      <div style={{ display: 'flex', gap: 8, marginBottom: 12 }}>
        {slots.map((slot, si) => {
          const bot = slot.idx !== null ? BOTS[slot.idx] : null;
          const BC = bot ? bot.C : null;
          const isOpen = openSlot === si;
          const slotColor = bot ? bot.color : INK;
          return (
            <div key={si} style={{ position: 'relative', flex: 1, minWidth: 0 }}>
              <div style={{
                display: 'flex', flexDirection: 'column', gap: 5,
                padding: '8px 6px 6px',
                background: '#ffffff',
                border: `1.5px solid ${bot ? slotColor + '55' : INK + '22'}`,
                borderRadius: 12,
                boxShadow: `0 1.5px 0 ${INK}14`,
                fontFamily: FONT,
              }}>
                {/* 봇 픽커 */}
                <button onClick={() => setOpenSlot(isOpen ? null : si)}
                  style={{
                    display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 3,
                    padding: '4px',
                    background: 'transparent',
                    border: 0,
                    cursor: 'pointer', fontFamily: FONT,
                  }}>
                  <div style={{ width: 32, height: 32, display: 'flex',
                    alignItems: 'center', justifyContent: 'center' }}>
                    {BC ? <BC size={32} /> : (
                      <span style={{
                        width: 30, height: 30, borderRadius: '50%',
                        background: '#f5f1e8', border: `1.5px dashed ${INK}33`,
                        display: 'flex', alignItems: 'center', justifyContent: 'center',
                        fontSize: 16, color: INK, opacity: 0.45, fontWeight: 700,
                      }}>+</span>
                    )}
                  </div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 2 }}>
                    <span style={{ fontSize: 10, fontWeight: 800,
                      color: bot ? slotColor : INK + '80' }}>
                      {bot ? bot.sub : (lang === 'en' ? 'Add' : '추가')}
                    </span>
                    <span style={{ fontSize: 7, color: bot ? slotColor : INK,
                      opacity: 0.55,
                      transform: isOpen ? 'rotate(180deg)' : 'rotate(0)',
                      transition: 'transform 0.2s' }}>▾</span>
                  </div>
                </button>
                {/* % 리스트박스 (정밀 선택) */}
                <select
                  value={slot.pct}
                  disabled={!bot}
                  onChange={(e) => {
                    const next = +e.target.value;
                    setSlots(prev => {
                      const cur = prev[si].pct;
                      const otherPct = totalPct - cur;
                      if (otherPct + next > MAX_TOTAL) return prev;
                      return prev.map((s, i) => i === si ? { ...s, pct: next } : s);
                    });
                  }}
                  style={{
                    width: 64,
                    margin: '0 auto',
                    padding: '3px 4px',
                    background: slot.pct > 0 ? slotColor : '#ffffff',
                    color: slot.pct > 0 ? '#ffffff' : INK,
                    border: `1.2px solid ${slot.pct > 0 ? slotColor : INK + '22'}`,
                    borderRadius: 5,
                    fontSize: 10, fontWeight: 800,
                    cursor: bot ? 'pointer' : 'not-allowed',
                    fontFamily: FONT,
                    textAlign: 'center',
                    textAlignLast: 'center',
                    appearance: 'none',
                    WebkitAppearance: 'none',
                    MozAppearance: 'none',
                    opacity: bot ? 1 : 0.5,
                  }}>
                  {PERCENT_OPTIONS.map(p => {
                    const isCur = slot.pct === p;
                    const wouldExceed = !isCur && (totalPct - slot.pct + p > MAX_TOTAL);
                    return (
                      <option key={p} value={p} disabled={wouldExceed}
                        style={{ background: '#ffffff', color: INK }}>
                        {p}%
                      </option>
                    );
                  })}
                </select>
              </div>

              {/* 봇 드롭다운 (슬롯 별) */}
              {isOpen && (
                <div style={{
                  position: 'absolute', top: 'calc(100% + 4px)', left: 0,
                  width: 200, background: '#ffffff',
                  border: `2px solid ${INK}`, borderRadius: 12,
                  padding: 5, boxShadow: `0 12px 30px rgba(0,0,0,0.16)`,
                  zIndex: 30, maxHeight: 320, overflowY: 'auto',
                }}>
                  {bot && (
                    <button onClick={() => setSlots(prev => prev.map((s, i) => i === si ? { idx: null, pct: 0 } : s)) || setOpenSlot(null)}
                      style={{
                        width: '100%', padding: '6px 10px',
                        background: 'transparent', border: 0, borderRadius: 6,
                        fontSize: 11, fontWeight: 700,
                        color: '#a83232', cursor: 'pointer',
                        textAlign: 'left', fontFamily: FONT,
                      }}>
                      ✕ {lang === 'en' ? 'Remove' : '제거'}
                    </button>
                  )}
                  {BOTS.map((b, i) => {
                    const BC2 = b.C;
                    const isCur = slot.idx === i;
                    const usedByOther = usedIdxs.includes(i) && !isCur;
                    return (
                      <button key={b.key}
                        disabled={usedByOther}
                        onClick={() => setSlotBot(si, i)}
                        onMouseEnter={(e) => { if (!usedByOther) e.currentTarget.style.background = `${b.color}1a`; }}
                        onMouseLeave={(e) => { e.currentTarget.style.background = isCur ? `${b.color}22` : 'transparent'; }}
                        style={{
                          width: '100%', display: 'flex', alignItems: 'center', gap: 8,
                          padding: '6px 8px',
                          background: isCur ? `${b.color}22` : 'transparent',
                          border: 0, borderRadius: 6,
                          cursor: usedByOther ? 'not-allowed' : 'pointer',
                          opacity: usedByOther ? 0.35 : 1,
                          fontFamily: FONT,
                          textAlign: 'left',
                        }}>
                        <div style={{ width: 24, height: 24, display: 'flex',
                          alignItems: 'center', justifyContent: 'center' }}>
                          {BC2 && <BC2 size={24} />}
                        </div>
                        <div style={{ fontSize: 12, fontWeight: 800, color: b.color }}>{b.sub}</div>
                      </button>
                    );
                  })}
                </div>
              )}
            </div>
          );
        })}
      </div>

      {/* 플랜 카드 3장 — 용량 캡 + 등급. 선택 시 selectPlan(cap)로 게이지 캡 변경 */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 12, padding: '0 4px' }}>
        {PLAN_OPTIONS.map(({ tier, cap, price, ko, en, dko, den, hot }) => {
          const sel = planTier === tier;
          return (
            <button key={tier} onClick={() => { selectPlan(cap); setPlanTier(tier); }}
              style={{
                position: 'relative', padding: '11px 13px', borderRadius: 12, cursor: 'pointer',
                border: `${sel ? 2 : 1.5}px solid ${sel ? accent : INK + '22'}`,
                background: sel ? `${accent}14` : '#fff', fontFamily: FONT, textAlign: 'left',
                display: 'flex', alignItems: 'center', justifyContent: 'space-between',
              }}>
              <div>
                <div style={{ fontSize: 14, fontWeight: 800, color: sel ? accent : INK }}>
                  {lang === 'en' ? en : ko}
                  {hot && <span style={{ marginLeft: 6, fontSize: 9, fontWeight: 700, color: accent, background: `${accent}1e`, padding: '2px 6px', borderRadius: 6 }}>{lang === 'en' ? 'Popular' : '인기'}</span>}
                </div>
                <div style={{ fontSize: 11, fontWeight: 600, color: '#9a8763', marginTop: 2 }}>{lang === 'en' ? den : dko}</div>
              </div>
              <div style={{ fontSize: 14, fontWeight: 800, color: INK }}>{price}<span style={{ fontSize: 10, fontWeight: 600, color: '#9a8763' }}>{lang === 'en' ? ' / mo' : ' / 월'}</span></div>
            </button>
          );
        })}
      </div>

      {/* 합계 게이지 — 0→선택캡 채움, 선택캡 도달 시에만 채팅 시작 enable */}
      <div style={{ marginBottom: 12, padding: '0 4px' }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
          <span style={{ fontSize: 10, fontWeight: 700, color: INK, opacity: 0.55,
            letterSpacing: '0.14em', textTransform: 'uppercase' }}>
            {lang === 'en' ? 'Capacity' : '용량'}
          </span>
          <span style={{ fontSize: 14, fontWeight: 800, color: ready ? accent : INK }}>
            {totalPct}% / {MAX_TOTAL}%
          </span>
        </div>
        {/* 채움 바 — 200%에서 가득 (50% 지점에 100% 눈금) */}
        <div style={{ position: 'relative', height: 9, borderRadius: 999,
          background: `${INK}12`, overflow: 'hidden' }}>
          <div style={{
            height: '100%',
            width: `${Math.min(totalPct, MAX_TOTAL) / MAX_TOTAL * 100}%`,
            background: ready
              ? `linear-gradient(90deg, ${primaryBot ? primaryBot.color : accent}, ${accent})`
              : (primaryBot ? primaryBot.color : accent),
            borderRadius: 999, transition: 'width 0.25s ease',
          }} />
          {MAX_TOTAL > 100 && (
            <div style={{ position: 'absolute', top: 0, bottom: 0, left: `${100 / MAX_TOTAL * 100}%`,
              width: 1.5, background: `${INK}33` }} />
          )}
        </div>
        {/* 안내 — 선택캡 미만이면 봇 더 채우라고 */}
        <div style={{ marginTop: 6, fontSize: 10, fontWeight: 600,
          color: ready ? accent : '#9a8763', lineHeight: 1.4 }}>
          {ready
            ? (lang === 'en' ? '✓ Full capacity — ready to start' : `✓ ${MAX_TOTAL}% 가득 — 시작 준비 완료`)
            : (lang === 'en'
                ? `Add more bot capacity to reach ${MAX_TOTAL}% (${MAX_TOTAL - totalPct}% to go)`
                : `봇을 더 채워 ${MAX_TOTAL}%로 (${MAX_TOTAL - totalPct}% 남음)`)}
        </div>
      </div>

      {/* 인사말 */}
      {primaryBot && totalPct > 0 && (
        <div style={{
          background: `${primaryBot.color}18`,
          border: `1.5px solid ${primaryBot.color}55`,
          borderRadius: 10,
          padding: '8px 11px',
          marginBottom: 12,
          fontSize: 12, fontWeight: 600,
          color: INK, lineHeight: 1.4,
        }}>
          <div style={{ fontSize: 8, fontWeight: 800,
            color: primaryBot.color, letterSpacing: '0.14em',
            textTransform: 'uppercase', marginBottom: 2 }}>
            {primaryBot.sub} {lang === 'en' ? 'says' : '인사'}
          </div>
          "{greet}"
        </div>
      )}

      {/* Start chat CTA — 200% 가득일 때만 활성 */}
      <button
        disabled={!ready}
        onClick={() => { if (ready) { if (primaryBot) localStorage.setItem('tc_bot', primaryBot.key); try { localStorage.setItem('tc_slots', JSON.stringify(slots.filter(s => s.idx != null && s.pct > 0).map(s => ({ key: BOTS[s.idx].key, pct: s.pct })))); } catch (e) {} window.location.href = '/internal/beta-v3/' + (primaryBot ? '?bot=' + primaryBot.key : ''); } }}
        title={ready ? '' : (lang === 'en' ? `Fill capacity to ${MAX_TOTAL}% to start` : `${MAX_TOTAL}% 채워야 시작할 수 있어요`)}
        onMouseEnter={(e) => { if (ready) {
          e.currentTarget.style.transform = 'translateY(-2px)';
          e.currentTarget.style.boxShadow = `0 8px 18px ${primaryBot ? primaryBot.color + '55' : INK + '33'}, 0 3px 0 ${INK}22`;
        }}}
        onMouseLeave={(e) => { e.currentTarget.style.transform = 'translateY(0)';
          e.currentTarget.style.boxShadow = `0 3px 0 ${INK}22`; }}
        style={{
          display: 'inline-flex', alignItems: 'center', gap: 7,
          padding: '8px 16px', borderRadius: 999,
          background: ready && primaryBot ? primaryBot.color : '#cfc7b8',
          color: '#ffffff',
          border: 0, fontSize: 11, fontWeight: 800,
          cursor: ready ? 'pointer' : 'not-allowed',
          fontFamily: FONT, letterSpacing: '0.02em',
          textTransform: 'uppercase',
          boxShadow: `0 3px 0 ${INK}22`,
          transition: 'all 0.18s ease',
        }}>
        <svg width="12" height="12" viewBox="0 0 16 16" fill="none">
          <path d="M2,4 A1,1 0 0,1 3,3 L13,3 A1,1 0 0,1 14,4 L14,11 A1,1 0 0,1 13,12 L6,12 L3,14.5 L3,12 A1,1 0 0,1 2,11 Z"
            stroke="#ffffff" strokeWidth={1.6} strokeLinejoin="round" fill="none" />
        </svg>
        {lang === 'en' ? 'Start Chat' : '채팅 시작'}
        {` · ${totalPct}%`}
      </button>

      {/* 가격 + 모바일 다운로드 */}
      <div style={{
        marginTop: 14, fontSize: 11, fontWeight: 600,
        color: '#7a6a4a', letterSpacing: '-0.005em',
        display: 'flex', flexDirection: 'column', gap: 6,
      }}>
        <div>
          {lang === 'en'
            ? 'Light $9 · Standard $15 · Pro $25 / mo'
            : '라이트 $9 · 스탠다드 $15 · 프로 $25 / 월'}
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8,
          fontSize: 10, color: '#7a6a4a' }}>
          <svg width="12" height="12" viewBox="0 0 14 14" fill="none">
            <rect x={3} y={1} width={8} height={12} rx={1.5}
              stroke="#7a6a4a" strokeWidth={1.4} fill="none" />
            <circle cx={7} cy={11} r={0.8} fill="#7a6a4a" />
          </svg>
          {lang === 'en' ? 'Also on mobile (iOS / Android)' : '모바일 앱 (iOS / Android)'}
        </div>
      </div>
    </div>
  );
}

// ═════════════════════════════════════════════════════════════════
// TalkCatcher — 예약/가입/로그인 + 사용안내/메커니즘 모달
// 노랑 hex: 밑화면 기존 #f5a857 (ADHD/Focus). 새 색 ❌.
// 인증: Supabase Auth (window.AdhdAuth, tc-auth.js). 결제/앱간연동은 scaffold.
// ═════════════════════════════════════════════════════════════════
const TALK_YELLOW = '#f5a857';
const TALK_YELLOW_SOFT = '#fdf2e1';

function tcRead(key, fallback) {
  try { const v = JSON.parse(localStorage.getItem(key)); return v == null ? fallback : v; }
  catch (e) { return fallback; }
}
function tcWrite(key, val) { try { localStorage.setItem(key, JSON.stringify(val)); } catch (e) {} }
// 관리자 데모 목록([6])용 최소 미러 — 비번 저장 ❌ (실제 인증은 Supabase)
function tcMirrorAccount(name, email, extra) {
  email = (email || '').toLowerCase();
  const accts = tcRead('tc_accounts', []).filter(a => a.email !== email);
  const prev = tcRead('tc_accounts', []).find(a => a.email === email) || {};
  accts.push(Object.assign({ name: name || prev.name || '', email, createdAt: prev.createdAt || new Date().toISOString(), plan: 'trial' }, prev, extra || {}, { name: name || prev.name || '', email }));
  tcWrite('tc_accounts', accts);
}
function tcPwChecks(pw) {
  return { len: pw.length >= 8, num: /[0-9]/.test(pw), sym: /[^A-Za-z0-9]/.test(pw) };
}
function tcPwOk(pw) { const c = tcPwChecks(pw); return c.len && c.num && c.sym; }

const tcInput = {
  width: '100%', padding: '11px 13px', marginBottom: 8,
  border: `1.5px solid #e8d9b8`, background: '#fff', borderRadius: 10,
  fontFamily: FONT, fontSize: 13.5, color: INK, outline: 'none', boxSizing: 'border-box',
};
const tcPrimaryBtn = {
  width: '100%', padding: '13px', background: TALK_YELLOW, color: '#1f1d1a',
  border: 0, borderRadius: 12, fontFamily: FONT, fontWeight: 800, fontSize: 14,
  cursor: 'pointer', boxShadow: `0 3px 0 ${INK}1a`,
};
const tcGhostBtn = {
  width: '100%', padding: '11px', background: TALK_YELLOW_SOFT, color: '#b8801c',
  border: `1.5px solid ${TALK_YELLOW}`, borderRadius: 12, fontFamily: FONT,
  fontWeight: 700, fontSize: 13, cursor: 'pointer',
};
const tcErr = (msg) => (
  <div style={{ marginTop: 4, marginBottom: 8, fontSize: 12, fontWeight: 600, color: '#C25E25',
    padding: '9px 12px', background: '#FEF1E9', borderRadius: 10, border: '1px solid #FCD9C2' }}>{msg}</div>
);
const tcFlag = (msg) => (
  <div style={{ marginTop: 10, fontSize: 10.5, lineHeight: 1.5, color: '#9a8763',
    padding: '8px 11px', background: '#f5ecd6', borderRadius: 9, border: `1px dashed ${INK}22` }}>{msg}</div>
);

// 가입/로그인 버튼 (예약 옆) — 같은 노랑 톤, 예약만 채움 pill
function TalkAuthButtons({ lang, user, verified, onSignup, onLogin, onLogout }) {
  const ko = lang === 'ko';
  const base = {
    padding: '8px 14px', borderRadius: 999, fontFamily: FONT, fontSize: lang === 'ko' ? 11 : 12, fontWeight: 700,
    cursor: 'pointer', whiteSpace: 'nowrap', transition: 'all 0.16s ease',
  };
  if (verified && user && user.email) {
    return (
      <button onClick={onLogout}
        style={{ ...base, background: TALK_YELLOW_SOFT, color: '#b8801c', border: `1.5px solid ${TALK_YELLOW}` }}>
        {ko ? '로그아웃' : 'Log out'}
      </button>
    );
  }
  return (
    <>
      <button onClick={onLogin}
        onMouseEnter={(e) => { e.currentTarget.style.background = '#fff'; }}
        onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}
        style={{ ...base, background: 'transparent', color: '#5a4a35', border: `1.5px solid ${INK}22` }}>
        {ko ? '로그인' : 'Log in'}
      </button>
      <button onClick={onSignup}
        onMouseEnter={(e) => { e.currentTarget.style.background = '#fff'; }}
        onMouseLeave={(e) => { e.currentTarget.style.background = 'transparent'; }}
        style={{ ...base, background: 'transparent', color: '#5a4a35', border: `1.5px solid ${INK}22` }}>
        {ko ? '가입' : 'Sign up'}
      </button>
    </>
  );
}

function AdhdAdminButtons({ lang, user, verified, onLogout }) {
  return (
    <TalkAuthButtons lang={lang} user={user} verified={verified} onSignup={() => { if (window.AdhdGate) window.AdhdGate.require(); }} onLogin={() => { if (window.AdhdGate) window.AdhdGate.require(); }} onLogout={onLogout} />
  );
}

function SuperButton({ lang }) {
  const onClick = () => {
    const pw = window.prompt(lang === 'ko' ? '슈퍼 관리자 비밀번호' : 'Super admin password');
    if (pw === null) return;
    if (pw === 'bnm123#') { window.location.href = '/super.html'; }
    else { alert(lang === 'ko' ? '비밀번호가 틀렸습니다.' : 'Wrong password.'); }
  };
  return (
    <button
      onClick={onClick}
      title={lang === 'ko' ? '슈퍼 관리자' : 'Super admin'}
      style={{ marginLeft: '8px', padding: '8px 16px', fontSize: lang === 'ko' ? '11px' : '12px', fontWeight: 600, fontFamily: 'inherit', background: 'transparent', border: '1px solid rgba(90,74,53,0.22)', borderRadius: '999px', color: '#5a4a35', cursor: 'pointer', whiteSpace: 'nowrap' }}
    >
      {lang === 'ko' ? '슈퍼' : 'Super'}
    </button>
  );
}

function TCModal({ title, eyebrow, onClose, children, maxWidth = 460 }) {
  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 1000,
      background: 'rgba(31,29,26,0.45)', backdropFilter: 'blur(3px)', WebkitBackdropFilter: 'blur(3px)',
      display: 'flex', alignItems: 'flex-start', justifyContent: 'center',
      padding: '40px 16px', overflowY: 'auto', fontFamily: FONT }}>
      <div onClick={(e) => e.stopPropagation()} style={{ width: maxWidth, maxWidth: '100%',
        background: '#fffdf6', border: `2px solid ${INK}`, borderRadius: 22,
        padding: '24px 26px 26px', boxShadow: '0 24px 60px rgba(31,29,26,0.30)', position: 'relative' }}>
        <button onClick={onClose} aria-label="close" style={{ position: 'absolute', top: 16, right: 16,
          width: 30, height: 30, borderRadius: 999, background: '#f4ede0', border: `1.5px solid ${INK}22`,
          color: INK, fontSize: 15, fontWeight: 800, cursor: 'pointer', lineHeight: 1, fontFamily: FONT }}>×</button>
        {eyebrow && <div style={{ fontSize: 10, fontWeight: 800, color: TALK_YELLOW, letterSpacing: '0.16em',
          textTransform: 'uppercase', marginBottom: 4 }}>{eyebrow}</div>}
        {title && <h2 style={{ margin: '0 0 14px', fontSize: 24, fontWeight: 800, color: INK,
          letterSpacing: '-0.02em', paddingRight: 28 }}>{title}</h2>}
        {children}
      </div>
    </div>
  );
}

// [3+5] 첫째 풀다운 — 사용 안내 (그림 포함)
function TCGuideModal({ lang, onClose }) {
  const ko = lang === 'ko';
  const BOTS = window.BOTS || [];
  const pics = ['adhd', 'anxiety', 'learning'].map(k => BOTS.find(b => b.key === k)).filter(Boolean);
  const steps = ko
    ? [['봇 고르기', '최대 3개까지 — 나에게 맞는 전문봇을 골라요.'],
       ['강도 채우기', '각 봇을 10~100%로, 합쳐서 200%까지 채워요.'],
       ['대화 시작', '200% 가득 차면 채팅이 열려요. 24/7 곁에 있어요.']]
    : [['Pick bots', 'Up to 3 — choose the specialists that fit you.'],
       ['Fill intensity', 'Each bot 10–100%, up to 200% combined.'],
       ['Start chatting', 'At full 200% the chat opens. Here 24/7.']];
  return (
    <TCModal eyebrow={ko ? '사용 안내' : 'Guide'} title={ko ? 'TalkCatcher 사용 안내' : 'How TalkCatcher works'}
      onClose={onClose} maxWidth={520}>
      {/* 그림 — 봇 일러스트 3종 */}
      <div style={{ display: 'flex', gap: 10, justifyContent: 'center', marginBottom: 16,
        padding: '14px 0', background: TALK_YELLOW_SOFT, borderRadius: 14 }}>
        {pics.map(b => {
          const C = b.C;
          return (
            <div key={b.key} style={{ textAlign: 'center' }}>
              <div style={{ width: 56, height: 56, margin: '0 auto', display: 'flex',
                alignItems: 'center', justifyContent: 'center' }}>{C ? <C size={56} /> : null}</div>
              <div style={{ fontSize: 10, fontWeight: 800, color: b.color, marginTop: 2 }}>{b.sub}</div>
            </div>
          );
        })}
      </div>
      {/* 스텝 */}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginBottom: 18 }}>
        {steps.map(([t, d], i) => (
          <div key={i} style={{ display: 'flex', gap: 12, alignItems: 'flex-start' }}>
            <span style={{ flexShrink: 0, width: 26, height: 26, borderRadius: 999, background: TALK_YELLOW,
              color: '#1f1d1a', fontWeight: 800, fontSize: 13, display: 'flex', alignItems: 'center',
              justifyContent: 'center' }}>{i + 1}</span>
            <div>
              <div style={{ fontSize: 14, fontWeight: 800, color: INK }}>{t}</div>
              <div style={{ fontSize: 12.5, color: '#5a4a35', lineHeight: 1.5 }}>{d}</div>
            </div>
          </div>
        ))}
      </div>
      {/* 봇 최대 3개 */}
      <div style={{ fontSize: 12.5, fontWeight: 700, color: INK, marginBottom: 8 }}>
        {ko ? '봇은 최대 3개까지 함께 둘 수 있어요.' : 'You can keep up to 3 bots together.'}
      </div>
      {/* 요금제 — 라이트/스탠다드/프로 3단계 (중간=하이라이트) */}
      <div style={{ fontSize: 10, fontWeight: 800, color: '#9a8763', letterSpacing: '0.14em',
        textTransform: 'uppercase', margin: '14px 0 8px' }}>{ko ? '요금제' : 'Plans'}</div>
      <div style={{ display: 'flex', gap: 10, marginBottom: 14 }}>
        {[['100%', '$9', ko ? '봇 강도 합 100%' : 'Bots total 100%'],
          ['150%', '$15', ko ? '봇 강도 합 150%' : 'Bots total 150%'],
          ['200%', '$25', ko ? '봇 강도 합 200% (가득)' : 'Bots total 200% (full)']].map(([cap, price, d], i) => (
          <div key={i} style={{ flex: 1, padding: '12px 14px', border: `1.5px solid ${i === 1 ? TALK_YELLOW : INK + '22'}`,
            background: i === 1 ? TALK_YELLOW_SOFT : '#fff', borderRadius: 14 }}>
            <div style={{ fontSize: 18, fontWeight: 800, color: i === 1 ? '#b8801c' : INK }}>{cap}</div>
            <div style={{ fontSize: 15, fontWeight: 800, color: INK, marginTop: 2 }}>{price}
              <span style={{ fontSize: 11, fontWeight: 600, color: '#9a8763' }}> {ko ? '/ 월' : '/ mo'}</span></div>
            <div style={{ fontSize: 11, color: '#5a4a35', marginTop: 4, lineHeight: 1.4 }}>{d}</div>
          </div>
        ))}
      </div>
      {/* 다른 쪽 정보 불러오기 */}
      <div style={{ fontSize: 12.5, color: '#5a4a35', lineHeight: 1.55, marginBottom: 12,
        padding: '10px 12px', background: '#fff', border: `1.5px solid ${INK}14`, borderRadius: 12 }}>
        {ko
          ? '다른 쪽(증상판별·개별증상 캐쳐)의 정보를 불러오면, 전문봇이 역할에 더 맞게 도울 수 있어요.'
          : 'When you bring in info from the other catchers (Symptom / Track), each bot can play its specialist role more fully.'}
      </div>
      {/* 보안 문구 — 지정 표현 그대로, 절대표현 ❌ */}
      <div style={{ display: 'flex', gap: 9, alignItems: 'flex-start',
        padding: '11px 13px', background: '#EFF5EB', border: '1.5px solid #cfe3c4', borderRadius: 12 }}>
        <span style={{ fontSize: 16, lineHeight: 1 }}>🔒</span>
        <div style={{ fontSize: 12, color: '#3f5a37', lineHeight: 1.55, fontWeight: 600 }}>
          {ko
            ? '여기 올린 자료는 본인 Google Drive 저장, 본인만 접근(회사도 못 봄).'
            : 'Anything you upload is stored in your own Google Drive — only you can open it (we can\'t see it either).'}
        </div>
      </div>
    </TCModal>
  );
}

// [3+5] 둘째 풀다운 — 작동 메커니즘
function TCMechanismModal({ lang, onClose }) {
  const ko = lang === 'ko';
  const rows = ko
    ? [['도메인 지식 금고', 'DSM-5-TR 기준 · 검증된 척도 · 인지왜곡 지도 · 기제 그래프 · 훈련 그리드를 도메인별로 보유.'],
       ['역할·말투 프로파일', '각 봇이 자기 영역의 어조·우선순위·금기를 담은 역할 정의를 따름.'],
       ['내 자료 검색(RAG)', '불러온 내 기록을 근거로 끌어와, 일반론이 아니라 내 맥락으로 응답.'],
       ['다중 알고리즘 파이프라인', '여러 알고리즘이 차례로 검토·교차확인해 한 봇의 응답을 만듦.']]
    : [['Domain knowledge vault', 'DSM-5-TR criteria, validated scales, distortion maps, mechanism graphs, training grids — per domain.'],
       ['Role & voice profile', 'Each bot follows a role definition with its tone, priorities, and boundaries.'],
       ['Retrieval over your data (RAG)', 'Pulls from the records you imported, so replies fit your context — not generic advice.'],
       ['Multi-algorithm pipeline', 'Several algorithms review and cross-check in turn to shape one bot\'s reply.']];
  return (
    <TCModal eyebrow={ko ? '작동 메커니즘' : 'How it works'}
      title={ko ? '전문봇은 이렇게 역할을 갖춰요' : 'How each bot earns its role'} onClose={onClose} maxWidth={540}>
      <p style={{ fontSize: 13, color: '#5a4a35', lineHeight: 1.6, marginTop: 0, marginBottom: 16 }}>
        {ko
          ? '각 봇이 "전문봇"이 되는 건 네 가지 조건이 맞물려서예요. 아래 네 가지가 모두 갖춰질 때 그 역할을 수행합니다.'
          : 'A bot becomes a "specialist" when four pieces fit together. It plays the role when all four below are in place.'}
      </p>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        {rows.map(([t, d], i) => (
          <div key={i} style={{ display: 'flex', gap: 12, alignItems: 'flex-start',
            padding: '12px 14px', background: '#fff', border: `1.5px solid ${INK}14`, borderRadius: 12 }}>
            <span style={{ flexShrink: 0, width: 22, height: 22, borderRadius: 999, background: '#EFF5EB',
              color: '#4F7544', fontWeight: 800, fontSize: 13, display: 'flex', alignItems: 'center',
              justifyContent: 'center', border: '1.5px solid #cfe3c4' }}>✓</span>
            <div>
              <div style={{ fontSize: 13.5, fontWeight: 800, color: INK }}>{t}</div>
              <div style={{ fontSize: 12.5, color: '#5a4a35', lineHeight: 1.5, marginTop: 2 }}>{d}</div>
            </div>
          </div>
        ))}
      </div>
      <div style={{ marginTop: 14, fontSize: 12.5, fontWeight: 700, color: '#4F7544',
        padding: '10px 12px', background: '#EFF5EB', border: '1.5px solid #cfe3c4', borderRadius: 12 }}>
        {ko ? '→ 네 조건이 모두 충족되면, 봇이 그 역할을 갖춘 상태로 작동합니다.'
            : '→ With all four met, the bot operates as a role-ready specialist.'}
      </div>
    </TCModal>
  );
}

// [1] 가입 — 이름+이메일+비번×2(요건) → Supabase signUp → 이메일 검증 메일
function TCSignupModal({ lang, onClose, onLogin }) {
  const ko = lang === 'ko';
  const [step, setStep] = React.useState('form'); // form | verify | done
  const [name, setName] = React.useState('');
  const [email, setEmail] = React.useState('');
  const [pw, setPw] = React.useState('');
  const [pw2, setPw2] = React.useState('');
  const [err, setErr] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [msg, setMsg] = React.useState('');
  const checks = tcPwChecks(pw);

  const submitForm = async () => {
    setErr('');
    if (!name.trim()) return setErr(ko ? '이름을 입력해주세요.' : 'Name is required.');
    if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) return setErr(ko ? '유효한 이메일을 입력해주세요.' : 'A valid email is required.');
    if (!tcPwOk(pw)) return setErr(ko ? '비밀번호 요건을 충족해주세요.' : 'Password does not meet the requirements.');
    if (pw !== pw2) return setErr(ko ? '비밀번호가 일치하지 않아요.' : 'Passwords do not match.');
    if (!window.AdhdAuth || !window.AdhdAuth.configured()) {
      return setErr(ko ? 'Supabase 프로젝트 미설정 (tc-auth.js — 할비 확정 대기).' : 'Supabase project not configured (tc-auth.js).');
    }
    setBusy(true);
    const { data, error } = await window.AdhdAuth.signUp({ name: name.trim(), email: email.trim().toLowerCase(), password: pw, lang, deployMode: 'consumer' });
    setBusy(false);
    if (error) return setErr((error.message === 'NOT_CONFIGURED')
      ? (ko ? 'Supabase 프로젝트 미설정.' : 'Supabase not configured.') : error.message);
    tcMirrorAccount(name.trim(), email.trim().toLowerCase(), { plan: 'trial', verified: false }); // [6] 관리자 데모 미러
    if (data && data.session) setStep('done'); // 이메일 확인 OFF → 즉시 로그인
    else setStep('verify'); // 이메일 확인 ON → 검증 대기
  };
  const resend = async () => {
    setMsg(''); setErr('');
    const { error } = await window.AdhdAuth.resendVerification(email.trim().toLowerCase());
    if (error) setErr(error.message); else setMsg(ko ? '검증 메일을 다시 보냈어요.' : 'Verification email resent.');
  };

  const Check = ({ ok, label }) => (
    <span style={{ fontSize: 11, fontWeight: 600, color: ok ? '#4F7544' : '#9a8763' }}>{ok ? '✓' : '○'} {label}</span>
  );

  return (
    <TCModal eyebrow={ko ? '가입' : 'Sign up'}
      title={step === 'verify' ? (ko ? '이메일을 확인해주세요' : 'Check your email')
            : step === 'done' ? (ko ? '가입 완료!' : 'You\'re in!') : (ko ? '계정 만들기' : 'Create account')}
      onClose={onClose}>
      {step === 'form' && (
        <>
          <input style={tcInput} placeholder={ko ? '이름' : 'Name'} value={name} onChange={e => setName(e.target.value)} />
          <input style={tcInput} type="email" placeholder={ko ? '이메일' : 'Email'} value={email} onChange={e => setEmail(e.target.value)} />
          <input style={tcInput} type="password" placeholder={ko ? '비밀번호' : 'Password'} value={pw} onChange={e => setPw(e.target.value)} />
          <input style={tcInput} type="password" placeholder={ko ? '비밀번호 다시 입력' : 'Confirm password'} value={pw2} onChange={e => setPw2(e.target.value)} />
          <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', margin: '2px 2px 12px' }}>
            <Check ok={checks.len} label={ko ? '8자 이상' : '8+ chars'} />
            <Check ok={checks.num} label={ko ? '숫자 포함' : 'a number'} />
            <Check ok={checks.sym} label={ko ? '특수문자 포함' : 'a symbol'} />
            {pw2.length > 0 && <Check ok={pw === pw2 && pw.length > 0} label={ko ? '일치' : 'match'} />}
          </div>
          {err && tcErr(err)}
          <button style={{ ...tcPrimaryBtn, opacity: busy ? 0.6 : 1 }} disabled={busy} onClick={submitForm}>
            {busy ? (ko ? '처리 중…' : 'Working…') : (ko ? '가입하기' : 'Sign up')}</button>
          <div style={{ textAlign: 'center', marginTop: 12, fontSize: 12, color: '#5a4a35' }}>
            {ko ? '이미 계정이 있나요? ' : 'Already have an account? '}
            <button onClick={onLogin} style={{ border: 0, background: 'none', color: '#b8801c', fontWeight: 800, cursor: 'pointer', fontFamily: FONT, fontSize: 12 }}>
              {ko ? '로그인' : 'Log in'}</button>
          </div>
        </>
      )}
      {step === 'verify' && (
        <>
          <p style={{ fontSize: 13.5, color: '#5a4a35', lineHeight: 1.6, marginTop: 0 }}>
            {ko ? `${email} 로 검증 메일을 보냈어요. 메일의 링크를 누르면 가입이 완료돼요. 검증 전엔 로그인·데이터 연동이 비활성입니다.`
                : `We sent a verification link to ${email}. Click it to finish signing up. Login and data link stay disabled until verified.`}
          </p>
          {err && tcErr(err)}
          {msg && <div style={{ marginBottom: 10, fontSize: 12, fontWeight: 600, color: '#4F7544', padding: '9px 12px', background: '#EFF5EB', borderRadius: 10, border: '1px solid #cfe3c4' }}>{msg}</div>}
          <button style={tcPrimaryBtn} onClick={onLogin}>{ko ? '로그인으로' : 'Go to login'}</button>
          <button style={{ ...tcGhostBtn, marginTop: 10 }} onClick={resend}>{ko ? '검증 메일 다시 보내기' : 'Resend verification email'}</button>
        </>
      )}
      {step === 'done' && (
        <>
          <p style={{ fontSize: 13.5, color: '#5a4a35', lineHeight: 1.6, marginTop: 0 }}>
            {ko ? `${name}님, 환영해요! 로그인된 상태예요.` : `Welcome, ${name}! You're logged in.`}
          </p>
          <button style={tcPrimaryBtn} onClick={() => { window.location.href = '/internal/beta-v3/'; }}>{ko ? '채팅으로 가기' : 'Go to chat'}</button>
        </>
      )}
    </TCModal>
  );
}

// [1] 로그인 + 비밀번호 찾기 (Supabase Auth)
function TCLoginModal({ lang, onClose, onSignup, user, onAuthChange, onDataLink }) {
  const ko = lang === 'ko';
  const [mode, setMode] = React.useState(user && user.email ? 'account' : 'login'); // login | reset | account
  const [email, setEmail] = React.useState('');
  const [pw, setPw] = React.useState('');
  const [err, setErr] = React.useState('');
  const [msg, setMsg] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const cfg = !!(window.AdhdAuth && window.AdhdAuth.configured());

  const doLogin = async () => {
    setErr('');
    if (!cfg) return setErr(ko ? 'Supabase 프로젝트 미설정 (tc-auth.js — 할비 확정 대기).' : 'Supabase not configured (tc-auth.js).');
    setBusy(true);
    const { data, error } = await window.AdhdAuth.signIn({ email: email.trim().toLowerCase(), password: pw });
    setBusy(false);
    if (error) {
      const notConfirmed = /not confirmed|confirm/i.test(error.message || '');
      return setErr(notConfirmed
        ? (ko ? '이메일 검증이 아직 안 됐어요. 메일의 링크를 먼저 눌러주세요.' : 'Email not verified yet — click the link in your email first.')
        : (ko ? '이메일 또는 비밀번호가 맞지 않아요.' : 'Email or password is incorrect.'));
    }
    if (data && data.user) tcMirrorAccount((data.user.user_metadata || {}).display_name, data.user.email, { verified: true });
    if (onAuthChange) onAuthChange();
    setMode('account');
  };
  const doReset = async () => {
    setErr(''); setMsg('');
    if (!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email)) return setErr(ko ? '유효한 이메일을 입력해주세요.' : 'A valid email is required.');
    if (!cfg) return setErr(ko ? 'Supabase 프로젝트 미설정.' : 'Supabase not configured.');
    setBusy(true);
    const { error } = await window.AdhdAuth.resetPassword(email.trim().toLowerCase());
    setBusy(false);
    if (error) return setErr(error.message);
    setMsg(ko ? '재설정 링크를 이메일로 보냈어요. 메일에서 링크를 누르면 새 비밀번호를 정할 수 있어요.'
             : 'Reset link sent. Open it from your email to set a new password.');
  };
  const logout = async () => { if (window.AdhdAuth) await window.AdhdAuth.signOut(); if (onAuthChange) onAuthChange(); setMode('login'); setEmail(''); setPw(''); };
  const verified = window.AdhdAuth ? window.AdhdAuth.isVerified(user) : false;

  return (
    <TCModal eyebrow={mode === 'reset' ? (ko ? '비밀번호 찾기' : 'Reset') : (ko ? '로그인' : 'Log in')}
      title={mode === 'account' ? (ko ? '내 계정' : 'My account') : mode === 'reset' ? (ko ? '비밀번호 재설정' : 'Reset password') : (ko ? '로그인' : 'Log in')}
      onClose={onClose}>
      {mode === 'login' && (
        <>
          <input style={tcInput} type="email" placeholder={ko ? '이메일' : 'Email'} value={email} onChange={e => setEmail(e.target.value)} />
          <input style={tcInput} type="password" placeholder={ko ? '비밀번호' : 'Password'} value={pw}
            onChange={e => setPw(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') doLogin(); }} />
          {err && tcErr(err)}
          <button style={{ ...tcPrimaryBtn, opacity: busy ? 0.6 : 1 }} disabled={busy} onClick={doLogin}>
            {busy ? (ko ? '처리 중…' : 'Working…') : (ko ? '로그인' : 'Log in')}</button>
          <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 12, fontSize: 12 }}>
            <button onClick={() => { setErr(''); setMode('reset'); }} style={{ border: 0, background: 'none', color: '#5a4a35', cursor: 'pointer', fontFamily: FONT, fontSize: 12 }}>
              {ko ? '비밀번호 찾기' : 'Forgot password?'}</button>
            <button onClick={onSignup} style={{ border: 0, background: 'none', color: '#b8801c', fontWeight: 800, cursor: 'pointer', fontFamily: FONT, fontSize: 12 }}>
              {ko ? '가입하기' : 'Sign up'}</button>
          </div>
        </>
      )}
      {mode === 'reset' && (
        <>
          <p style={{ fontSize: 13, color: '#5a4a35', lineHeight: 1.6, marginTop: 0 }}>
            {ko ? '가입한 이메일로 재설정 링크를 보내드려요.' : 'We\'ll send a reset link to your email.'}</p>
          <input style={tcInput} type="email" placeholder={ko ? '이메일' : 'Email'} value={email} onChange={e => setEmail(e.target.value)} />
          {err && tcErr(err)}
          {msg && <div style={{ marginBottom: 10, fontSize: 12, fontWeight: 600, color: '#4F7544', padding: '9px 12px', background: '#EFF5EB', borderRadius: 10, border: '1px solid #cfe3c4' }}>{msg}</div>}
          <button style={{ ...tcPrimaryBtn, opacity: busy ? 0.6 : 1 }} disabled={busy} onClick={doReset}>{ko ? '재설정 링크 보내기' : 'Send reset link'}</button>
          <button style={{ ...tcGhostBtn, marginTop: 10 }} onClick={() => { setMsg(''); setErr(''); setMode('login'); }}>{ko ? '← 로그인으로' : '← Back to login'}</button>
        </>
      )}
      {mode === 'account' && user && (
        <>
          <div style={{ padding: '12px 14px', background: TALK_YELLOW_SOFT, borderRadius: 12, marginBottom: 12 }}>
            <div style={{ fontSize: 14, fontWeight: 800, color: INK }}>{(user.user_metadata || {}).display_name || user.email}</div>
            <div style={{ fontSize: 12, color: '#5a4a35' }}>{user.email} {verified
              ? <span style={{ color: '#4F7544', fontWeight: 700 }}>· {ko ? '검증됨' : 'verified'}</span>
              : <span style={{ color: '#C25E25', fontWeight: 700 }}>· {ko ? '미검증' : 'unverified'}</span>}</div>
          </div>
          <button style={tcPrimaryBtn} onClick={() => { window.location.href = '/internal/beta-v3/'; }}>{ko ? '채팅으로 가기' : 'Go to chat'}</button>
          <button style={{ ...tcGhostBtn, marginTop: 10, opacity: verified ? 1 : 0.55, cursor: verified ? 'pointer' : 'not-allowed' }}
            disabled={!verified} onClick={() => verified && onDataLink && onDataLink()}>
            {ko ? '다른 앱 정보 불러오기' : 'Import data from other apps'}</button>
          <button style={{ ...tcGhostBtn, marginTop: 10, background: '#fff', color: '#5a4a35', border: `1.5px solid ${INK}22` }} onClick={logout}>{ko ? '로그아웃' : 'Log out'}</button>
        </>
      )}
    </TCModal>
  );
}

// [1] 비밀번호 재설정 완료 — 메일 링크(recovery)로 돌아왔을 때 새 비번 설정
function TCRecoveryModal({ lang, onClose, onAuthChange }) {
  const ko = lang === 'ko';
  const [pw, setPw] = React.useState('');
  const [pw2, setPw2] = React.useState('');
  const [err, setErr] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [done, setDone] = React.useState(false);
  const checks = tcPwChecks(pw);
  const submit = async () => {
    setErr('');
    if (!tcPwOk(pw)) return setErr(ko ? '비밀번호 요건을 충족해주세요.' : 'Password does not meet the requirements.');
    if (pw !== pw2) return setErr(ko ? '비밀번호가 일치하지 않아요.' : 'Passwords do not match.');
    setBusy(true);
    const { error } = await window.AdhdAuth.updatePassword(pw);
    setBusy(false);
    if (error) return setErr(error.message);
    if (onAuthChange) onAuthChange();
    setDone(true);
  };
  const Check = ({ ok, label }) => (<span style={{ fontSize: 11, fontWeight: 600, color: ok ? '#4F7544' : '#9a8763' }}>{ok ? '✓' : '○'} {label}</span>);
  return (
    <TCModal eyebrow={ko ? '비밀번호 재설정' : 'Reset'} title={ko ? '새 비밀번호 설정' : 'Set a new password'} onClose={onClose}>
      {done ? (
        <>
          <p style={{ fontSize: 13.5, color: '#5a4a35', lineHeight: 1.6, marginTop: 0 }}>
            {ko ? '비밀번호가 바뀌었어요. 로그인된 상태예요.' : 'Password updated. You\'re logged in.'}</p>
          <button style={tcPrimaryBtn} onClick={onClose}>{ko ? '완료' : 'Done'}</button>
        </>
      ) : (
        <>
          <input style={tcInput} type="password" placeholder={ko ? '새 비밀번호' : 'New password'} value={pw} onChange={e => setPw(e.target.value)} />
          <input style={tcInput} type="password" placeholder={ko ? '새 비밀번호 다시' : 'Confirm new password'} value={pw2} onChange={e => setPw2(e.target.value)} />
          <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', margin: '2px 2px 12px' }}>
            <Check ok={checks.len} label={ko ? '8자 이상' : '8+ chars'} />
            <Check ok={checks.num} label={ko ? '숫자 포함' : 'a number'} />
            <Check ok={checks.sym} label={ko ? '특수문자 포함' : 'a symbol'} />
          </div>
          {err && tcErr(err)}
          <button style={{ ...tcPrimaryBtn, opacity: busy ? 0.6 : 1 }} disabled={busy} onClick={submit}>{ko ? '비밀번호 바꾸기' : 'Update password'}</button>
        </>
      )}
    </TCModal>
  );
}

// [2] 앱간 데이터 링크 — 로그인+검증된 이메일로만. 이름/이메일 입력칸 ❌.
//     동의 → 본인 Drive로 pull. symptom/track 소스 미연동 → scaffold(목록만)+flag.
function TCDataLinkModal({ lang, onClose, user }) {
  const ko = lang === 'ko';
  const verified = window.AdhdAuth ? window.AdhdAuth.isVerified(user) : false;
  const email = user && user.email ? user.email : '';
  const [step, setStep] = React.useState('pick'); // pick | done
  const [consent, setConsent] = React.useState(false);
  const sources = ko
    ? [{ app: '증상판별캐쳐', items: ['ADHD 선별 결과 (ASRS)', '수면 패턴 요약', '기분 변동 기록'] },
       { app: '개별증상캐쳐 (트랙)', items: ['최근 30일 집중도 추이', '수면 시간 로그', '감정 일기 태그'] }]
    : [{ app: 'SymptomCatcher', items: ['ADHD screen (ASRS)', 'Sleep pattern summary', 'Mood swing log'] },
       { app: 'TrackCatcher', items: ['Focus trend (30 days)', 'Sleep-time log', 'Mood-journal tags'] }];
  const allKeys = sources.flatMap((s, si) => s.items.map((_, ii) => si + ':' + ii));
  const [picked, setPicked] = React.useState(() => new Set(allKeys));
  const toggle = (k) => setPicked(prev => { const n = new Set(prev); n.has(k) ? n.delete(k) : n.add(k); return n; });

  const pull = () => {
    const sel = sources.flatMap((s, si) => s.items.filter((_, ii) => picked.has(si + ':' + ii)).map(label => ({ app: s.app, label })));
    tcWrite('tc_imported', { email: email.toLowerCase(), at: new Date().toISOString(), items: sel });
    setStep('done');
  };

  // 신원 게이트 — 로그인·검증 안 됐으면 진입 차단
  if (!verified) {
    return (
      <TCModal eyebrow={ko ? '데이터 연동' : 'Data link'} title={ko ? '로그인이 필요해요' : 'Login required'} onClose={onClose} maxWidth={460}>
        <p style={{ fontSize: 13.5, color: '#5a4a35', lineHeight: 1.6, marginTop: 0 }}>
          {ko ? '검증된 계정으로 로그인한 뒤에만 내 기록을 불러올 수 있어요.' : 'Sign in with a verified account to import your records.'}</p>
        <button style={tcPrimaryBtn} onClick={onClose}>{ko ? '닫기' : 'Close'}</button>
      </TCModal>
    );
  }

  return (
    <TCModal eyebrow={ko ? '데이터 연동' : 'Data link'}
      title={ko ? '내 기록 불러오기' : 'Import my records'} onClose={onClose} maxWidth={500}>
      {step === 'pick' && (
        <>
          <div style={{ fontSize: 12, color: '#5a4a35', marginBottom: 12, padding: '8px 11px',
            background: TALK_YELLOW_SOFT, borderRadius: 10 }}>
            {ko ? '로그인 계정' : 'Account'}: <strong style={{ color: INK }}>{email}</strong> {ko ? '의 기록만 조회해요.' : ' — only this identity is queried.'}
          </div>
          {sources.map((s, si) => (
            <div key={si} style={{ marginBottom: 12 }}>
              <div style={{ fontSize: 10, fontWeight: 800, color: '#9a8763', letterSpacing: '0.1em', textTransform: 'uppercase', marginBottom: 6 }}>{s.app}</div>
              {s.items.map((it, ii) => {
                const k = si + ':' + ii; const on = picked.has(k);
                return (
                  <label key={ii} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '9px 11px', marginBottom: 6,
                    background: on ? TALK_YELLOW_SOFT : '#fff', border: `1.5px solid ${on ? TALK_YELLOW : INK + '18'}`,
                    borderRadius: 10, cursor: 'pointer' }}>
                    <input type="checkbox" checked={on} onChange={() => toggle(k)} style={{ accentColor: TALK_YELLOW }} />
                    <span style={{ fontSize: 12.5, color: INK, fontWeight: 600 }}>{it}</span>
                  </label>
                );
              })}
            </div>
          ))}
          {/* 동의 */}
          <label style={{ display: 'flex', alignItems: 'flex-start', gap: 9, padding: '10px 12px', marginBottom: 10,
            background: '#EFF5EB', border: '1.5px solid #cfe3c4', borderRadius: 10, cursor: 'pointer' }}>
            <input type="checkbox" checked={consent} onChange={e => setConsent(e.target.checked)} style={{ accentColor: '#4F7544', marginTop: 2 }} />
            <span style={{ fontSize: 12, color: '#3f5a37', lineHeight: 1.5, fontWeight: 600 }}>
              {ko ? '선택 항목을 본인 Google Drive로 가져오는 데 동의합니다 (회사 서버 저장 ❌).'
                  : 'I agree to pull the selected items into my own Google Drive (not company servers).'}</span>
          </label>
          <button style={{ ...tcPrimaryBtn, opacity: consent ? 1 : 0.55, cursor: consent ? 'pointer' : 'not-allowed' }}
            disabled={!consent} onClick={pull}>
            {ko ? `내 Drive로 가져오기 (${picked.size})` : `Pull to my Drive (${picked.size})`}</button>
          {tcFlag(ko ? '⚠ scaffold: symptom/track 소스·Drive pull 미연동 — 위 목록은 예시. 신원 게이트(로그인+검증 이메일)는 실제 적용됨.'
                    : '⚠ scaffold: symptom/track source & Drive pull not wired — list is a sample. Identity gate (verified login) is real.')}
        </>
      )}
      {step === 'done' && (
        <>
          <p style={{ fontSize: 13.5, color: '#5a4a35', lineHeight: 1.6, marginTop: 0 }}>
            {ko ? '선택한 기록을 가져오기로 표시했어요. (실제 Drive 저장은 소스/Drive 연동 후)' : 'Marked your selection for import. (Actual Drive save once source/Drive are wired.)'}</p>
          <button style={tcPrimaryBtn} onClick={onClose}>{ko ? '완료' : 'Done'}</button>
          {tcFlag(ko ? '⚠ scaffold: 현재는 이 브라우저에 선택만 저장. Drive pull은 gapi(beta-v3 drive.js) 연동 필요.'
                    : '⚠ scaffold: selection saved in this browser only. Drive pull needs gapi (beta-v3 drive.js).')}
        </>
      )}
    </TCModal>
  );
}

// 고정 stage 하단 법적 바 (Stripe 요구 — legal 링크 + 회사정보). whiteSpace:nowrap + flexWrap = 세로 깨짐 방지.
function TalkLegalFooter({ lang }) {
  const en = lang === 'en';
  return (
    <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, zIndex: 60,
      padding: '7px 24px', display: 'flex', alignItems: 'center', justifyContent: 'center',
      flexWrap: 'wrap', gap: 9, fontFamily: FONT, fontSize: 10.5,
      color: 'rgba(255,255,255,0.62)', background: 'rgba(0,0,0,0.34)', backdropFilter: 'blur(4px)' }}>
      <span style={{ whiteSpace: 'nowrap', opacity: 0.85 }}>
        {en ? 'TalkCatcher is an AI wellness tool, not medical care or diagnosis · Crisis? 988'
            : 'TalkCatcher는 AI 웰니스 도구이며 의료·진단·치료가 아니에요 · 위기? 988'}
      </span>
      <span style={{ opacity: 0.4 }}>·</span>
      {LEGAL_NAV.map((l, i) => (
        <React.Fragment key={l.en}>
          {i > 0 && <span style={{ opacity: 0.4 }}>·</span>}
          <a href={l.href + '?from=' + encodeURIComponent('https://agedlearning.com/')} target="_blank" rel="noopener"
            style={{ color: 'rgba(255,255,255,0.72)', textDecoration: 'none', whiteSpace: 'nowrap' }}>
            {en ? l.en : l.ko}
          </a>
        </React.Fragment>
      ))}
      <span style={{ opacity: 0.4 }}>·</span>
      <span style={{ whiteSpace: 'nowrap' }}>© 2026 Boston Neuromind LLC · 866 Washington St, Canton MA 02021</span>
    </div>
  );
}

function TalkCatcherHero() {
  const [lang, setLang] = React.useState(typeof window !== 'undefined' && window.bnmGetLang ? window.bnmGetLang() : 'en');
  const [modal, setModal] = React.useState(null); // guide | mechanism | signup | login | datalink | recovery | null
  const [user, setUser] = React.useState(null);          // raw user (모달 표시용 - 미검증 포함)
  const [verified, setVerified] = React.useState(false); // 헤더 게이트 (peak isVerified 기준)
  const [role, setRole] = React.useState(null);          // 임상가 역할 (owner/admin/clinician)
  const close = () => setModal(null);

  // peak init() 과 동일 순서를 한 곳에서: getUser -> isVerified 게이트 -> ensure -> role
  const refreshAuth = React.useCallback(async () => {
    if (!window.AdhdAuth) { setUser(null); setVerified(false); setRole(null); return; }
    let u = null;
    try { u = await window.AdhdAuth.getUser(); } catch (e) { u = null; }
    setUser(u);
    const ok = !!(u && window.AdhdAuth.isVerified && window.AdhdAuth.isVerified(u));
    setVerified(ok);
    if (!ok) { setRole(null); return; }
    if (window.AdhdSession && window.AdhdSession.ensure) {
      try { await window.AdhdSession.ensure(); } catch (e) {}
    }
    const s = (window.AdhdSession && window.AdhdSession.current) ? window.AdhdSession.current() : null;
    setRole(s ? s.role : null);
  }, []);

  React.useEffect(() => {
    refreshAuth();
    let off = null;
    if (window.AdhdAuth && window.AdhdAuth.onChange) off = window.AdhdAuth.onChange(() => { refreshAuth(); });
    // 메일 링크(recovery)로 돌아온 경우 hash로도 감지
    try { if (/type=recovery/.test(window.location.hash || '')) setModal('recovery'); } catch (e) {}
    return () => { if (typeof off === 'function') off(); };
  }, [refreshAuth]);

  // peak 로그아웃과 동일: AdhdSession.logout + signOut + location.reload
  const handleLogout = React.useCallback(async () => {
    try { if (window.AdhdSession && window.AdhdSession.logout) await window.AdhdSession.logout(); } catch (e) {}
    try { if (window.AdhdAuth && window.AdhdAuth.client) { const c = window.AdhdAuth.client(); if (c) await c.auth.signOut(); } } catch (e) {}
    location.reload();
  }, []);

  // 헤더 버튼 - 단일 상태(user/verified/role) 전달, 자체 구독 없음
  const authButtons = <AdhdAdminButtons lang={lang} user={user} verified={verified} role={role} onLogout={handleLogout} />;
  const overlay = (
    <>
      {modal === 'guide' && <TCGuideModal lang={lang} onClose={close} />}
      {modal === 'mechanism' && <TCMechanismModal lang={lang} onClose={close} />}
      {modal === 'signup' && <TCSignupModal lang={lang} onClose={close} onLogin={() => setModal('login')} />}
      {modal === 'login' && <TCLoginModal lang={lang} onClose={close} onSignup={() => setModal('signup')}
        user={user} onAuthChange={refreshAuth} onDataLink={() => setModal('datalink')} />}
      {modal === 'datalink' && <TCDataLinkModal lang={lang} onClose={close} user={user} />}
      {modal === 'recovery' && <TCRecoveryModal lang={lang} onClose={close} onAuthChange={refreshAuth} />}
    </>
  );
  return <SiteHero siteKey="talk" config={CONFIGS.talk}
    hideCorner={true}
    lang={lang} setLang={setLang}
    onCta={() => { window.location.href = '/Booking.html'; }}
    ctaColor={TALK_YELLOW} ctaSoft={true}
    authButtons={authButtons} overlay={overlay}
    onNavAction={(a) => setModal(a)}
    extras={(p, lang2) => <TalkBotRentalCard accent={p.accent} lang={lang2} />}
    pose={({ p, accent }) => <PoseTalk p={p} accent={accent} />} />;
}
function BostonNeuroMindHero() {
  return <SiteHero siteKey="boston" config={CONFIGS.boston}
    hideCorner={true}
    extras={(p) => <SceneBostonExtras p={p} />}
    pose={({ p, lang }) => <PoseBoston p={p} lang={lang} />} />;
}
function NeuroCatchersHero() {
  return <SiteHero siteKey="neuro" config={CONFIGS.neuro}
    hideCorner={true}
    extras={(p, lang) => <SceneNeuroExtras p={p} lang={lang} />}
    pose={({ p, lang }) => <PoseNeuro p={p} lang={lang} />} />;
}
function ModalityCatcherHero() {
  return <SiteHero siteKey="modality" config={CONFIGS.modality}
    extras={(p, lang) => <TherapistThoughts accent={p.accent} lang={lang} />}
    pose={({ p, lang }) => <PoseModality p={p} lang={lang} />} />;
}

// ═════════════════════════════════════════════════════════════════
// TrackCatcher Globe — 큰 글로브 안에 symptom 이름 + 봇이 번갈아 들어가는 캐쳐
// 11개 봇이 차례로 글로브 안에 등장 → 11개 제품의 시각 시그니처
function TrackCatcherSession() {
  const [lang, setLang] = React.useState(typeof window !== 'undefined' && window.bnmGetLang ? window.bnmGetLang() : 'en');
  const [idx, setIdx] = React.useState(0);
  const [autoPlay, setAutoPlay] = React.useState(true);
  const [tick, setTick] = React.useState(0);
  const BOTS = window.BOTS || [];

  React.useEffect(() => {
    if (!autoPlay || BOTS.length === 0) return;
    // 120초 한 바퀴 끝나면 다음 봇으로
    const id = setInterval(() => setIdx(i => (i + 1) % BOTS.length), 120000);
    return () => clearInterval(id);
  }, [autoPlay, BOTS.length]);

  // 행성 공전 — 100ms마다 위치 갱신 (240초 한 바퀴, 매우 천천히)
  React.useEffect(() => {
    if (!autoPlay) return;
    const id = setInterval(() => setTick(t => t + 1), 100);
    return () => clearInterval(id);
  }, [autoPlay]);

  const bot = BOTS[idx] || {};
  const accent = bot.color || '#5a8acc';
  const site = SITE_COLORS.neuro;
  const p = { ...SITE_PALETTES.neuro, id: 'neuro', accent };
  const BotC = bot.C;
  const c = CONFIGS.neuro[lang] || CONFIGS.neuro;

  const GW = 480; // globe diameter
  const CW = GW + 100, CH = GW + 140;
  const gcx = CW / 2, gcy = GW / 2 + 30, gr = GW / 2;
  const standId = `globeShadow-${idx}`;

  return (
    <div style={{ width: '100%', height: '100%', position: 'relative',
      overflow: 'hidden',
      background: 'radial-gradient(ellipse at center, #4a3550 0%, #2c1f38 55%, #18101f 100%)',
      fontFamily: FONT }}>
      <Nav siteName={site.name} items={c.nav} ctaLabel={c.navCta}
        accent={site.value} lang={lang} setLang={setLang} currentSite="neuro" darkMode={true} />

      <style>{`
        @keyframes orbit {
          from { transform: rotate(0deg); }
          to   { transform: rotate(360deg); }
        }
        @keyframes shootingStar {
          0%   { opacity: 0; transform: translate(0, 0) scale(0.4); }
          5%   { opacity: 1; transform: translate(0, 0) scale(1); }
          85%  { opacity: 1; transform: translate(var(--sx), var(--sy)) scale(0.8); }
          92%  { opacity: 0; transform: translate(var(--sx), var(--sy)) scale(0.4); }
          100% { opacity: 0; transform: translate(0, 0) scale(0.4); }
        }
        @keyframes starPulseSlow {
          0%, 100% { opacity: 0.2; transform: scale(0.8); }
          50%      { opacity: 0.9; transform: scale(1.2); }
        }
        @keyframes starSpin {
          0%, 100% { transform: rotate(0deg) scale(1); opacity: 0.85; }
          50%      { transform: rotate(180deg) scale(1.3); opacity: 1; }
        }
        @keyframes rocketRoundTrip {
          0%   { transform: translate(var(--start-x), var(--start-y)); }
          22%  { transform: translate(var(--apex-x), var(--apex-y)); }
          44%, 56% { transform: translate(var(--target-x), var(--target-y)); }
          78%  { transform: translate(var(--apex-x), var(--apex-y)); }
          100% { transform: translate(var(--start-x), var(--start-y)); }
        }
        @keyframes rocketSpin {
          from { transform: rotate(0deg); }
          to   { transform: rotate(-360deg); }
        }
        @keyframes planetSlowSpin {
          from { transform: rotate(0deg); }
          to   { transform: rotate(360deg); }
        }
        @keyframes starTwinkle {
          0%, 100% { opacity: 0.4; }
          50%      { opacity: 1; }
        }
        @keyframes accentStarTwinkle {
          0%, 100% { opacity: 0.5; transform: scale(1); }
          50%      { opacity: 1; transform: scale(1.4); }
        }
        @keyframes sunPulse {
          0%, 100% { opacity: 0.5; transform: scale(1); }
          50%      { opacity: 0.7; transform: scale(1.04); }
        }
        @keyframes rocketFlame {
          0%, 100% { transform: scaleY(1); opacity: 0.95; }
          50%      { transform: scaleY(1.3); opacity: 0.75; }
        }
        @keyframes labelFloat {
          0%, 100% { transform: translate(-50%, 0); }
          50%      { transform: translate(-50%, -4px); }
        }
        @keyframes weekFade {
          0%, 100% { opacity: 0.55; }
          50%      { opacity: 1; }
        }
      `}</style>

      {/* === 태양 중심 + 11 행성 정적 + 로켓이 한 바퀴 돌며 모든 행성 방문 === */}
      {(() => {
        const cx = 720, cy = 460;
        const sunR = 60;
        const planetSizes = [24, 30, 36, 28, 38, 44, 36, 32, 28, 26, 22];
        const orbitRx = 380;
        const orbitRy = 210;
        // 11 행성 — 정적 배치
        const planets = BOTS.map((b, i) => {
          const a = (i / BOTS.length) * Math.PI * 2 - Math.PI / 2;
          return {
            ...b,
            angle: a,
            x: cx + Math.cos(a) * orbitRx,
            y: cy + Math.sin(a) * orbitRy,
            size: planetSizes[i] || 28,
          };
        });

        // 로켓 위치 — 한 바퀴 = 120초
        const CYCLE = 120;
        const phase = (tick * 0.1 / CYCLE) % 1;
        const rocketA = phase * Math.PI * 2 - Math.PI / 2;
        const rocketX = cx + Math.cos(rocketA) * orbitRx;
        const rocketY = cy + Math.sin(rocketA) * orbitRy;
        // 진행 방향 (접선) — 로켓 코가 가리키도록
        const dRx = -orbitRx * Math.sin(rocketA);
        const dRy =  orbitRy * Math.cos(rocketA);
        const headingDeg = Math.atan2(dRx, -dRy) * 180 / Math.PI;

        // 한 바퀴 끝 부근 (마지막 5%) — 외광 살짝 강조
        const sunGlowBoost = phase > 0.95 ? 0.3 : 0;
        // 표정 morphing — smoothstep으로 미소 빨리 도달 + 오래 유지
        const smoothstep = (e0, e1, x) => {
          const t = Math.max(0, Math.min(1, (x - e0) / (e1 - e0)));
          return t * t * (3 - 2 * t);
        };
        const sadIntensity = 1 - smoothstep(0, 0.18, phase);          // 0~18%: 찡그림
        const smileLevel = smoothstep(0.18, 0.55, phase);              // 18~55%: 미소 도달
        const mouthEndY = 82 + sadIntensity * 5;
        const mouthArcY = 82 + 22 * smileLevel;
        const smileEyeFade = smoothstep(0.45, 0.7, phase);             // 45~70%: 미소눈 도달
        const eyeFade = 1 - smileEyeFade;
        const cheekFade = smoothstep(0.4, 0.7, phase) * 0.7;

        // 활성 행성 (로켓에 가장 가까운)
        let nearestIdx = idx, minDist = Infinity;
        planets.forEach((p, i) => {
          const dx = p.x - rocketX, dy = p.y - rocketY;
          const d = dx * dx + dy * dy;
          if (d < minDist) { minDist = d; nearestIdx = i; }
        });

        return (
          <>
            {/* 별 배경 — 단순 white twinkle (균등 분산) */}
            <svg style={{
              position: 'absolute', inset: 0, width: '100%', height: '100%',
              zIndex: 1, pointerEvents: 'none',
            }} viewBox="0 0 1440 900" preserveAspectRatio="xMidYMid slice">
              {[
                // 상단 줄
                [120, 90, 1.2], [280, 60, 0.9], [440, 110, 1.3], [620, 70, 1],
                [800, 90, 1.2], [980, 60, 0.9], [1140, 110, 1.3], [1320, 80, 1],
                // 좌우 측면
                [80, 250, 1.1], [80, 420, 1.3], [80, 580, 1],
                [1380, 250, 1.1], [1380, 420, 1.3], [1380, 580, 1],
                // 하단 줄
                [120, 760, 1.1], [320, 800, 1.3], [560, 820, 1],
                [820, 820, 1.2], [1080, 800, 1.1], [1320, 760, 1.3],
              ].map(([x, y, r], i) => (
                <circle key={i} cx={x} cy={y} r={r}
                  fill="#ffffff"
                  opacity={0.55 + (i % 3) * 0.15}
                  style={{
                    animation: `starTwinkle ${2.5 + (i % 4)}s ease-in-out infinite`,
                    animationDelay: `${(i % 5) * 0.5}s`,
                  }} />
              ))}
            </svg>

            {/* 별 효과 레이어 — 균형 잡힌 4점 배치 */}
            <svg style={{
              position: 'absolute', inset: 0, width: '100%', height: '100%',
              zIndex: 1, pointerEvents: 'none',
            }} viewBox="0 0 1440 900" preserveAspectRatio="xMidYMid slice">
              {/* 큰 흰 펄스 별 — 4귀퉁이 균형 */}
              {[
                [200, 200], [1240, 200], [200, 700], [1240, 700],
              ].map(([x, y], i) => (
                <circle key={`pulse-${i}`} cx={x} cy={y} r={2}
                  fill="#ffffff"
                  style={{
                    animation: `starPulseSlow ${6 + (i % 2)}s ease-in-out infinite`,
                    animationDelay: `${i * 1.3}s`,
                    transformOrigin: `${x}px ${y}px`,
                  }} />
              ))}
              {/* accent sparkle — X자 배치 (대칭) */}
              {[
                [350, 320], [1090, 320], [350, 580], [1090, 580],
              ].map(([x, y], i) => (
                <g key={`acc-${i}`} style={{
                  animation: `accentStarTwinkle ${4 + (i % 3)}s ease-in-out infinite`,
                  animationDelay: `${i * 0.8}s`,
                  transformOrigin: `${x}px ${y}px`,
                }}>
                  <circle cx={x} cy={y} r={2.4} fill={accent} opacity={0.95} />
                  <line x1={x - 8} y1={y} x2={x + 8} y2={y}
                    stroke={accent} strokeWidth={0.8}
                    strokeLinecap="round" opacity={0.6} />
                  <line x1={x} y1={y - 8} x2={x} y2={y + 8}
                    stroke={accent} strokeWidth={0.8}
                    strokeLinecap="round" opacity={0.6} />
                </g>
              ))}
              {/* 슈팅 스타 — 2개 (시간차) */}
              {[
                { x: 150, y: 180, sx: 220, sy: 90, dur: 8, delay: 0 },
                { x: 1100, y: 720, sx: -200, sy: -100, dur: 9, delay: 4.5 },
              ].map((s, i) => (
                <g key={`shoot-${i}`} style={{
                  transformOrigin: `${s.x}px ${s.y}px`,
                  animation: `shootingStar ${s.dur}s ease-out infinite`,
                  animationDelay: `${s.delay}s`,
                  '--sx': `${s.sx}px`,
                  '--sy': `${s.sy}px`,
                }}>
                  <line x1={s.x} y1={s.y}
                    x2={s.x - s.sx * 0.18} y2={s.y - s.sy * 0.18}
                    stroke="#ffffff" strokeWidth={1.5}
                    strokeLinecap="round" opacity={0.55} />
                  <circle cx={s.x} cy={s.y} r={2} fill="#ffffff" />
                </g>
              ))}
            </svg>

            {/* 상단 메시지 — 은하수 sparkle halo 둘러쌈 */}
            <div style={{
              position: 'absolute', left: '50%', top: 145,
              transform: 'translateX(-50%)',
              zIndex: 6,
              display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
            }}>
              {/* 텍스트 뒤 은하수 halo + sparkle */}
              <svg style={{
                position: 'absolute', left: '50%', top: '50%',
                transform: 'translate(-50%, -50%)',
                width: 560, height: 200,
                pointerEvents: 'none', overflow: 'visible',
              }} viewBox="0 0 560 200">
                <defs>
                  <radialGradient id={`titleHalo-${idx}`} cx="50%" cy="50%" r="50%">
                    <stop offset="0%" stopColor={accent} stopOpacity={0.10} />
                    <stop offset="55%" stopColor={accent} stopOpacity={0.04} />
                    <stop offset="100%" stopColor={accent} stopOpacity={0} />
                  </radialGradient>
                </defs>
                {/* 부드러운 halo — opacity 낮춤 */}
                <ellipse cx="280" cy="100" rx="260" ry="80"
                  fill={`url(#titleHalo-${idx})`} />
                {/* 흩뿌린 sparkle 별 — 텍스트와 떨어지게 더 바깥쪽 */}
                {[
                  // 좌측 끝
                  [25, 50, 1.6], [45, 110, 1.2], [10, 90, 1.3],
                  [75, 25, 1.4], [85, 155, 1.1],
                  // 우측 끝
                  [535, 50, 1.6], [515, 110, 1.2], [550, 90, 1.3],
                  [485, 25, 1.4], [475, 155, 1.1],
                  // 상하 가운데 더 바깥
                  [200, 8, 1.3], [360, 8, 1.3],
                  [220, 185, 1.2], [340, 185, 1.2],
                ].map(([x, y, r], i) => (
                  <circle key={i} cx={x} cy={y} r={r}
                    fill={i % 3 === 0 ? '#ffffff' : accent}
                    opacity={0.6 + (i % 2) * 0.2}
                    style={{
                      animation: `starTwinkle ${2 + (i % 4)}s ease-in-out infinite`,
                      animationDelay: `${(i % 5) * 0.4}s`,
                    }} />
                ))}
                {/* accent X-sparkle 2개 — 좌우 끝에 (크기↑) */}
                {[
                  [10, 100], [550, 100],
                ].map(([x, y], i) => (
                  <g key={`x-${i}`} style={{
                    animation: `accentStarTwinkle ${4 + i}s ease-in-out infinite`,
                    animationDelay: `${i * 0.7}s`,
                    transformOrigin: `${x}px ${y}px`,
                  }}>
                    <circle cx={x} cy={y} r={2.2} fill={accent} opacity={0.95} />
                    <line x1={x - 8} y1={y} x2={x + 8} y2={y}
                      stroke={accent} strokeWidth={0.8}
                      strokeLinecap="round" opacity={0.65} />
                    <line x1={x} y1={y - 8} x2={x} y2={y + 8}
                      stroke={accent} strokeWidth={0.8}
                      strokeLinecap="round" opacity={0.65} />
                  </g>
                ))}
              </svg>
              <div style={{
                position: 'relative',
                fontFamily: FONT, fontSize: 10, fontWeight: 800,
                color: accent, letterSpacing: '0.24em',
                textTransform: 'uppercase',
              }}>My Track</div>
              <div style={{
                position: 'relative',
                fontFamily: FONT, fontSize: 30, fontWeight: 800,
                color: '#ffffff', letterSpacing: '-0.02em',
                textShadow: '0 2px 12px rgba(0,0,0,0.6)',
              }}>
                <span style={{ color: accent }}>{bot.sub}</span> Catcher
              </div>
            </div>

            {/* 큰 궤도 (점선 타원) */}
            <svg style={{
              position: 'absolute', left: cx - orbitRx - 60, top: cy - orbitRy - 60,
              width: (orbitRx + 60) * 2, height: (orbitRy + 60) * 2,
              zIndex: 2, pointerEvents: 'none', overflow: 'visible',
            }} viewBox={`0 0 ${(orbitRx + 60) * 2} ${(orbitRy + 60) * 2}`}>
              <ellipse cx={orbitRx + 60} cy={orbitRy + 60}
                rx={orbitRx} ry={orbitRy}
                fill="none" stroke="#ffffff" strokeWidth={1}
                opacity={0.18} strokeDasharray="2 8" />
            </svg>

            {/* 태양 → 활성 행성 에너지 빛줄기 (별도 SVG, 화면 전체 좌표) */}
            <svg style={{
              position: 'absolute', inset: 0, width: '100%', height: '100%',
              zIndex: 1, pointerEvents: 'none',
            }} viewBox="0 0 1440 900" preserveAspectRatio="xMidYMid slice">
              <defs>
                <linearGradient id={`energyBeam-${nearestIdx}`}
                  x1={cx} y1={cy}
                  x2={planets[nearestIdx].x} y2={planets[nearestIdx].y}
                  gradientUnits="userSpaceOnUse">
                  <stop offset="0%" stopColor="#ffb247" stopOpacity={0.55} />
                  <stop offset="100%" stopColor={planets[nearestIdx].color} stopOpacity={0.05} />
                </linearGradient>
              </defs>
              <line x1={cx} y1={cy}
                x2={planets[nearestIdx].x} y2={planets[nearestIdx].y}
                stroke={`url(#energyBeam-${nearestIdx})`}
                strokeWidth={3} strokeLinecap="round" opacity={0.7} />
            </svg>

            {/* 태양 — 중앙 */}
            <div style={{
              position: 'absolute', left: cx - 70, top: cy - 70,
              zIndex: 2, pointerEvents: 'none',
            }}>
              <div style={{
                position: 'absolute', left: -50, top: -50,
                width: 240, height: 240, borderRadius: '50%',
                background: 'radial-gradient(circle, #ffd370 0%, #ff8c42 40%, transparent 70%)',
                opacity: 0.55 + sunGlowBoost,
                animation: 'sunPulse 5s ease-in-out infinite',
                transition: 'opacity 0.8s ease',
              }} />
              <svg width="140" height="140" viewBox="0 0 140 140">
                <defs>
                  <radialGradient id="sunBody" cx="40%" cy="35%" r="60%">
                    <stop offset="0%" stopColor="#ffe9a0" />
                    <stop offset="60%" stopColor="#ffb247" />
                    <stop offset="100%" stopColor="#e8722a" />
                  </radialGradient>
                </defs>
                <circle cx={70} cy={70} r={sunR} fill="url(#sunBody)" />

                {/* 눈썹 — 처음에 살짝 찡그림 (phase < 0.18) */}
                <g opacity={sadIntensity * 0.55}>
                  <line x1="50" y1="48" x2="60" y2="53"
                    stroke="#7a4818" strokeWidth={2.2} strokeLinecap="round" />
                  <line x1="80" y1="53" x2="90" y2="48"
                    stroke="#7a4818" strokeWidth={2.2} strokeLinecap="round" />
                </g>

                {/* 둥근 눈 — phase < 0.6 */}
                <g opacity={eyeFade}>
                  <circle cx={56} cy={60} r={2.6} fill="#7a4818" />
                  <circle cx={84} cy={60} r={2.6} fill="#7a4818" />
                </g>

                {/* 미소 눈 (눈웃음) — phase > 0.6 */}
                <g opacity={smileEyeFade}>
                  <path d="M 50,62 Q 56,54 62,62"
                    stroke="#7a4818" strokeWidth={2.8}
                    fill="none" strokeLinecap="round" />
                  <path d="M 78,62 Q 84,54 90,62"
                    stroke="#7a4818" strokeWidth={2.8}
                    fill="none" strokeLinecap="round" />
                </g>

                {/* 입 — phase에 따라 morph (처짐 → 직선 → 미소) */}
                <path d={`M 50,${mouthEndY} Q 70,${mouthArcY} 90,${mouthEndY}`}
                  stroke="#7a4818" strokeWidth={3}
                  fill="none" strokeLinecap="round" />

                {/* 발그레 볼터치 — phase 후반 */}
                <circle cx={48} cy={78} r={4.5} fill="#ff6b6b" opacity={cheekFade} />
                <circle cx={92} cy={78} r={4.5} fill="#ff6b6b" opacity={cheekFade} />
              </svg>
            </div>

            {/* 11개 행성 — 정적 (방문 중 행성만 강조) + 번호 표시 */}
            {planets.map((p, i) => {
              const isVisited = i === nearestIdx;
              const isActiveBot = i === idx;
              const highlight = isVisited;
              return (
                <div key={p.key} style={{
                  position: 'absolute',
                  left: p.x - p.size,
                  top: p.y - p.size,
                  width: p.size * 2, height: p.size * 2,
                  zIndex: 3,
                  filter: highlight
                    ? `drop-shadow(0 0 22px ${p.color})`
                    : `drop-shadow(0 2px 6px rgba(0,0,0,0.5))`,
                  cursor: 'pointer',
                  transition: 'filter 0.4s ease',
                }} onClick={() => { setIdx(i); setAutoPlay(false); }}>
                  <svg width={p.size * 2} height={p.size * 2}
                    viewBox={`0 0 ${p.size * 2} ${p.size * 2}`}>
                    <defs>
                      <radialGradient id={`planet-${i}`} cx="35%" cy="30%" r="65%">
                        <stop offset="0%" stopColor="#ffffff" stopOpacity={0.6} />
                        <stop offset="40%" stopColor={p.color} />
                        <stop offset="100%" stopColor={p.color} stopOpacity={0.65} />
                      </radialGradient>
                    </defs>
                    <circle cx={p.size} cy={p.size} r={p.size - 2}
                      fill={`url(#planet-${i})`}
                      stroke={INK} strokeWidth={1.5} opacity={0.95} />
                    {i === 5 && (
                      <ellipse cx={p.size} cy={p.size} rx={p.size + 10} ry={p.size * 0.28}
                        fill="none" stroke={p.color} strokeWidth={2.5} opacity={0.55}
                        transform={`rotate(-15 ${p.size} ${p.size})`} />
                    )}
                    <ellipse cx={p.size * 0.7} cy={p.size * 0.6} rx={p.size * 0.25} ry={p.size * 0.12}
                      fill="#ffffff" opacity={0.5} />
                    {/* 번호 — 행성 안에 (사이즈 캡 적용) */}
                    <text x={p.size} y={p.size + Math.min(p.size * 0.18, 7)}
                      fontSize={Math.min(p.size * 0.55, 18)}
                      fontWeight={600}
                      fill="#ffffff"
                      textAnchor="middle"
                      fontFamily={FONT}
                      opacity={highlight ? 1 : 0.72}
                      style={{
                        paintOrder: 'stroke',
                        stroke: 'rgba(0,0,0,0.22)',
                        strokeWidth: 0.5,
                      }}>{i + 1}</text>
                  </svg>
                </div>
              );
            })}

            {/* === 로켓 — 큰 타원 궤도를 차례로 돌며 모든 행성 방문 === */}
            <div style={{
              position: 'absolute',
              left: rocketX,
              top: rocketY,
              zIndex: 5,
              pointerEvents: 'none',
            }}>
              <div style={{
                transform: `translate(-50%, -50%) rotate(${headingDeg}deg)`,
              }}>
                <div style={{ position: 'relative', width: 80, height: 120 }}>
                  <svg viewBox="0 0 80 120" width={80} height={120}
                    style={{ overflow: 'visible' }}>
                    <g style={{
                      transformOrigin: '40px 96px',
                      animation: 'rocketFlame 0.25s ease-in-out infinite',
                    }}>
                      <path d="M 28,96 Q 31,114 40,120 Q 49,114 52,96 L 45,93 L 40,100 L 35,93 Z"
                        fill="#ff8c42" />
                      <path d="M 32,96 Q 33,110 40,116 Q 47,110 48,96 L 45,93 L 40,98 L 35,93 Z"
                        fill="#ffe9a0" />
                    </g>
                    <path d="M 14,72 L 24,68 L 24,92 L 14,96 Z"
                      fill={accent} stroke={INK} strokeWidth={2} strokeLinejoin="round" />
                    <path d="M 66,72 L 56,68 L 56,92 L 66,96 Z"
                      fill={accent} stroke={INK} strokeWidth={2} strokeLinejoin="round" />
                    <path d="M 24,40 Q 24,12 40,3 Q 56,12 56,40 L 56,94 Q 56,100 50,100 L 30,100 Q 24,100 24,94 Z"
                      fill="#ffffff"
                      stroke={INK} strokeWidth={2.2}
                      strokeLinejoin="round" />
                    <path d="M 24,40 Q 24,12 40,3 Q 56,12 56,40 Z"
                      fill={accent}
                      stroke={INK} strokeWidth={2.2}
                      strokeLinejoin="round" />
                    <circle cx={40} cy={54} r={16}
                      fill="#1a2347"
                      stroke={INK} strokeWidth={2.2} />
                  </svg>
                  <div style={{
                    position: 'absolute',
                    left: 40 - 16, top: 54 - 16,
                    width: 32, height: 32,
                    borderRadius: '50%',
                    overflow: 'hidden',
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                  }}>
                    {BotC && (
                      <div style={{ transform: 'scale(0.9) translateY(4px)' }}>
                        <BotC size={42} />
                      </div>
                    )}
                  </div>
                  <div style={{
                    position: 'absolute', left: '50%', top: 76,
                    transform: 'translateX(-50%)',
                    fontSize: 6.5, fontWeight: 800,
                    color: INK,
                    fontFamily: FONT, letterSpacing: '0.05em',
                    textAlign: 'center',
                    textTransform: 'uppercase',
                    whiteSpace: 'nowrap',
                    pointerEvents: 'none',
                    lineHeight: 1.15,
                  }}>
                    <span style={{
                      display: 'inline-block',
                      width: 5, height: 5, borderRadius: '50%',
                      background: accent,
                      marginRight: 3,
                      verticalAlign: 'middle',
                      boxShadow: `0 0 4px ${accent}`,
                    }} />{bot.sub}<br/><span style={{
                      fontSize: 5, color: accent, letterSpacing: '0.18em'
                    }}>CATCHER</span></div>
                </div>
              </div>
            </div>

            {/* 하단 11 봇 셀렉터 */}
            <div style={{
              position: 'absolute', bottom: 24, left: '50%',
              transform: 'translateX(-50%)',
              display: 'flex', gap: 14, alignItems: 'flex-end',
              zIndex: 6, fontFamily: FONT,
            }}>
              {BOTS.map((b, i) => {
                const BC = b.C;
                const active = i === idx;
                return (
                  <button key={b.key} onClick={() => { setIdx(i); setAutoPlay(false); }}
                    style={{
                      background: 'transparent', border: 0, padding: 4,
                      cursor: 'pointer', display: 'flex', flexDirection: 'column',
                      alignItems: 'center', gap: 4,
                      transform: active ? 'translateY(-4px)' : 'translateY(0)',
                      transition: 'transform 0.2s',
                    }}>
                    <div style={{
                      width: 44, height: 48,
                      filter: active ? `drop-shadow(0 4px 14px ${b.color})` : 'none',
                      opacity: active ? 1 : 0.62,
                      transform: active ? 'scale(1.15)' : 'scale(1)',
                      transition: 'transform 0.2s, opacity 0.2s, filter 0.2s',
                    }}>
                      {BC && <BC size={42} />}
                    </div>
                    <div style={{
                      fontSize: 10, fontWeight: active ? 800 : 600,
                      color: active ? b.color : '#ffffff',
                      opacity: active ? 1 : 0.6,
                      letterSpacing: '0.06em',
                      textTransform: 'uppercase',
                    }}>{b.sub}</div>
                  </button>
                );
              })}
            </div>
          </>
        );
      })()}
      {/* PAUSE/AUTO 토글 — 좌하단 (셀렉터와 겹치지 않게) */}
      <button onClick={() => setAutoPlay(!autoPlay)}
        style={{
          position: 'absolute', bottom: 28, left: 28, zIndex: 7,
          padding: '9px 16px', borderRadius: 999,
          background: autoPlay ? 'rgba(255,255,255,0.15)' : '#ffffff',
          color: autoPlay ? '#ffffff' : '#1f1d1a',
          border: autoPlay ? '1.5px solid rgba(255,255,255,0.35)' : '0',
          fontSize: 11, fontWeight: 800, cursor: 'pointer',
          fontFamily: FONT, letterSpacing: '0.14em',
          backdropFilter: 'blur(6px)',
          textTransform: 'uppercase',
        }}>{autoPlay
          ? (lang === 'en' ? '⏸ Pause' : '⏸ 정지')
          : (lang === 'en' ? '▶ Auto' : '▶ 자동')}</button>
    </div>
  );
}

Object.assign(window, {
  TalkCatcherHero, BostonNeuroMindHero, NeuroCatchersHero, ModalityCatcherHero,
  OfflineBookingCard, BookingModal, TrackCatcherSession,
});
