// Shared data & utility components for the welcome page variants.
// Exposed on `window` so each variant script can read them.

const COLOR_PRESETS = [
{ id: 'void', name: 'Abyss', bg: '#0a0a14', accent: '#818cf8', text: '#f8fafc' },
{ id: 'arctic', name: 'Frost', bg: '#0c1524', accent: '#38bdf8', text: '#e0f2fe' },
{ id: 'ember', name: 'Blaze', bg: '#1a0c08', accent: '#f97316', text: '#fff7ed' },
{ id: 'forest', name: 'Grove', bg: '#0a1a0e', accent: '#22c55e', text: '#f0fdf4' },
{ id: 'neon', name: 'Cyan', bg: '#0a0e1a', accent: '#22d3ee', text: '#e0fcff' },
{ id: 'rose', name: 'Bloom', bg: '#1a0a14', accent: '#f472b6', text: '#fdf2f8' },
{ id: 'midnight', name: 'Indigo', bg: '#08082a', accent: '#6366f1', text: '#eef2ff' },
{ id: 'mono', name: 'Slate', bg: '#121212', accent: '#a0a0a0', text: '#e8e8e8' },
{ id: 'sunset', name: 'Crimson', bg: '#1a0e10', accent: '#e11d48', text: '#ffe4e6' },
{ id: 'ocean', name: 'Tidal', bg: '#08141e', accent: '#0891b2', text: '#cffafe' },
{ id: 'lavender', name: 'Violet', bg: '#14101e', accent: '#a78bfa', text: '#ede9fe' },
{ id: 'copper', name: 'Amber', bg: '#1a1410', accent: '#d97706', text: '#fef3c7' }];


// Brand tokens pulled directly from editor-sidebar.js
const BRAND = {
  c1: '#146ef5',
  c2: '#3b89ff',
  text: '#080808',
  sub: '#5a5a5a',
  dim: '#ababab',
  border: '#d8d8d8',
  card: '#fff',
  bg: '#fff',
  soft: '#f4f4f4'
};

// Brand wordmark + Chroma logo mark.
// Brand mark — chat bubble face on white, displayed inside a rounded-square
// frame so it has the same silhouette as the previous placeholder logo.
function ChromaLogo({ size = 28 }) {
  return (
    <img
      src="assets/logo.png"
      width={size}
      height={size}
      alt="Chroma AI"
      style={{
        width: size,
        height: size,
        borderRadius: '22%',
        display: 'block',
        // Subtle hairline border keeps the white logo readable on dark glass nav.
        boxShadow: '0 0 0 1px rgba(255,255,255,0.08)',
      }}
    />
  );
}

// Keep ATELogo as an alias for any legacy references.
const ATELogo = ChromaLogo;

// Brand icons — recognisable approximations of the real product marks.
// ChatGPT: OpenAI's interlaced trefoil on the brand green.
// Claude:  Anthropic's warm-coral 4-point starburst.
// Gemini:  Google's blue→purple→pink sparkle (concave 4-point star).
function PlatformIcon({ name, size = 28 }) {
  const props = { width: size, height: size, viewBox: '0 0 32 32', fill: 'none' };
  if (name === 'chatgpt') {
    // OpenAI 의 공식 ChatGPT 마크 (single-path). 배경 없음, 검은색 단일색.
    // (흰 배경 섹션에서 흰색이면 안 보여서 검정으로 교체 — 2026-07-03)
    // viewBox 만 24x24 로 별도 — 다른 아이콘과 시각적 크기는 size prop 로 동기화됨.
    return (
      <svg width={size} height={size} viewBox="0 0 24 24" fill="#000">
        <path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.073zM13.2599 22.4106a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zM3.6048 18.3214a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1353-1.6288zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.8956zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863L6.2812 11.6945a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"/>
      </svg>
    );
  }
  if (name === 'claude') {
    // 코랄 12-ray 스타버스트 — Anthropic 의 최신 Claude 브랜드 마크. 배경 사각형 없음.
    const rays = [];
    for (let i = 0; i < 12; i++) {
      rays.push(
        <path
          key={i}
          d="M -1.4 -2.5 L 1.4 -2.5 L 0.7 -14.5 L -0.7 -14.5 Z"
          transform={`rotate(${i * 30})`}
        />
      );
    }
    return (
      <svg {...props}>
        <g fill="#D97757" transform="translate(16 16)">{rays}</g>
      </svg>
    );
  }
  if (name === 'gemini') {
    // 4-point sparkle + 무지개 conic gradient (Google 의 최신 Gemini 마크).
    // SVG 는 conic-gradient 미지원이라 div + CSS mask 로 sparkle 모양만 잘라낸다.
    const mask = `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><path d='M 16 2 Q 16 14 2 16 Q 16 18 16 30 Q 16 18 30 16 Q 16 14 16 2 Z' fill='black'/></svg>")`;
    return (
      <div
        style={{
          width: size,
          height: size,
          display: 'inline-block',
          flexShrink: 0,
          background: 'conic-gradient(from 0deg at 50% 50%, #EA4335 0deg, #4285F4 90deg, #34A853 180deg, #FBBC04 270deg, #EA4335 360deg)',
          WebkitMaskImage: mask,
          maskImage: mask,
          WebkitMaskRepeat: 'no-repeat',
          maskRepeat: 'no-repeat',
          WebkitMaskSize: 'contain',
          maskSize: 'contain',
        }}
      />
    );
  }
  return null;
}

// i18n strings — Korean primary, EN/中文 secondary
const I18N = {
  ko: {
    nav_features: '기능', nav_presets: '프리셋', nav_pricing: '플랜', nav_faq: 'FAQ',
    nav_upgrade: 'Pro로 업그레이드',
    nav_login: '로그인', nav_mypage: '마이페이지',
    brand_name: 'Chroma AI',
    brand_tagline: '당신의 AI를, 당신답게',
    eyebrow: '설치 완료 · v0.1.0',
    hero_h1_a: 'AI 챗봇을\n당신의 공간으로.',
    hero_h1_b: '당신의 AI,\n당신만의 AI.',
    hero_sub: 'Claude · ChatGPT · Gemini, 당신의 AI를 당신만의 색으로.\n사이드바 하나로 AI 챗봇을 자유롭게 커스터마이즈하세요.',
    cta_primary: '다운로드',
    cta_secondary: '테마 적용해주기',
    scroll_hint: '아래로 스크롤하기',
    section_compare: '같은 챗봇,\n전혀 다른 공간',
    section_compare_sub: '한 번의 클릭으로 익숙한 화면이 새로워집니다',
    before: 'Before',
    after: 'After - Chroma AI 적용',
    section_platforms: '지원 플랫폼',
    section_platforms_sub: '지금 바로 사용 가능',
    section_presets: '당신만을 위한 12종의 무료 프리미엄 프리셋',
    section_presets_sub: '클릭 한 번으로 배경·강조·텍스트 색상이 한꺼번에 바뀝니다',
    section_steps: '3단계로 시작하기',
    step1_t: '확장 핀 고정',
    step1_d: '브라우저 우측 상단 퍼즐 아이콘에서 AI Theme Engine을 핀으로 고정하세요.',
    step2_t: '챗봇 페이지 열기',
    step2_d: 'ChatGPT, Claude, Gemini 어느 곳이든 평소처럼 접속합니다.',
    step3_t: '아이콘 클릭',
    step3_d: '브라우저 우측 상단에 핀 고정한 Chroma AI 아이콘을 클릭하면 페이지 우측에 에디터 사이드바가 슬라이드 인.',
    section_plan: '두 가지 플랜',
    plan_free: 'Free',
    plan_free_price: '₩0',
    plan_free_desc: '핵심 기능 무료 사용',
    plan_pro: 'Pro',
    plan_pro_price: '$0/월',
    plan_pro_regular_price: '$2.99/월',
    plan_pro_desc: '기간 한정 Pro 플랜 무료 배포 (결제 불필요)',
    plan_promo_badge: '기간 한정 무료',
    plan_promo_off: '100% OFF',
    plan_promo_note: '정규가 $2.99/월 → 현재 회원가입 시 완전 무료',
    plan_current: '지금 사용 중',
    plan_upgrade: 'Pro 플랜 무료로 받기',
    plan_pro_active: 'Pro 혜택 적용됨',
    f_presets: '12종 컬러 프리셋',
    f_solid: '단색 그라디언트 배경',
    f_overlay: '색상 오버레이',
    f_glass: '글라스 효과 (블러)',
    f_media5: '미디어 배경 (이미지·영상) 5회',
    f_media_unlimited: '미디어 배경 무제한',
    f_filter: '배경 필터 (흑백·세피아·비비드)',
    f_pro_editor: 'PRO 에디터 — 라이브 프리뷰',
    f_fonts: '맞춤형 폰트',
    f_support: '커스텀 테마 프리셋 이용 가능',
    badge_new: 'NEW',
    badge_beta: 'BETA',
    hero_badge: '신규 · 커스텀 테마 프리셋',
    section_custom: '커스텀 테마 프리셋',
    section_custom_sub: '익숙한 그 앱처럼 — 메신저·시트 스타일로 챗봇 레이아웃을 바꿔보세요',
    custom_msg_name: 'Messenger',
    custom_msg_desc: '메신저 앱처럼 — 사이드 레일과 말풍선 중심의 친근한 대화 레이아웃',
    custom_sheet_name: 'Sheet',
    custom_sheet_desc: '스프레드시트처럼 — 정돈된 그리드와 셀 기반의 깔끔한 집중 레이아웃',
    footer_made: 'Copyright © ComfortOne Co.,Ltd. All rights reserved.',
    footer_privacy: '개인정보처리방침',
    footer_terms: '이용약관',
    footer_support: '지원',
    footer_trademark: 'ChatGPT · Claude · Gemini는 각 권리자의 상표입니다. Chroma AI는 어떤 회사와도 제휴되지 않은 독립적인 외부 도구입니다.',
    open_sidebar_hint: '당신의 챗봇에게 선물하세요.',
    footer_cta_a: '지금 바로',
    footer_cta_b: '새로운 분위기',
    footer_cta_c: '를',
    compare_cap_before: '',
    compare_cap_after: '',
    chat_titles: ['아이디어 정리', '코드 리뷰', '여행 계획', '독서 메모', '주간 보고서'],
    chat_new: '새 채팅',
    chat_search: '채팅 검색',
    chat_recent: '최근 항목',
    chat_user_1: '오늘 일정 정리해줘 — 회의 3개랑 점심 약속 있어.',
    chat_bot: '오늘 일정을 정리해드릴게요. 우선순위 기준으로 묶었습니다.',
    chat_sched: ['• 10:00 디자인 리뷰 (45분)', '• 12:30 점심 — 카페 로비', '• 14:00 PRD 싱크 (1시간)', '• 16:00 1:1 (30분)'],
    chat_user_2: '완벽해, 고마워!',
    chat_input: '무엇이든 물어보세요…'
  },
  en: {
    nav_features: 'Features', nav_presets: 'Presets', nav_pricing: 'Plans', nav_faq: 'FAQ',
    nav_upgrade: 'Upgrade to Pro',
    nav_login: 'Sign in', nav_mypage: 'My Page',
    brand_name: 'Chroma AI',
    brand_tagline: 'Customize your AI',
    eyebrow: 'Installed · v0.1.0',
    hero_h1_a: 'Make any AI chat\nfeel like yours.',
    hero_h1_b: 'Your AI,\nFit Your Imagination',
    hero_sub: 'Customize your AI — Claude, ChatGPT, Gemini\nBackgrounds, colors and marvelous effects, all from a single sidebar',
    cta_primary: 'Download',
    cta_secondary: 'Apply theme',
    scroll_hint: 'Scroll down',
    section_compare: 'Same chatbot,\nA whole new space',
    section_compare_sub: 'One click turns the familiar into something new',
    before: 'Before',
    after: 'After — Applying Chroma AI',
    section_platforms: 'Supported Platforms',
    section_platforms_sub: 'Available today',
    section_presets: '12 free Premium presets',
    section_presets_sub: 'Background, accent and text colors swap together in one click',
    section_steps: 'Get started in 3 steps',
    step1_t: 'Pin the extension',
    step1_d: 'Click the puzzle icon in the top right of your browser and pin AI Theme Engine.',
    step2_t: 'Open any chatbot',
    step2_d: 'Visit ChatGPT, Claude or Gemini as you normally would.',
    step3_t: 'Click the icon',
    step3_d: 'Click the pinned Chroma AI icon in the top right of your browser and the editor sidebar slides in from the right.',
    section_plan: 'Two simple plans',
    plan_free: 'Free',
    plan_free_price: '$0',
    plan_free_desc: 'Core features, free forever',
    plan_pro: 'Pro',
    plan_pro_price: '$0/mo',
    plan_pro_regular_price: '$2.99/mo',
    plan_pro_desc: 'Limited time free distribution (No payment required)',
    plan_promo_badge: 'FREE PROMO',
    plan_promo_off: '100% OFF',
    plan_promo_note: 'Regular $2.99/mo → Free for a limited time',
    plan_current: 'Current plan',
    plan_upgrade: 'Get Pro for Free',
    plan_pro_active: 'Pro benefit active',
    f_presets: '12 color presets',
    f_solid: 'Solid + gradient backgrounds',
    f_overlay: 'Color overlay',
    f_glass: 'Glass blur effect',
    f_media5: 'Media backgrounds (5 changes)',
    f_media_unlimited: 'Unlimited media backgrounds',
    f_filter: 'Background filters (gray · sepia · vivid)',
    f_pro_editor: 'PRO editor — live preview',
    f_fonts: 'Custom fonts',
    f_support: 'Custom theme presets available',
    badge_new: 'NEW',
    badge_beta: 'BETA',
    hero_badge: 'New · Custom theme presets',
    section_custom: 'Custom theme presets',
    section_custom_sub: 'Like the apps you know — re-skin your chatbot as a messenger or a sheet',
    custom_msg_name: 'Messenger',
    custom_msg_desc: 'Messenger-style — a friendly layout built around a side rail and chat bubbles',
    custom_sheet_name: 'Sheet',
    custom_sheet_desc: 'Spreadsheet-style — a focused, grid-and-cell layout that keeps things tidy',
    footer_made: 'Copyright © ComfortOne Co.,Ltd. All rights reserved.',
    footer_privacy: 'Privacy',
    footer_terms: 'Terms',
    footer_support: 'Support',
    footer_trademark: 'ChatGPT, Claude, and Gemini are trademarks of their respective owners. Chroma AI is an independent third-party tool, not affiliated with any of these companies.',
    open_sidebar_hint: 'A gift for your chatbot.',
    footer_cta_a: 'Start the',
    footer_cta_b: 'new mood',
    footer_cta_c: ', now',
    compare_cap_before: '',
    compare_cap_after: '',
    chat_titles: ['Idea notes', 'Code review', 'Trip plan', 'Reading log', 'Weekly report'],
    chat_new: 'New chat',
    chat_search: 'Search chats',
    chat_recent: 'Recent',
    chat_user_1: 'Summarize my day — 3 meetings and lunch.',
    chat_bot: 'Here’s your day, grouped by priority.',
    chat_sched: ['• 10:00 Design review (45m)', '• 12:30 Lunch — Café Lobby', '• 14:00 PRD sync (1h)', '• 16:00 1:1 (30m)'],
    chat_user_2: 'Perfect, thanks!',
    chat_input: 'Ask anything…'
  }
};

// Detect initial UI language. A stored preference (shared with the legal /
// upgrade pages via legal.js, same `chroma-lang` key) wins, so the language
// choice stays in sync when navigating between the React landing page and the
// static legal/upgrade pages. Falls back to the browser locale, then English.
function detectInitialLang() {
  try {
    const stored = localStorage.getItem('chroma-lang');
    if (stored === 'ko' || stored === 'en') return stored;
  } catch {/* storage unavailable */}
  try {
    const langs = navigator.languages && navigator.languages.length ?
    navigator.languages :
    [navigator.language || 'en'];
    for (const l of langs) {
      const tag = String(l).toLowerCase();
      if (tag.startsWith('ko')) return 'ko';
      if (tag.startsWith('en')) return 'en';
    }
  } catch {/* SSR or unavailable */}
  return 'en';
}

// ChatGPT-ish mockup component used for Before/After comparison.
// `theme` controls colors. When `themed`, applies a wallpaper-style bg.
function ChatGPTMockup({ themed = false, preset, scale = 1, width = 520, height = 340, lang = 'ko' }) {
  const p = preset || COLOR_PRESETS[1]; // Frost
  const tt = I18N[lang] || I18N.ko;
  const baseBg = themed ? p.bg : '#ffffff';
  const sidebarBg = themed ? 'transparent' : '#f9f9f9';
  const textCol = themed ? p.text : '#0d0d0d';
  const subText = themed ? `${p.text}b3` : '#5d5d5d';
  const bubbleUser = themed ? `${p.accent}33` : '#e9e9e9';
  const bubbleBot = themed ? 'rgba(255,255,255,0.04)' : 'transparent';
  const inputBg = themed ? 'rgba(255,255,255,0.06)' : '#f4f4f4';
  const borderC = themed ? 'rgba(255,255,255,0.08)' : '#e7e7e7';

  const wallpaperBg = themed ? `
    radial-gradient(ellipse 80% 60% at 15% 10%, ${p.accent}33 0%, transparent 55%),
    radial-gradient(ellipse 60% 80% at 85% 90%, ${p.accent}22 0%, transparent 55%),
    radial-gradient(circle at 50% 40%, rgba(255,255,255,0.04) 0%, transparent 40%),
    linear-gradient(160deg, ${p.bg} 0%, ${p.accent}1f 35%, ${p.bg} 65%, ${p.accent}14 100%)
  ` : '#ffffff';

  const chats = [tt.chat_new, ...tt.chat_titles];
  const bodyFont = lang === 'ko' ? "'Pretendard', system-ui, sans-serif" : "'Inter', 'Pretendard', system-ui, sans-serif";

  return (
    <div style={{
      width, height, borderRadius: 14, overflow: 'hidden',
      background: wallpaperBg, border: `1px solid ${themed ? '#1f2a3a' : '#e5e5e5'}`,
      boxShadow: themed ? '0 24px 60px rgba(0,0,0,0.35)' : '0 12px 40px rgba(0,0,0,0.08)',
      fontFamily: bodyFont, display: 'flex',
      transform: `scale(${scale})`, transformOrigin: 'top left'
    }}>
      {/* Sidebar */}
      <div style={{ width: 148, background: sidebarBg, padding: '14px 10px', display: 'flex', flexDirection: 'column', gap: 8, borderRight: `1px solid ${borderC}`, flexShrink: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '6px 8px', borderRadius: 6, background: themed ? 'rgba(255,255,255,0.08)' : '#fff', backdropFilter: themed ? 'blur(22px) saturate(160%)' : 'none', border: themed ? 'none' : `1px solid ${borderC}` }}>
          <div style={{ width: 14, height: 14, borderRadius: 3, background: themed ? p.accent : '#0d0d0d' }} />
          <div style={{ fontSize: 10, color: textCol, fontWeight: 600, whiteSpace: 'nowrap' }}>{tt.chat_new}</div>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '6px 8px', borderRadius: 6, color: subText, fontSize: 10, whiteSpace: 'nowrap' }}>
          <svg width={10} height={10} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="11" cy="11" r="8" /><path d="M21 21l-4.3-4.3" /></svg>
          {tt.chat_search}
        </div>
        <div style={{ fontSize: 8, fontWeight: 600, color: subText, padding: '8px 8px 4px', textTransform: 'uppercase', letterSpacing: '.08em' }}>{tt.chat_recent}</div>
        {tt.chat_titles.map((c, i) =>
        <div key={i} style={{ padding: '4px 8px', borderRadius: 4, fontSize: 10, color: i === 0 ? textCol : subText, fontWeight: i === 0 ? 500 : 400, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{c}</div>
        )}
      </div>

      {/* Main */}
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', position: 'relative', minWidth: 0 }}>
        {/* Header */}
        <div style={{ padding: '12px 16px', borderBottom: `1px solid ${borderC}`, display: 'flex', alignItems: 'center', justifyContent: 'space-between', backdropFilter: themed ? 'blur(7px)' : 'none' }}>
          <div style={{ fontSize: 11, fontWeight: 600, color: textCol }}>ChatGPT </div>
          <div style={{ width: 18, height: 18, borderRadius: '50%', background: themed ? p.accent : '#0d0d0d' }} />
        </div>

        {/* Messages */}
        <div style={{ flex: 1, padding: '14px 16px', display: 'flex', flexDirection: 'column', gap: 10, fontSize: 10 }}>
          <div style={{ alignSelf: 'flex-end', maxWidth: '75%', padding: '8px 12px', borderRadius: 12, background: bubbleUser, color: textCol }}>
            {tt.chat_user_1}
          </div>
          <div style={{ alignSelf: 'flex-start', maxWidth: '85%', padding: '8px 12px', borderRadius: 12, background: bubbleBot, color: textCol, lineHeight: 1.5 }}>
            {tt.chat_bot}
            <div style={{ marginTop: 6, fontSize: 9, color: subText }}>
              {tt.chat_sched.map((line, i) =>
              <div key={i}>{line}</div>
              )}
            </div>
          </div>
          <div style={{ alignSelf: 'flex-end', maxWidth: '60%', padding: '8px 12px', borderRadius: 12, background: bubbleUser, color: textCol }}>
            {tt.chat_user_2}
          </div>
        </div>

        {/* Input */}
        <div style={{ padding: '12px 16px' }}>
          <div style={{
            background: inputBg,
            border: `1px solid ${borderC}`,
            borderRadius: 14, padding: '10px 14px',
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            fontSize: 10, color: subText,
            backdropFilter: themed ? 'blur(8px)' : 'none'
          }}>
            <span>{tt.chat_input}</span>
            <div style={{ width: 24, height: 24, borderRadius: '50%', background: themed ? p.accent : '#0d0d0d', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <svg width={10} height={10} viewBox="0 0 24 24" fill="none" stroke={themed ? p.bg : '#fff'} strokeWidth="2"><path d="M5 12l14 0M13 6l6 6-6 6" /></svg>
            </div>
          </div>
        </div>
      </div>
    </div>);

}

// Language switcher (KO / EN)
function LangSwitch({ value, onChange, theme = 'light' }) {
  const langs = [['ko', '한국어'], ['en', 'English']];
  const isDark = theme === 'dark';
  return (
    <div style={{
      display: 'flex', gap: 2, padding: 3,
      background: isDark ? 'rgba(255,255,255,0.06)' : '#f4f4f4',
      borderRadius: 8,
      border: isDark ? '1px solid rgba(255,255,255,0.1)' : `1px solid ${BRAND.border}`
    }}>
      {langs.map(([id, label]) =>
      <button key={id} onClick={() => onChange(id)} style={{
        padding: '5px 11px', border: 'none',
        background: value === id ? isDark ? 'rgba(255,255,255,0.15)' : '#fff' : 'transparent',
        color: value === id ? isDark ? '#fff' : BRAND.c1 : isDark ? 'rgba(255,255,255,0.65)' : BRAND.sub,
        fontSize: 11, fontWeight: 600, fontFamily: 'Pretendard,system-ui,sans-serif',
        borderRadius: 6, cursor: 'pointer', whiteSpace: 'nowrap',
        boxShadow: value === id ? isDark ? 'none' : '0 1px 2px rgba(0,0,0,0.04)' : 'none',
        letterSpacing: id === 'en' ? '.04em' : 0
      }}>{label}</button>
      )}
    </div>);

}

// Keyboard combo chip — used in hero hint
function Kbd({ children, theme = 'light' }) {
  const isDark = theme === 'dark';
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      minWidth: 22, height: 22, padding: '0 6px',
      fontSize: 11, fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',
      fontWeight: 600,
      color: isDark ? '#fff' : BRAND.text,
      background: isDark ? 'rgba(255,255,255,0.12)' : '#fff',
      border: isDark ? '1px solid rgba(255,255,255,0.18)' : `1px solid ${BRAND.border}`,
      borderRadius: 5,
      boxShadow: isDark ? 'inset 0 -1px 0 rgba(0,0,0,0.3)' : '0 1px 0 #d8d8d8, inset 0 -1px 0 rgba(0,0,0,0.04)'
    }}>{children}</span>);

}

// Compact preset swatch matching the one in editor-sidebar.js
function PresetSwatch({ p, size = 64, label = true, onHover }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 6, alignItems: 'center' }}
    onMouseEnter={onHover}>
      <div style={{
        width: size, height: size, borderRadius: size * 0.18,
        background: p.bg,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        position: 'relative', overflow: 'hidden',
        boxShadow: '0 4px 16px rgba(0,0,0,0.08)'
      }}>
        <span style={{ color: p.text, fontSize: size * 0.32, fontWeight: 600, letterSpacing: '-0.02em' }}>Aa</span>
        <span style={{ position: 'absolute', left: 6, right: 6, bottom: 5, height: 3, borderRadius: 2, background: p.accent }} />
      </div>
      {label && <span style={{ fontSize: 11, color: BRAND.sub, fontWeight: 500 }}>{p.name}</span>}
    </div>);

}

Object.assign(window, {
  COLOR_PRESETS, BRAND, I18N,
  ATELogo, ChromaLogo, PlatformIcon, ChatGPTMockup, LangSwitch, Kbd, PresetSwatch,
  Reveal, detectInitialLang
});

// ─── Reveal — fade + lift on scroll into view ────────────────────────────
// Wrap any element; defaults: 24px lift, 700ms, easeOutCubic-ish.
// Pass `delay` (ms) for staggered children. Once visible, stays visible.
function Reveal({
  children,
  delay = 0,
  duration = 700,
  y = 24,
  threshold = 0.12,
  as: As = 'div',
  style,
  ...rest
}) {
  const ref = React.useRef(null);
  const [visible, setVisible] = React.useState(false);

  React.useEffect(() => {
    const el = ref.current;
    if (!el) return;
    // Respect prefers-reduced-motion — show immediately, no transform/transition.
    const prefersReduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    if (prefersReduce) {setVisible(true);return;}

    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            setVisible(true);
            io.unobserve(e.target);
          }
        });
      },
      { threshold, rootMargin: '0px 0px -40px 0px' }
    );
    io.observe(el);
    return () => io.disconnect();
  }, [threshold]);

  return (
    <As
      ref={ref}
      style={{
        opacity: visible ? 1 : 0,
        transform: visible ? 'translateY(0)' : `translateY(${y}px)`,
        transition: `opacity ${duration}ms cubic-bezier(0.16,1,0.3,1) ${delay}ms, transform ${duration}ms cubic-bezier(0.16,1,0.3,1) ${delay}ms`,
        willChange: visible ? 'auto' : 'opacity, transform',
        ...style
      }}
      {...rest}>
      
      {children}
    </As>);

}