/* =====================================================================
   TarotModule.jsx — 타로 전체 플로우 (최고존엄 인터랙티브 버전)
   ① 꿈 입력 → ② 로딩 → ③ 무료 결과 → ④ 프리미엄 게이트
   → ⑤ 광고/결제 → ⑥ 폼 입력 → ⑦ 22장 카드 뽑기 인터랙션
   → ⑧ AI 리딩 생성 → ⑨ 결과 (로컬 카드 이미지 + 커스텀 AI 운명 카드)

   ★ 로컬 카드 이미지 경로: /images/tarot/{slug}.png
     예) The Hermit → /images/tarot/the_hermit.png
     파일이 없으면 Pollinations AI 이미지로 자동 폴백됩니다.
===================================================================== */
const _T = React;
const { useState, useEffect, useRef, useMemo } = _T;

/* ────────────────────────────────────────────────────────────────────
   상수 — 22 메이저 + 56 마이너 = 78장 풀 덱
───────────────────────────────────────────────────────────────────── */
const MAJOR_ARCANA = [
  { id:0,  name:'The Fool',           nameKo:'바보',            slug:'the_fool' },
  { id:1,  name:'The Magician',       nameKo:'마법사',           slug:'the_magician' },
  { id:2,  name:'The High Priestess', nameKo:'여사제',           slug:'the_high_priestess' },
  { id:3,  name:'The Empress',        nameKo:'여황제',           slug:'the_empress' },
  { id:4,  name:'The Emperor',        nameKo:'황제',             slug:'the_emperor' },
  { id:5,  name:'The Hierophant',     nameKo:'교황',             slug:'the_hierophant' },
  { id:6,  name:'The Lovers',         nameKo:'연인',             slug:'the_lovers' },
  { id:7,  name:'The Chariot',        nameKo:'전차',             slug:'the_chariot' },
  { id:8,  name:'Strength',           nameKo:'힘',               slug:'strength' },
  { id:9,  name:'The Hermit',         nameKo:'은둔자',           slug:'the_hermit' },
  { id:10, name:'Wheel of Fortune',   nameKo:'운명의 수레바퀴',  slug:'wheel_of_fortune' },
  { id:11, name:'Justice',            nameKo:'정의',             slug:'justice' },
  { id:12, name:'The Hanged Man',     nameKo:'매달린 남자',      slug:'the_hanged_man' },
  { id:13, name:'Death',              nameKo:'변화',             slug:'death' },
  { id:14, name:'Temperance',         nameKo:'절제',             slug:'temperance' },
  { id:15, name:'The Devil',          nameKo:'악마',             slug:'the_devil' },
  { id:16, name:'The Tower',          nameKo:'탑',               slug:'the_tower' },
  { id:17, name:'The Star',           nameKo:'별',               slug:'the_star' },
  { id:18, name:'The Moon',           nameKo:'달',               slug:'the_moon' },
  { id:19, name:'The Sun',            nameKo:'태양',             slug:'the_sun' },
  { id:20, name:'Judgement',          nameKo:'심판',             slug:'judgement' },
  { id:21, name:'The World',          nameKo:'세계',             slug:'the_world' }
];

/* 마이너 아르카나 56장 */
const _SUITS = [
  { en:'Wands',     ko:'완드',   prefix:'wands' },
  { en:'Cups',      ko:'컵',     prefix:'cups' },
  { en:'Swords',    ko:'소드',   prefix:'swords' },
  { en:'Pentacles', ko:'펜타클', prefix:'pentacles' }
];
const _PIPS = [
  { n:'Ace', ko:'에이스', slug:'ace' },
  ...Array.from({length:9},(_,i)=>({ n:String(i+2), ko:String(i+2), slug:String(i+2) })),
  { n:'Page',   ko:'시종', slug:'page' },
  { n:'Knight', ko:'기사', slug:'knight' },
  { n:'Queen',  ko:'여왕', slug:'queen' },
  { n:'King',   ko:'왕',   slug:'king' }
];
let _id = 22;
const MINOR_ARCANA = _SUITS.flatMap(s =>
  _PIPS.map(p => ({
    id: _id++,
    name:   p.n === 'Ace' ? `Ace of ${s.en}` : isNaN(Number(p.n)) ? `${p.n} of ${s.en}` : `${p.n} of ${s.en}`,
    nameKo: `${s.ko} ${p.ko}`,
    slug:   `${s.prefix}_${p.slug}`
  }))
);

const FULL_78_DECK = [...MAJOR_ARCANA, ...MINOR_ARCANA];

/* 로컬 이미지 경로 */
function getLocalCardPath(slug) { return `/images/tarot/${slug}.png`; }

/* 배열 셔플 */
function shuffleArr(arr) {
  const a = [...arr];
  for (let i = a.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}

/* ────────────────────────────────────────────────────────────────────
   유틸 — 커스텀 운명 카드 URL 생성
───────────────────────────────────────────────────────────────────── */
function buildCustomCardUrl(dreamText, zodiac, mood, name) {
  const raw    = (dreamText || '').trim().replace(/^[pP]\//, '');
  const zPart  = zodiac ? `,%20${encodeURIComponent(zodiac + ' zodiac celestial energy')}` : '';
  const mStyle = mood === 'good'
    ? 'luminous%20golden%20transcendent%20divine%20light,%20warm%20ethereal%20radiance,%20ascending%20cosmic%20energy'
    : 'mysterious%20dark%20cosmic%20void,%20deep%20indigo%20moonlight,%20haunting%20ethereal%20shadows,%20descending%20energy';
  return `https://image.pollinations.ai/p/flux/${encodeURIComponent(raw)},%20cinematic%20masterpiece%20custom%20tarot%20card${zPart},%20${mStyle},%20ornate%20art%20nouveau%20gold%20filigree%20borders,%20intricate%20celestial%20arcane%20symbols,%20surreal%20fantasy%20dreamscape,%20ultra%20detailed%208k,%20no%20text%20no%20letters%20no%20numbers%20no%20watermarks`;
}

/* ────────────────────────────────────────────────────────────────────
   유틸 — 뽑힌 카드 기반 AI 리딩 생성
───────────────────────────────────────────────────────────────────── */
async function generateReadingForPickedCards(dreamText, mood, lang, form, picked) {
  const isKo  = lang === 'ko';
  const name  = form.name.trim() || (isKo ? '소중한 분' : 'Dear Seeker');
  const zodiac = form.zodiac || 'Unknown';
  const past  = picked[0], pres = picked[1], fut = picked[2];

  const sys = isKo
    ? `당신은 대한민국 최고의 타로 마스터이자 칼 융 분析심리학 전문가입니다.
유저가 직접 선택한 카드:
• 과거 포지션: ${past.name} (${past.nameKo})
• 현재 포지션: ${pres.name} (${pres.nameKo})
• 미래 포지션: ${fut.name} (${fut.nameKo})

위 카드들과 ${name}님의 ${zodiac} 별자리, 꿈 내용을 심층 분析하여 극존칭 존댓말 신탁 어조로 압도적인 분량의 리딩을 생성하세요.
각 sections의 content는 반드시 250자 이상이어야 하며, 지정된 카드명을 각 섹션 첫 문장에 반드시 언급해야 합니다.

반드시 아래 JSON만 반환:
{
  "title": "${name}님의 타로 신탁 (25자 이내)",
  "subtitle": "핵심 키워드 3개 · · ·",
  "sections": {
    "essence": {
      "title": "✦ 세 카드의 우주적 공명과 총운",
      "content": "250자 이상. ${name}님을 직접 호명하며 시작. ${zodiac}의 수호 에너지와 세 카드(${past.nameKo}·${pres.nameKo}·${fut.nameKo})가 형성하는 전체 운명 패턴 분析. 칼 융의 집단 무의식 관점 포함."
    },
    "pastCard": {
      "title": "✦ 과거 카드 — ${past.nameKo}",
      "content": "250자 이상. 첫 문장에 반드시 ${past.name}(${past.nameKo}) 카드명 언급. 이 카드의 도상이 꿈 장면과 공명하는 지점 구체적으로 서술. ${name}님의 삶의 뿌리와 현재 상황의 원인 분析."
    },
    "presentCard": {
      "title": "✦ 현재 카드 — ${pres.nameKo}",
      "content": "250자 이상. 첫 문장에 반드시 ${pres.name}(${pres.nameKo}) 카드명 언급. 현재 삶에서 작동하는 에너지 패턴. ${zodiac} 기운이 이 카드를 증폭하는 방식. ${name}님이 직면해야 할 진실."
    },
    "futureCard": {
      "title": "✦ 미래 신탁 — ${fut.nameKo}",
      "content": "300자 이상. 첫 문장에 반드시 ${fut.name}(${fut.nameKo}) 카드명 언급. ① 행운 방위 1개(동/서/남/북 중) ② 행운 숫자 3개와 각 의미 ③ 조심할 달 2개 ④ 일상 액막이 2가지. ${name}님께 진심 어린 격려로 마무리."
    }
  },
  "cards": {
    "past":    {"cardName":"${past.name}",  "cardNameKo":"${past.nameKo}",  "reading":"${name}님의 과거를 3문장 존댓말로"},
    "present": {"cardName":"${pres.name}", "cardNameKo":"${pres.nameKo}", "reading":"${name}님의 현재를 3문장 존댓말로"},
    "future":  {"cardName":"${fut.name}",  "cardNameKo":"${fut.nameKo}",  "reading":"${name}님의 미래 신탁 3문장 존댓말로"}
  }
}`
    : `You are a world-class tarot master and Jungian analyst.
User hand-picked cards:
• Past:    ${past.name}
• Present: ${pres.name}
• Future:  ${fut.name}

Generate an overwhelmingly rich reading for ${name} (${zodiac}). Each section MUST name its card in the FIRST sentence. Maintain a dignified, respectful oracle tone throughout.

Return ONLY this JSON (content fields = real text, 200+ words each):
{
  "title": "${name}'s Tarot Oracle (max 45 chars)",
  "subtitle": "3 cosmic keywords · · ·",
  "sections": {
    "essence": {
      "title": "✦ The Three-Card Cosmic Confluence",
      "content": "200+ words. Open by addressing ${name} directly. Analyze the synergy of all three cards (${past.name}, ${pres.name}, ${fut.name}) with ${zodiac} energy. Include Jungian archetype analysis."
    },
    "pastCard": {
      "title": "✦ Past — ${past.name}",
      "content": "200+ words. Name ${past.name} in the first sentence. Map this card's iconography to the dream imagery. Reveal the root pattern from ${name}'s past."
    },
    "presentCard": {
      "title": "✦ Present — ${pres.name}",
      "content": "200+ words. Name ${pres.name} in the first sentence. Expose the active psychological patterns. Show how ${zodiac} amplifies this card for ${name} right now."
    },
    "futureCard": {
      "title": "✦ Future Oracle — ${fut.name}",
      "content": "250+ words. Name ${fut.name} in the first sentence. Include: ① one auspicious direction ② three lucky numbers with meanings ③ two cautious months ④ two daily protective practices. Close with sincere encouragement to ${name}."
    }
  },
  "cards": {
    "past":    {"cardName":"${past.name}",  "reading":"3 respectful oracle sentences to ${name}"},
    "present": {"cardName":"${pres.name}", "reading":"3 respectful oracle sentences to ${name}"},
    "future":  {"cardName":"${fut.name}",  "reading":"3 respectful oracle sentences to ${name}"}
  }
}`;

  let up = isKo
    ? `이름: ${name}\n별자리: ${zodiac}\n꿈: "${dreamText}"\n분위기: ${mood === 'good' ? '긍정적' : '불안'}\n선택 카드: 과거=${past.name}, 현재=${pres.name}, 미래=${fut.name}\n각 content 250자 이상 장문으로 채워주세요.`
    : `Name: ${name}\nZodiac: ${zodiac}\nDream: "${dreamText}"\nMood: ${mood}\nPicked: past=${past.name}, present=${pres.name}, future=${fut.name}\nFill each content with 200+ words of actual text.`;

  // 타로 78카드 사전 + 테트라비블로스/별자리 사전 + 꿈해몽 사전 자료를 컨텍스트로 주입
  try {
    const cardNames = [past.name, pres.name, fut.name];
    const tarotCtx = await window.ReferenceEngine?.getTarotAstroContext(zodiac, cardNames, lang) || '';
    const dreamCtx = await window.ReferenceEngine?.getDreamContext(dreamText, lang) || '';
    up += tarotCtx + dreamCtx;
  } catch (e) { /* 참고자료 없이도 계속 진행 */ }

  const p = await callTextAI(sys, up);
  if (!p.title || !p.sections) throw new Error('Missing fields');

  const cleanSec = s => ({
    title:   (s?.title   || '').trim(),
    content: (s?.content || '').replace(/^【.*?】\s*/g, '').trim()
  });

  return {
    title:    (p.title    || '').slice(0, 60),
    subtitle: (p.subtitle || '').slice(0, 120),
    sections: {
      essence:     cleanSec(p.sections?.essence),
      pastCard:    cleanSec(p.sections?.pastCard),
      presentCard: cleanSec(p.sections?.presentCard),
      futureCard:  cleanSec(p.sections?.futureCard)
    },
    cards: {
      past:    { cardName: past.name,  cardNameKo: past.nameKo,  reading: (p.cards?.past?.reading    || '').trim() },
      present: { cardName: pres.name, cardNameKo: pres.nameKo, reading: (p.cards?.present?.reading || '').trim() },
      future:  { cardName: fut.name,  cardNameKo: fut.nameKo,  reading: (p.cards?.future?.reading  || '').trim() }
    }
  };
}

/* 로컬 폴백 — 뽑힌 카드 덮어씌우기 */
function localFallbackForPickedCards(dreamText, mood, lang, form, picked) {
  const data = generateLocalPremiumTarotFallback(dreamText, mood, lang, form, picked);
  const past = picked[0], pres = picked[1], fut = picked[2];
  const isKo = lang === 'ko';
  data.cards = {
    past:    { ...data.cards.past,    cardName: past.name,  cardNameKo: past.nameKo },
    present: { ...data.cards.present, cardName: pres.name, cardNameKo: pres.nameKo },
    future:  { ...data.cards.future,  cardName: fut.name,  cardNameKo: fut.nameKo }
  };
  if (data.sections.pastCard)
    data.sections.pastCard.title    = isKo ? `✦ 과거 카드 — ${past.nameKo}`  : `✦ Past — ${past.name}`;
  if (data.sections.presentCard)
    data.sections.presentCard.title = isKo ? `✦ 현재 카드 — ${pres.nameKo}` : `✦ Present — ${pres.name}`;
  if (data.sections.futureCard)
    data.sections.futureCard.title  = isKo ? `✦ 미래 신탁 — ${fut.nameKo}`  : `✦ Future — ${fut.name}`;
  return data;
}

/* ────────────────────────────────────────────────────────────────────
   1. FreeDreamArt — Cosmic Dreamscape 캔버스 (무료 공개)
───────────────────────────────────────────────────────────────────── */
function FreeDreamArt({ url, lang }) {
  const L = LANG[lang];
  return (
    <div style={{ marginBottom:'32px' }}>
      <div style={{ textAlign:'center', marginBottom:'14px',
        color:'#c4b5fd', fontSize:'.72rem', fontWeight:700,
        letterSpacing:'.22em', textTransform:'uppercase',
        textShadow:'0 0 18px rgba(168,85,247,.55)' }}>
        {L.freeCanvasTitle}
      </div>
      <div style={{
        position:'relative', width:'100%', aspectRatio:'16/9',
        borderRadius:'14px', overflow:'hidden',
        background:'linear-gradient(135deg,#060412,#0f0a24)',
        boxShadow:'0 0 0 1px rgba(255,255,255,.06),0 8px 48px rgba(0,0,0,.85),0 0 80px rgba(124,58,237,.15)'
      }}>
        {/* shimmer — <img> 뒤에서 로딩 중 배경 역할 */}
        <div style={{
          position:'absolute', inset:0, zIndex:1,
          background:'linear-gradient(90deg,#060412 25%,#0f0a24 50%,#060412 75%)',
          backgroundSize:'200% 100%', animation:'shimmerLoad 1.6s infinite'
        }}/>
        {/* ★ freeDreamImageUrl → src 직접 바인딩
             referrerPolicy="no-referrer": localhost 레퍼러 차단 → 익명 요청 유지 */}
        <img
          src={url}
          alt="Dream Canvas"
          loading="lazy"
          referrerPolicy="no-referrer"
          crossOrigin="anonymous"
          style={{
            position:'absolute', inset:0,
            width:'100%', height:'100%',
            objectFit:'cover', zIndex:2, borderRadius:'14px'
          }}
        />
        <div style={{
          position:'absolute', inset:0, zIndex:3, pointerEvents:'none',
          background:'radial-gradient(ellipse at 50% 50%,transparent 55%,rgba(0,0,0,.38) 100%)'
        }}/>
      </div>
      <p style={{ textAlign:'center', marginTop:'10px',
        color:'rgba(124,58,237,.45)', fontSize:'.62rem',
        letterSpacing:'.14em', fontStyle:'italic' }}>
        {L.freeCanvasCaption}
      </p>
    </div>
  );
}

/* ────────────────────────────────────────────────────────────────────
   2. PremiumSection — 카테고리별 장문 섹션
───────────────────────────────────────────────────────────────────── */
function PremiumSection({ section, color, icon }) {
  if (!section?.content) return null;
  return (
    <div style={{
      background:`linear-gradient(135deg,${color}0d,rgba(0,0,0,.45))`,
      border:`1px solid ${color}2e`, borderRadius:'16px',
      padding:'22px 20px', marginBottom:'18px',
      position:'relative', overflow:'hidden'
    }}>
      <div style={{ position:'absolute', left:0, top:0, bottom:0, width:'3px',
        background:`linear-gradient(to bottom,${color}88,${color}11)` }}/>
      <div style={{ display:'flex', alignItems:'flex-start', gap:'10px',
        marginBottom:'12px', paddingLeft:'6px' }}>
        <span style={{ fontSize:'1rem', flexShrink:0, marginTop:'2px' }}>{icon}</span>
        <h4 style={{ color, fontSize:'.75rem', fontWeight:700, letterSpacing:'.1em',
          fontFamily:'Cinzel,serif', lineHeight:1.4, textShadow:`0 0 10px ${color}44` }}>
          {section.title}
        </h4>
      </div>
      <p style={{ color:'rgba(255,255,255,.87)', fontSize:'.84rem',
        lineHeight:2.1, whiteSpace:'pre-line', paddingLeft:'6px' }}>
        {section.content}
      </p>
    </div>
  );
}

/* ────────────────────────────────────────────────────────────────────
   3. CardBack — 타로 카드 뒷면 컴포넌트 (클릭으로 선택)
───────────────────────────────────────────────────────────────────── */
function CardBack({ card, selOrder, onPick, disabled, appeared, idx }) {
  const isSelected = selOrder !== null;
  const [hovered,    setHovered]    = useState(false);
  const [imgFailed,  setImgFailed]  = useState(false);

  const SEL_COLORS = ['#a78bfa', '#c4b5fd', '#fde68a'];
  const SEL_LABELS = ['①', '②', '③'];
  const selColor   = isSelected ? SEL_COLORS[selOrder] : null;

  const borderColor = isSelected
    ? selColor
    : hovered && !disabled
    ? 'rgba(168,85,247,.9)'
    : 'rgba(124,58,237,.38)';

  const shadowStr = isSelected
    ? `0 0 18px ${selColor}99, 0 0 36px ${selColor}44, 0 0 2px ${selColor}`
    : hovered && !disabled
    ? '0 0 16px rgba(124,58,237,.7), 0 0 32px rgba(124,58,237,.3)'
    : '0 2px 8px rgba(0,0,0,.5)';

  const scaleStr = isSelected
    ? 'scale(0.92)'
    : hovered && !disabled
    ? 'scale(1.07) translateY(-4px)'
    : 'scale(1)';

  /* 애니메이션 지연 */
  const appearTransition = `opacity .38s ease ${idx * 28}ms, transform .38s ease ${idx * 28}ms`;
  const interactTransition = 'box-shadow .22s ease, border-color .22s ease, transform .22s ease';

  return (
    <div
      onClick={() => !disabled && !isSelected && onPick(card)}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      style={{
        cursor: isSelected || disabled ? 'default' : 'pointer',
        position: 'relative',
        width: '100%',
        aspectRatio: '2/3',
        borderRadius: '7px',
        border: `1.5px solid ${borderColor}`,
        boxShadow: shadowStr,
        transform: scaleStr,
        opacity: appeared ? 1 : 0,
        transition: `${appeared ? interactTransition : appearTransition}, opacity .38s ease ${idx * 28}ms`,
        overflow: 'hidden',
        userSelect: 'none',
        background: '#0d0520'
      }}
    >
      {/* 카드 뒷면 — 이미지 있으면 표시, 없으면 CSS 폴백 */}
      {!imgFailed ? (
        <img
          src="/images/tarot/card_back.png"
          alt="card back"
          referrerPolicy="no-referrer"
          onError={() => setImgFailed(true)}
          style={{
            position:'absolute', inset:0,
            width:'100%', height:'100%',
            objectFit:'cover',
            opacity: isSelected ? 0.45 : disabled ? 0.28 : hovered ? 0.92 : 0.78,
            transition:'opacity .2s ease'
          }}
        />
      ) : (
        /* CSS 폴백 — 신비로운 보라 그라디언트 패턴 */
        <>
          <div style={{
            position:'absolute', inset:0,
            background: isSelected
              ? `linear-gradient(145deg,${SEL_COLORS[selOrder] || '#a78bfa'}18,#0d0520,#1a0840)`
              : 'linear-gradient(145deg,#0d0520,#1a0840,#0a031a)',
            opacity: disabled ? 0.35 : 1
          }}/>
          <div style={{
            position:'absolute', inset:'4px', borderRadius:'4px',
            border:'1px solid rgba(168,85,247,.28)',
            background:'radial-gradient(circle at 50% 50%, rgba(124,58,237,.1) 0%, transparent 65%)'
          }}/>
          <div style={{
            position:'absolute', inset:0,
            display:'flex', alignItems:'center', justifyContent:'center'
          }}>
            <span style={{
              fontSize:'.72rem', color:'rgba(168,85,247,.5)',
              filter:'drop-shadow(0 0 6px rgba(168,85,247,.4))'
            }}>✦</span>
          </div>
        </>
      )}

      {/* 선택 오버레이 */}
      {isSelected && (
        <div style={{
          position:'absolute', inset:0,
          background:`linear-gradient(145deg,${selColor}22,#0d052088)`,
          display:'flex', alignItems:'center', justifyContent:'center',
          flexDirection:'column', gap:'3px'
        }}>
          <span style={{ fontSize:'1rem', color:selColor, filter:`drop-shadow(0 0 9px ${selColor})` }}>✦</span>
          <span style={{
            fontSize:'.62rem', fontWeight:900, color:selColor,
            fontFamily:'Cinzel,serif', letterSpacing:'.08em',
            textShadow:`0 0 10px ${selColor}`
          }}>{SEL_LABELS[selOrder]}</span>
        </div>
      )}

      {/* hover 글로우 */}
      {!isSelected && hovered && !disabled && (
        <div style={{
          position:'absolute', inset:0, pointerEvents:'none',
          background:'radial-gradient(circle at 50% 50%, rgba(168,85,247,.18) 0%, transparent 70%)'
        }}/>
      )}
    </div>
  );
}

/* ────────────────────────────────────────────────────────────────────
   4. CardPickerStage — 22장 셔플 카드 선택 인터랙션
───────────────────────────────────────────────────────────────────── */
function CardPickerStage({ lang, onComplete }) {
  const isKo = lang === 'ko';
  const [deck,     setDeck]     = useState([]);
  const [selected, setSelected] = useState([]);
  const [appeared, setAppeared] = useState(false);

  useEffect(() => {
    setDeck(shuffleArr(FULL_78_DECK));
    const t = setTimeout(() => setAppeared(true), 60);
    return () => clearTimeout(t);
  }, []);

  const getSelOrder = (card) => {
    const i = selected.findIndex(s => s.id === card.id);
    return i === -1 ? null : i;
  };

  const handlePick = (card) => {
    if (selected.length >= 3) return;
    setSelected(prev => [...prev, card]);
  };

  const POS = isKo
    ? [{ label:'과거', sub:'원인', col:'#a78bfa' }, { label:'현재', sub:'상황', col:'#c4b5fd' }, { label:'미래', sub:'신탁', col:'#fde68a' }]
    : [{ label:'PAST', sub:'Origin', col:'#a78bfa' }, { label:'PRESENT', sub:'Now', col:'#c4b5fd' }, { label:'FUTURE', sub:'Oracle', col:'#fde68a' }];

  return (
    <div className="premium-reveal">

      {/* 헤더 */}
      <div style={{ textAlign:'center', marginBottom:'20px' }}>
        <div style={{ fontSize:'1.8rem', marginBottom:'10px',
          filter:'drop-shadow(0 0 22px rgba(168,85,247,.85))' }}>🃏</div>
        <h3 style={{
          color:'#c4b5fd', fontFamily:'Cinzel,serif', fontWeight:900,
          fontSize:'1.1rem', marginBottom:'8px',
          textShadow:'0 0 22px rgba(168,85,247,.65), 0 0 50px rgba(168,85,247,.3)'
        }}>
          {isKo ? '운명의 카드를 선택하세요' : 'Choose Your Destiny Cards'}
        </h3>
        <p style={{ color:'rgba(255,255,255,.48)', fontSize:'.78rem', lineHeight:1.65, maxWidth:'260px', margin:'0 auto' }}>
          {isKo
            ? '직관에 따라 마음이 이끄는 카드 3장을 순서대로 뽑아주세요'
            : 'Follow your intuition — pick 3 cards in order'}
        </p>
      </div>

      {/* 선택된 카드 슬롯 */}
      <div style={{ display:'flex', gap:'8px', justifyContent:'center', marginBottom:'18px' }}>
        {POS.map((pos, i) => (
          <div key={i} style={{
            flex:1, maxWidth:'100px', textAlign:'center',
            padding:'9px 6px', borderRadius:'11px',
            background: selected[i] ? `${pos.col}12` : 'rgba(255,255,255,.03)',
            border:`1px solid ${selected[i] ? pos.col + '55' : 'rgba(255,255,255,.08)'}`,
            transition:'all .35s ease'
          }}>
            <div style={{ color: pos.col, fontSize:'.6rem', fontWeight:700,
              letterSpacing:'.1em', textTransform:'uppercase', marginBottom:'2px' }}>
              {pos.label}
            </div>
            <div style={{ color:'rgba(255,255,255,.3)', fontSize:'.54rem', marginBottom:'4px' }}>
              {pos.sub}
            </div>
            <div style={{ color: pos.col, fontSize:'.68rem', fontWeight:700,
              minHeight:'1.1em', lineHeight:1.3,
              textShadow: selected[i] ? `0 0 10px ${pos.col}88` : 'none',
              transition:'text-shadow .3s ease' }}>
              {selected[i]
                ? (isKo ? selected[i].nameKo : selected[i].name)
                : <span style={{ opacity:.3 }}>—</span>}
            </div>
          </div>
        ))}
      </div>

      {/* 선택 카운터 */}
      <div style={{ textAlign:'center', marginBottom:'14px' }}>
        <span style={{
          color: selected.length === 3 ? '#4ade80' : 'rgba(255,255,255,.42)',
          fontSize:'.73rem', fontWeight:600, letterSpacing:'.06em',
          transition:'color .4s ease'
        }}>
          {isKo ? `${selected.length} / 3장 선택됨` : `${selected.length} / 3 selected`}
          {selected.length === 3 && (isKo ? ' ✦ 완성!' : ' ✦ Complete!')}
        </span>
      </div>

      {/* 78장 카드 그리드 */}
      <div style={{
        display:'grid', gridTemplateColumns:'repeat(6,1fr)',
        gap:'5px', marginBottom:'20px',
        maxHeight:'420px', overflowY:'auto',
        padding:'4px 2px'
      }}>
        {deck.map((card, idx) => (
          <CardBack
            key={card.id}
            card={card}
            selOrder={getSelOrder(card)}
            onPick={handlePick}
            disabled={selected.length >= 3 && getSelOrder(card) === null}
            appeared={appeared}
            idx={idx}
          />
        ))}
      </div>

      {/* 리딩 시작 버튼 */}
      <div style={{
        opacity: selected.length === 3 ? 1 : 0,
        transform: selected.length === 3 ? 'translateY(0)' : 'translateY(12px)',
        transition:'opacity .45s ease, transform .45s ease',
        pointerEvents: selected.length === 3 ? 'auto' : 'none'
      }}>
        <button
          onClick={() => selected.length === 3 && onComplete(selected)}
          className="w-full py-4 rounded-xl font-black text-base cursor-pointer"
          style={{
            background:'linear-gradient(135deg,#7c3aed,#ec4899)',
            boxShadow:'0 0 38px rgba(124,58,237,.8), 0 0 80px rgba(124,58,237,.35)',
            color:'white', letterSpacing:'.06em', fontSize:'1rem'
          }}
        >
          {isKo ? '✦ 운명 리딩 시작하기 ✦' : '✦ Begin Oracle Reading ✦'}
        </button>
      </div>
    </div>
  );
}

/* ────────────────────────────────────────────────────────────────────
   5. LocalCardImage — 로컬 이미지 우선, 실패 시 AI 폴백
───────────────────────────────────────────────────────────────────── */
function LocalCardImage({ card, mood, position }) {
  const acc = mood === 'good' ? '#d4af37' : '#94a3b8';
  const [status,      setStatus]      = useState('loading');
  const [useFallback, setUseFallback] = useState(false);
  const imgRef  = useRef(null);
  const retried = useRef(false);

  const localSrc = getLocalCardPath(card.slug);
  const fallbackSrc = useMemo(() => {
    const prompt = `${card.name} tarot card traditional iconography ${mood === 'good' ? 'golden celestial light art nouveau watercolor' : 'dark mysterious gothic watercolor atmosphere'}, ultra detailed`;
    return buildTarotCardImageUrl(sanitizeForImagePrompt(prompt), position, mood, '', '');
  }, [card.slug, mood, position]);

  const src = useFallback ? fallbackSrc : localSrc;

  useEffect(() => {
    setStatus('loading');
    retried.current = false;
  }, [src]);
  useEffect(() => {
    const img = imgRef.current;
    if (img && img.complete && img.naturalWidth > 0) setStatus('loaded');
  }, [src]);

  /* 로컬 이미지 3초 타임아웃 → AI 폴백으로 전환 */
  useEffect(() => {
    if (status !== 'loading') return;
    const t = setTimeout(() => {
      if (!useFallback) {
        setUseFallback(true);
      } else {
        setStatus('timeout');
      }
    }, useFallback ? 120000 : 3000);
    return () => clearTimeout(t);
  }, [status, useFallback]);

  const handleError = () => {
    if (!useFallback) {
      setUseFallback(true);
    } else if (!retried.current) {
      retried.current = true;
      setTimeout(() => {
        setStatus('loading');
        if (imgRef.current) imgRef.current.src = fallbackSrc + '&_r=1';
      }, 5000);
    } else {
      setStatus('error');
    }
  };
  const showErr = status === 'error' || status === 'timeout';

  return (
    <div style={{
      position:'relative', width:'100%', aspectRatio:'2/3',
      borderRadius:'10px', overflow:'hidden', background:'#07041a',
      border:`2px solid ${acc}55`,
      boxShadow: status === 'loaded'
        ? `0 0 20px ${acc}44, 0 6px 22px rgba(0,0,0,.7)`
        : '0 4px 10px rgba(0,0,0,.5)',
      transition:'box-shadow 1s ease'
    }}>
      {status === 'loading' && (
        <>
          <div style={{ position:'absolute', inset:0,
            background:'linear-gradient(90deg,#07041a 25%,#0f0a24 50%,#07041a 75%)',
            backgroundSize:'200% 100%', animation:'shimmerLoad 1.6s infinite' }}/>
          <div style={{ position:'absolute', inset:0, display:'flex',
            alignItems:'center', justifyContent:'center', zIndex:5 }}>
            <div className="spin-anim" style={{
              width:'26px', height:'26px', borderRadius:'50%',
              border:`2px solid rgba(255,255,255,.06)`, borderTopColor:acc
            }}/>
          </div>
        </>
      )}
      {showErr && (
        <div style={{ position:'absolute', inset:0, display:'flex',
          alignItems:'center', justifyContent:'center',
          background:'radial-gradient(ellipse at 50% 35%,#1e1b4b,#07041a)' }}>
          <span style={{ fontSize:'2.2rem', filter:`drop-shadow(0 0 18px ${acc})` }}>🔮</span>
        </div>
      )}
      <img
        ref={imgRef} src={src} alt={card.name}
        referrerPolicy="no-referrer"
        style={{
          position:'absolute', inset:0, width:'100%', height:'100%',
          objectFit:'cover', zIndex:3,
          opacity: status === 'loaded' ? 1 : 0, transition:'opacity 1.5s ease',
          animation: status === 'loaded' ? 'revealCard 2s cubic-bezier(.4,0,.2,1) forwards' : 'none'
        }}
        onLoad={() => setStatus('loaded')} onError={handleError}
      />
      {status === 'loaded' && (
        <div style={{ position:'absolute', bottom:0, left:0, right:0, zIndex:10,
          background:'linear-gradient(to top,rgba(0,0,0,.9) 0%,transparent 100%)',
          padding:'14px 4px 6px', textAlign:'center' }}>
          <span style={{ color:acc, fontSize:'.46rem', fontWeight:700,
            fontFamily:'Cinzel,serif', letterSpacing:'.06em',
            textShadow:`0 0 8px ${acc}`, display:'block' }}>
            {card.name}
          </span>
        </div>
      )}
    </div>
  );
}

/* ────────────────────────────────────────────────────────────────────
   6. ThreePickedCardsDisplay — 뽑힌 3장 + 로컬 이미지 + 카드 리딩
───────────────────────────────────────────────────────────────────── */
function ThreePickedCardsDisplay({ cards, pickedCards, mood, lang }) {
  const L = LANG[lang];
  const POS = [
    { key:'past',    card:pickedCards[0], label:L.tarotCardPast.label,    sub:L.tarotCardPast.sub,    col:'#a78bfa' },
    { key:'present', card:pickedCards[1], label:L.tarotCardPresent.label, sub:L.tarotCardPresent.sub, col:'#c4b5fd' },
    { key:'future',  card:pickedCards[2], label:L.tarotCardFuture.label,  sub:L.tarotCardFuture.sub,  col:'#fde68a' }
  ];

  return (
    <div style={{ marginBottom:'28px' }}>
      <div className="three-card-grid">
        {POS.map(pos => {
          const cardData = cards?.[pos.key] || {};
          return (
            <div key={pos.key} style={{ display:'flex', flexDirection:'column' }}>
              <div style={{ marginBottom:'8px', textAlign:'center' }}>
                <div className="card-position-label" style={{ color:pos.col }}>{pos.label}</div>
                <div className="card-position-sub"   style={{ color:pos.col }}>{pos.sub}</div>
              </div>
              <LocalCardImage card={pos.card} mood={mood} position={pos.key}/>
              {cardData.reading && (
                <p style={{ marginTop:'8px', fontSize:'.62rem',
                  color:'rgba(255,255,255,.55)', lineHeight:1.65,
                  borderTop:`1px solid ${pos.col}22`, paddingTop:'7px' }}>
                  {cardData.reading}
                </p>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ────────────────────────────────────────────────────────────────────
   7. CustomDestinyCard — AI 생성 나만의 운명 카드 (골드 트리플 프레임)
───────────────────────────────────────────────────────────────────── */
function CustomDestinyCard({ url, mood, name, zodiac, lang }) {
  const isKo = lang === 'ko';
  const acc  = mood === 'good' ? '#d4af37' : '#94a3b8';
  const [status,   setStatus]   = useState('loading');
  const [revealed, setRevealed] = useState(false);
  const imgRef   = useRef(null);
  const retried  = useRef(false);
  const retryRef = useRef(null);

  useEffect(() => {
    if (!url) return;
    const img = imgRef.current;
    if (img && img.complete && img.naturalWidth > 0) setStatus('loaded');
  }, [url]);
  useEffect(() => () => clearTimeout(retryRef.current), []);
  useEffect(() => {
    if (!url || status !== 'loading') return;
    const t = setTimeout(() => setStatus('timeout'), 180000);
    return () => clearTimeout(t);
  }, [url, status]);
  useEffect(() => {
    const t = setTimeout(() => setRevealed(true), 800);
    return () => clearTimeout(t);
  }, []);

  const handleError = () => {
    if (!retried.current) {
      retried.current = true;
      retryRef.current = setTimeout(() => {
        setStatus('loading');
        if (imgRef.current && url) imgRef.current.src = url + '&_r=1';
      }, 5000);
    } else { setStatus('error'); }
  };
  const showSpin = !url || status === 'loading';
  const showFall = status === 'error' || status === 'timeout';

  const outerGlow = revealed
    ? `0 0 0 1px ${acc}88, 0 0 42px ${acc}55, 0 0 100px ${acc}22, 0 0 200px ${acc}0a`
    : `0 0 0 1px ${acc}22`;

  return (
    <div style={{ position:'relative' }}>

      {/* 상단 씰 배지 */}
      <div style={{ textAlign:'center', marginBottom:'18px' }}>
        <div style={{
          display:'inline-flex', flexDirection:'column', alignItems:'center', gap:'7px'
        }}>
          <div style={{
            width:'58px', height:'58px', borderRadius:'50%',
            background:`linear-gradient(135deg,#12052b,#1e0b44)`,
            border:`2px solid ${acc}`,
            boxShadow: revealed
              ? `0 0 22px ${acc}88, 0 0 55px ${acc}33`
              : `0 0 10px ${acc}33`,
            display:'flex', alignItems:'center', justifyContent:'center',
            position:'relative', transition:'box-shadow 1.4s ease'
          }}>
            <div style={{ position:'absolute', inset:'5px', borderRadius:'50%',
              border:`1px solid ${acc}44` }}/>
            <span style={{ fontSize:'1.5rem', filter:`drop-shadow(0 0 8px ${acc}aa)` }}>🔮</span>
          </div>
          <span style={{
            color:`${acc}bb`, fontSize:'.61rem', letterSpacing:'.28em',
            textTransform:'uppercase', fontFamily:'Cinzel,serif', textAlign:'center',
            textShadow: revealed ? `0 0 14px ${acc}66` : 'none',
            transition:'text-shadow 1.4s ease'
          }}>
            {isKo
              ? '귀하의 꿈과 별자리가 조합된\n세상에 단 하나뿐인 운명 카드'
              : 'One-of-a-kind card forged\nfrom your dream & zodiac'}
          </span>
        </div>
      </div>

      {/* 외부 골드 프레임 */}
      <div style={{
        background:'linear-gradient(155deg,#0d0225,#1a0840,#080518)',
        border:`2px solid ${acc}`, borderRadius:'20px', padding:'10px',
        boxShadow: outerGlow, transition:'box-shadow 1.4s ease'
      }}>

        {/* 중간 내부 프레임 */}
        <div style={{
          border:`1px solid ${acc}44`, borderRadius:'12px', padding:'6px',
          background:`linear-gradient(180deg,${acc}09,transparent)`
        }}>

          {/* 이미지 컨테이너 */}
          <div style={{
            border:`1px solid ${acc}22`, borderRadius:'8px', overflow:'hidden',
            position:'relative', aspectRatio:'9/16',
            background: mood === 'good'
              ? 'linear-gradient(180deg,#12052b,#07041a)'
              : 'linear-gradient(180deg,#1a1a2e,#060412)'
          }}>

            {/* 코너 장식 */}
            {[
              { top:'8px',    left:'8px',   borderTop:`2px solid ${acc}cc`,   borderLeft:`2px solid ${acc}cc`,  borderRadius:'3px 0 0 0' },
              { top:'8px',    right:'8px',  borderTop:`2px solid ${acc}cc`,   borderRight:`2px solid ${acc}cc`, borderRadius:'0 3px 0 0' },
              { bottom:'8px', left:'8px',   borderBottom:`2px solid ${acc}cc`, borderLeft:`2px solid ${acc}cc`,  borderRadius:'0 0 0 3px' },
              { bottom:'8px', right:'8px',  borderBottom:`2px solid ${acc}cc`, borderRight:`2px solid ${acc}cc`, borderRadius:'0 0 3px 0' }
            ].map((s, i) => (
              <div key={i} style={{ position:'absolute', width:'22px', height:'22px', zIndex:10, ...s }}/>
            ))}

            {/* 로딩 */}
            {showSpin && (
              <>
                <div className="panel-skeleton" style={{ borderRadius:'7px' }}/>
                <div style={{ position:'absolute', inset:0, display:'flex',
                  flexDirection:'column', alignItems:'center', justifyContent:'center',
                  zIndex:5, gap:'18px' }}>
                  <div className="spin-anim" style={{
                    width:'58px', height:'58px', borderRadius:'50%',
                    border:`3px solid rgba(255,255,255,.06)`, borderTopColor:acc,
                    boxShadow:`0 0 30px ${acc}66`
                  }}/>
                  <span style={{
                    color:`${acc}66`, fontSize:'.72rem', letterSpacing:'.1em',
                    textAlign:'center', lineHeight:1.7, whiteSpace:'pre-line'
                  }}>
                    {isKo
                      ? '귀하만의 운명 카드를\n우주가 그리는 중...'
                      : 'The cosmos is painting\nyour destiny card...'}
                  </span>
                </div>
              </>
            )}

            {/* 에러 폴백 */}
            {showFall && (
              <div style={{ position:'absolute', inset:0, zIndex:2,
                background:'radial-gradient(ellipse at 50% 30%,#1e1b4b,#050510)',
                display:'flex', flexDirection:'column',
                alignItems:'center', justifyContent:'center', gap:'16px' }}>
                <span style={{ fontSize:'5rem', filter:`drop-shadow(0 0 34px ${acc})` }}>🌙</span>
                <span style={{ color:`${acc}55`, fontSize:'.68rem', letterSpacing:'.1em' }}>
                  {isKo ? '신탁이 준비 중입니다' : 'Oracle preparing...'}
                </span>
              </div>
            )}

            {/* 카드 이미지 */}
            {url && (
              <img
                ref={imgRef} src={url} alt="custom destiny card"
                referrerPolicy="no-referrer"
                style={{
                  position:'absolute', inset:0, width:'100%', height:'100%',
                  objectFit:'cover', zIndex:3,
                  opacity: status === 'loaded' ? 1 : 0, transition:'opacity 2s ease',
                  animation: revealed && status === 'loaded'
                    ? 'revealCard 2.8s cubic-bezier(.4,0,.2,1) forwards' : 'none'
                }}
                onLoad={() => setStatus('loaded')} onError={handleError}
              />
            )}

            {/* 하단 그라데이션 오버레이 */}
            {status === 'loaded' && (
              <div style={{ position:'absolute', bottom:0, left:0, right:0, zIndex:4,
                height:'28%', pointerEvents:'none',
                background:'linear-gradient(to top,rgba(0,0,0,.72) 0%,transparent 100%)' }}/>
            )}
          </div>
        </div>

        {/* 명패 */}
        <div style={{
          marginTop:'8px', padding:'9px 12px',
          borderTop:`1px solid ${acc}22`, textAlign:'center',
          opacity: revealed ? 1 : 0, transition:'opacity 1.1s ease .8s'
        }}>
          <span style={{
            color: acc, fontFamily:'Cinzel,serif',
            fontWeight:700, fontSize:'.95rem', letterSpacing:'.18em',
            textShadow:`0 0 20px ${acc}aa, 0 0 44px ${acc}44`
          }}>
            {isKo ? `${name}님의 운명 카드` : `${name}'s Destiny Card`}
          </span>
          {zodiac && (
            <div style={{ color:`${acc}66`, fontSize:'.6rem', marginTop:'3px', letterSpacing:'.12em' }}>
              {zodiac}
            </div>
          )}
        </div>
      </div>

      {/* 워터마크 */}
      <div style={{ textAlign:'center', marginTop:'12px',
        opacity: revealed ? 0.42 : 0, transition:'opacity 1.3s ease 1.2s' }}>
        <span style={{ color:`${acc}55`, fontSize:'.56rem',
          letterSpacing:'.24em', textTransform:'uppercase', fontFamily:'Cinzel,serif' }}>
          ✦ Dream Oracle ✦
        </span>
      </div>
    </div>
  );
}

/* ────────────────────────────────────────────────────────────────────
   8. TarotResult — 결과 화면 전체 레이아웃
   premPhase: null → watching → form → picking → generating → done
───────────────────────────────────────────────────────────────────── */
function TarotResult({ lang, mood, basicData, dreamText, onRestart }) {
  const L   = LANG[lang];
  const acc = '#7c3aed', accL = '#c4b5fd';
  const bg  = 'radial-gradient(ellipse at 50% 0%,#0d0520 0%,#050510 65%)';

  const [premPhase,    setPremPhase]    = useState(null);
  const [adProg,       setAdProg]       = useState(0);
  const [form,         setForm]         = useState({ name:'', zodiac:'' });
  const [formErr,      setFormErr]      = useState('');
  const [pickedCards,  setPickedCards]  = useState(null);
  const [premiumData,  setPremiumData]  = useState(null);
  const [customCardUrl, setCustomCardUrl] = useState(null);
  const adRef = useRef(null);

  const freeImgUrl = useMemo(
    () => buildFreeImageUrl(dreamText, mood, dreamText.slice(0, 30) + 'tarot', 'tarot'),
    [] // eslint-disable-line
  );

  /* 광고 */
  const startAd = () => {
    setPremPhase('watching');
    let p = 0;
    adRef.current = setInterval(() => {
      p += 100 / 300;
      setAdProg(Math.min(p, 100));
      if (p >= 100) { clearInterval(adRef.current); setTimeout(() => setPremPhase('form'), 500); }
    }, 100);
  };
  useEffect(() => () => clearInterval(adRef.current), []);
  const secsLeft = Math.ceil(30 * (1 - adProg / 100));

  /* 폼 검증 */
  const validate = () => {
    if (!form.name.trim()) { setFormErr(L.premSubmitValidName);   return false; }
    if (!form.zodiac)      { setFormErr(L.premSubmitValidZodiac); return false; }
    setFormErr(''); return true;
  };

  /* 폼 제출 → 카드 뽑기 화면으로 */
  const submitPremium = () => {
    if (!validate()) return;
    setPremPhase('picking');
  };

  /* 카드 3장 선택 완료 → AI 리딩 생성 */
  const handleCardsPicked = async (picked) => {
    setPickedCards(picked);
    setPremPhase('generating');
    setCustomCardUrl(buildCustomCardUrl(dreamText, form.zodiac, mood, form.name.trim()));
    try {
      const data = await generateReadingForPickedCards(dreamText, mood, lang, form, picked);
      setPremiumData(data);
    } catch (err) {
      console.warn('[TarotModule] AI fallback:', err.message);
      setPremiumData(localFallbackForPickedCards(dreamText, mood, lang, form, picked));
    }
    setPremPhase('done');
  };

  /* 프리미엄 게이트 추가 피처 리스트 */
  const extraFeatures = lang === 'ko'
    ? [
        '🎴 22장 덱에서 직접 3장 뽑기 인터랙션',
        '📊 재물·연애·건강·행운 분석',
        '🌌 귀하만의 운명 커스텀 타로 카드 1장 AI 생성'
      ]
    : [
        '🎴 Hand-pick 3 cards from the full Major Arcana',
        '📊 Wealth · Love · Health · Fortune reading',
        '🌌 1 AI-generated one-of-a-kind custom destiny card'
      ];

  const SECTION_CFG = [
    { key:'essence',     color:'#a78bfa', icon:'🔮' },
    { key:'pastCard',    color:'#d4af37', icon:'🃏' },
    { key:'presentCard', color:'#c084fc', icon:'🎴' },
    { key:'futureCard',  color:'#4ade80', icon:'✨' }
  ];

  return (
    <div className="relative min-h-screen px-4 py-8" style={{ background:bg }}>
      <Stars/>
      <div className="relative z-10 max-w-md mx-auto">

        {/* ① 결과 헤더 */}
        <div className="text-center pt-4 mb-7">
          <div className="inline-block px-3 py-1 rounded-full text-xs font-bold tracking-widest uppercase mb-3"
            style={{ background:`${acc}18`, color:acc, border:`1px solid ${acc}33` }}>
            {L.readingHeader.tarot}
          </div>
          <h2 className="font-black text-2xl md:text-3xl mb-2"
            style={{ color:accL, fontFamily:'Cinzel,serif' }}>
            {basicData.title}
          </h2>
          <p className="text-sm" style={{ color:acc }}>{basicData.subtitle}</p>
        </div>

        {/* ② 무료 해몽 텍스트 */}
        <Divider label={L.oracleSection.tarot} color={acc}/>
        <div className="glass rounded-2xl p-6 mb-8"
          style={{ borderColor:`${acc}44`,
            background:'linear-gradient(135deg,rgba(0,0,0,.42),rgba(124,58,237,.05))' }}>
          <div className="flex items-center gap-2 mb-3">
            <span>🔮</span>
            <span className="text-xs font-bold tracking-widest uppercase" style={{ color:acc }}>
              {L.oracleLabel.tarot}
            </span>
          </div>
          <p className="reading-text text-gray-200 text-sm">{sanitize(basicData.readingText)}</p>
        </div>

        {/* ③ Cosmic Dreamscape 캔버스 (무료 공개) */}
        <FreeDreamArt url={freeImgUrl} lang={lang}/>

        {/* ④ 프리미엄 게이트 */}
        {premPhase === null && (
          <div style={{
            background:'linear-gradient(135deg,rgba(88,28,220,.22),rgba(0,0,0,.55))',
            border:`1px solid ${acc}55`, borderRadius:'20px',
            padding:'26px 20px', marginBottom:'24px'
          }}>
            <div className="text-center mb-5">
              <div style={{ fontSize:'1.6rem', marginBottom:'10px' }}>🔒</div>
              <h3 className="font-black text-base mb-1" style={{ color:accL }}>
                {L.premGateTitle}
              </h3>
              <p className="text-sm leading-relaxed mt-2"
                style={{ color:'rgba(255,255,255,.62)', lineHeight:1.75 }}>
                {L.premGateNewDesc.tarot}
              </p>
            </div>
            <ul className="mb-6 space-y-2">
              {L.premFeatures.tarot.map((f, i) => (
                <li key={i} className="text-sm" style={{ color:'rgba(255,255,255,.72)' }}>{f}</li>
              ))}
              {extraFeatures.map((f, i) => (
                <li key={'x'+i} className="text-sm" style={{ color:'rgba(255,255,255,.72)' }}>{f}</li>
              ))}
            </ul>
            <div className="flex flex-col gap-3">
              <button onClick={startAd}
                className="w-full py-4 rounded-xl font-black text-sm cursor-pointer"
                style={{ background:`linear-gradient(135deg,${acc},#ec4899)`,
                  boxShadow:`0 0 30px ${acc}55` }}>
                {L.premAdBtn}
              </button>
              <button onClick={() => setPremPhase('form')}
                className="w-full py-3 rounded-xl font-black text-sm cursor-pointer"
                style={{ background:'linear-gradient(135deg,#3b0764,#6d28d9)',
                  boxShadow:'0 0 22px rgba(109,40,217,.4)', color:'white' }}>
                {L.premPayBtn}
              </button>
            </div>
          </div>
        )}

        {/* ⑤ 광고 진행바 */}
        {premPhase === 'watching' && (
          <div className="glass rounded-2xl p-6 mb-6" style={{ borderColor:`${acc}44` }}>
            <div className="flex items-center justify-between mb-3">
              <span className="text-gray-400 text-sm">{L.premAdPlaying}</span>
              <span className="font-black tabular-nums" style={{ color:acc, fontSize:'1.2rem' }}>
                {secsLeft}s
              </span>
            </div>
            <div className="w-full bg-gray-900 rounded-full mb-4" style={{ height:'5px' }}>
              <div className="prog-bar rounded-full"
                style={{ width:`${adProg}%`, background:`linear-gradient(90deg,${acc},#ec4899)` }}/>
            </div>
            <div className="rounded-xl p-5 text-center"
              style={{ background:'rgba(255,255,255,.03)', border:'1px dashed rgba(255,255,255,.08)' }}>
              <div className="text-gray-600 text-xs mb-1">[ AD PLACEHOLDER ]</div>
              <div className="text-gray-700 text-xs">Google AdSense / AdMob 광고 영역</div>
            </div>
            {adProg >= 100 && (
              <p className="text-center text-sm font-bold mt-3" style={{ color:'#4ade80' }}>
                {L.premAdDone}
              </p>
            )}
          </div>
        )}

        {/* ⑥ 이름 / 별자리 입력 폼 */}
        {premPhase === 'form' && (
          <div className="glass rounded-2xl p-6 mb-6 premium-reveal"
            style={{ borderColor:`${acc}55`,
              background:'linear-gradient(135deg,rgba(88,28,220,.13),rgba(0,0,0,.42))' }}>
            <h3 className="font-black text-base text-center mb-5" style={{ color:accL }}>
              {L.premFormTitle.tarot}
            </h3>
            <div className="mb-4">
              <label className="form-label">{L.premNameLabel}</label>
              <input className="form-input" type="text" placeholder={L.premNamePh}
                value={form.name} onChange={e => setForm({...form, name:e.target.value})}
                maxLength={30}/>
            </div>
            <div className="mb-4">
              <label className="form-label">{L.premZodiacLabel}</label>
              <div style={{ position:'relative' }}>
                <select className="form-select" value={form.zodiac}
                  onChange={e => setForm({...form, zodiac:e.target.value})}>
                  <option value="">{L.premZodiacDefault}</option>
                  {ZODIACS.map(z => (
                    <option key={z.en} value={z.en}>{lang === 'ko' ? z.ko : z.en}</option>
                  ))}
                </select>
                <span style={{ position:'absolute', right:'12px', top:'50%',
                  transform:'translateY(-50%)', pointerEvents:'none',
                  color:'rgba(255,255,255,.4)', fontSize:'.8rem' }}>▾</span>
              </div>
            </div>
            {formErr && (
              <p className="text-sm text-center mb-3" style={{ color:'#f87171' }}>{formErr}</p>
            )}
            <button onClick={submitPremium}
              className="w-full py-4 rounded-xl font-black text-base cursor-pointer"
              style={{ background:`linear-gradient(135deg,${acc},#ec4899)`,
                boxShadow:`0 0 32px ${acc}55` }}>
              {lang === 'ko' ? '🃏 카드 뽑기 화면으로 →' : '🃏 Choose My Cards →'}
            </button>
          </div>
        )}

        {/* ⑦ 22장 카드 뽑기 인터랙션 */}
        {premPhase === 'picking' && (
          <div style={{ marginBottom:'24px' }}>
            <CardPickerStage lang={lang} onComplete={handleCardsPicked}/>
          </div>
        )}

        {/* ⑧ AI 리딩 생성 중 */}
        {premPhase === 'generating' && (
          <div className="glass rounded-2xl p-8 mb-6 text-center premium-reveal"
            style={{ borderColor:`${acc}44` }}>
            <div className="inline-flex items-center justify-center w-20 h-20 mb-5 relative">
              <div className="spin-anim absolute inset-0 rounded-full"
                style={{ border:`2px solid transparent`, borderTopColor:acc,
                  boxShadow:`0 0 20px ${acc}88` }}/>
              <span style={{ fontSize:'2rem', filter:`drop-shadow(0 0 14px ${acc})` }}>🃏</span>
            </div>
            <p className="text-white text-sm font-medium">{L.premGenerating.tarot}</p>
          </div>
        )}

        {/* ⑨ 프리미엄 결과 전체 */}
        {premPhase === 'done' && premiumData && pickedCards && (
          <div className="premium-reveal">

            {/* PREMIUM 배지 */}
            <div className="text-center mb-8">
              <div className="inline-block px-3 py-1 rounded-full text-xs font-bold tracking-widest uppercase mb-3"
                style={{ background:'#7c3aed22', color:'#a78bfa', border:'1px solid #7c3aed44' }}>
                PREMIUM ORACLE · UNLOCKED ✦
              </div>
              <h3 className="font-black text-xl"
                style={{ color:accL, fontFamily:'Cinzel,serif',
                  textShadow:`0 0 22px ${acc}88` }}>
                ✦ {premiumData.title} ✦
              </h3>
              <p className="text-sm mt-1" style={{ color:acc }}>{premiumData.subtitle}</p>
            </div>

            {/* [A] 3카드 스프레드 — 로컬 이미지 */}
            <Divider label={L.tarotSpreadSection} color="#a78bfa"/>
            <ThreePickedCardsDisplay
              cards={premiumData.cards}
              pickedCards={pickedCards}
              mood={mood}
              lang={lang}
            />

            {/* [B] 4-섹션 장문 해몽 */}
            <Divider label={L.premSection.tarot} color="#a78bfa"/>
            <div style={{ marginBottom:'12px' }}>
              {SECTION_CFG.map(cfg => (
                <PremiumSection
                  key={cfg.key}
                  section={premiumData.sections?.[cfg.key]}
                  color={cfg.color}
                  icon={cfg.icon}
                />
              ))}
            </div>

            {/* [C] 나만의 운명 카드 피날레 */}
            <Divider
              label={lang === 'ko' ? '✦ 귀하만의 운명 카드' : '✦ Your Destiny Card'}
              color="#d4af37"
            />
            <div style={{ marginBottom:'28px' }}>
              {/* 설명 배너 */}
              <div style={{
                background:'linear-gradient(135deg,rgba(88,28,220,.1),rgba(0,0,0,.5))',
                border:'1px solid rgba(124,58,237,.22)', borderRadius:'13px',
                padding:'13px 16px', marginBottom:'18px', textAlign:'center'
              }}>
                <p style={{
                  color:'rgba(196,181,253,.62)', fontSize:'.73rem',
                  lineHeight:1.75, fontStyle:'italic'
                }}>
                  {lang === 'ko'
                    ? '✦ 귀하의 꿈과 별자리, 오늘의 에너지를 우주가 혼합하여\n세상에 단 하나뿐인 나만의 타로 운명 카드를 발급하였습니다 ✦'
                    : '✦ The cosmos has woven your dream frequency, zodiac energy, and soul signature\ninto one singular tarot card — yours, and yours alone ✦'}
                </p>
              </div>
              <CustomDestinyCard
                url={customCardUrl}
                mood={mood}
                name={form.name.trim()}
                zodiac={form.zodiac}
                lang={lang}
              />
            </div>

            <p className="text-center text-xs mb-8" style={{ color:`${acc}80` }}>
              {L.cardComplete.tarot}
            </p>
          </div>
        )}

        {/* 재시작 */}
        <div className="text-center pb-12 mt-2">
          <button onClick={onRestart}
            className="text-gray-600 hover:text-gray-400 text-sm transition-colors underline cursor-pointer">
            {L.restart.tarot}
          </button>
        </div>
      </div>
    </div>
  );
}

/* ────────────────────────────────────────────────────────────────────
   9. TarotModule — 루트 (입력 → 로딩 → 결과)
───────────────────────────────────────────────────────────────────── */
window.TarotModule = function TarotModule({ lang, onBack }) {
  const [phase,         setPhase]         = useState('input');
  const [dreamText,     setDreamText]     = useState('');
  const [mood,          setMood]          = useState(null);
  const [basicData,     setBasicData]     = useState(null);
  const [loadPhase,     setLoadPhase]     = useState('analyzing');
  const [scriptPreview, setScriptPreview] = useState(null);

  const handleSubmit = async (txt, m) => {
    setDreamText(txt); setMood(m);
    setPhase('loading'); setLoadPhase('analyzing'); setScriptPreview(null);
    await new Promise(r => setTimeout(r, 900));
    setLoadPhase('scripting');
    let data;
    try {
      data = await generateBasicReading(txt, 'tarot', m, lang);
      setScriptPreview(`"${data.title}"`);
    } catch (err) {
      console.warn('[TarotModule] basic fallback:', err.message);
      data = generateLocalBasicFallback(txt, 'tarot', m, lang);
      setScriptPreview('(ready)');
    }
    setBasicData(data);
    await new Promise(r => setTimeout(r, 700));
    setLoadPhase('drawing');
    await new Promise(r => setTimeout(r, 500));
    setPhase('result');
  };

  const goInput = () => { setPhase('input'); setBasicData(null); setScriptPreview(null); };

  if (phase === 'input')
    return <DreamInput  lang={lang} theme="tarot" onSubmit={handleSubmit} onBack={onBack}/>;
  if (phase === 'loading')
    return <Loading     lang={lang} theme="tarot" phase={loadPhase} scriptPreview={scriptPreview}/>;
  if (phase === 'result')
    return <TarotResult lang={lang} mood={mood} basicData={basicData} dreamText={dreamText} onRestart={goInput}/>;
  return null;
};
