// screens.jsx — 6 screens for 人生事業版圖 PWA
// Each screen is a pure component: takes data + callbacks via props.
// Navigation is owned by the host (pwa-shell.jsx), not by screens themselves.

const { useState, useEffect, useRef, useMemo } = React;

// ─────────────────────────────────────────────────────────────
// Shared primitive — Card (used across all screens)
// ─────────────────────────────────────────────────────────────
function Card({ children, style = {}, pad = 16, glow }) {
  return (
    <div style={{
      background: 'var(--bg-card)',
      borderRadius: 22,
      padding: pad,
      border: '1px solid var(--line)',
      boxShadow: glow || '0 1px 0 rgba(255,255,255,0.04) inset, 0 8px 22px rgba(0,0,0,0.3)',
      ...style,
    }}>{children}</div>
  );
}

// ─────────────────────────────────────────────────────────────
// Shared layout — full-bleed mobile screen (390px design width)
// ─────────────────────────────────────────────────────────────
function ScreenShell({ children, scrollable = true, pad = true, bg }) {
  return (
    <div style={{
      width: '100%', height: '100%',
      background: bg || 'radial-gradient(ellipse at top, #1A1F38 0%, #06070D 65%)',
      display: 'flex', flexDirection: 'column',
      overflow: scrollable ? 'auto' : 'hidden',
      color: 'var(--fg)',
    }}>
      <div style={{ flex: 1, padding: pad ? '100px 16px 24px' : 0, minHeight: 0 }}>
        {children}
      </div>
    </div>
  );
}

function TopBar({ title, onBack, right, progress }) {
  return (
    <div style={{
      position: 'absolute', top: 56, left: 16, right: 16, zIndex: 5,
      display: 'flex', alignItems: 'center', justifyContent: 'space-between',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
        {onBack && (
          <button onClick={onBack} style={{
            background: 'rgba(255,255,255,0.06)', border: '1px solid var(--line)',
            width: 36, height: 36, borderRadius: 12, cursor: 'pointer',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--fg)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M15 18l-6-6 6-6"/>
            </svg>
          </button>
        )}
        {title && <span style={{ fontSize: 15, fontWeight: 500, color: 'var(--fg)' }}>{title}</span>}
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
        {progress && (
          <span style={{ fontSize: 12, color: 'var(--fg-3)' }} className="num">{progress}</span>
        )}
        {right}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// SCREEN 1 — Welcome
// ─────────────────────────────────────────────────────────────
function WelcomeScreen({ content, onStart, onSignIn }) {
  if (!content) return <ScreenShell><LoadingDots/></ScreenShell>;
  return (
    <ScreenShell bg="radial-gradient(ellipse at center top, #2B1F4D 0%, #0B0E18 50%, #06070D 100%)">
      {/* nebula particles */}
      <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none', opacity: 0.6 }}>
        <Particles count={28}/>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', height: '100%', justifyContent: 'space-between' }}>
        <div style={{ paddingTop: 24, display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
          {/* hero orb */}
          <div style={{ position: 'relative' }}>
            <Blob size={140}/>
            {/* orbital ring */}
            <svg width={220} height={220} viewBox="0 0 220 220" style={{ position: 'absolute', top: -40, left: -40 }}>
              <circle cx="110" cy="110" r="100" fill="none"
                      stroke="rgba(176,124,255,0.25)" strokeWidth="1"
                      strokeDasharray="2 6"/>
            </svg>
          </div>

          <h1 style={{
            margin: '32px 0 8px', fontSize: 36, fontWeight: 700, letterSpacing: '0.02em',
            background: 'linear-gradient(120deg, #FFFFFF 0%, #B07CFF 50%, #FF5DA2 100%)',
            WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent',
          }}>{content.appName}</h1>
          <div style={{
            fontSize: 13, color: 'var(--fg-3)', letterSpacing: '0.32em',
          }}>{content.tagline}</div>

          <p style={{
            marginTop: 28, fontSize: 14, lineHeight: 1.9,
            color: 'var(--fg-2)', textAlign: 'center', whiteSpace: 'pre-line',
            maxWidth: 320,
          }}>{content.pitch}</p>

          {/* 3 pillars */}
          <div style={{ display: 'flex', gap: 10, marginTop: 24 }}>
            {content.pillars.map(p => (
              <div key={p.label} style={{
                background: 'rgba(255,255,255,0.04)',
                border: '1px solid var(--line)',
                borderRadius: 14, padding: '12px 14px',
                display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
                minWidth: 78,
                backdropFilter: 'blur(8px)',
              }}>
                <span style={{ fontSize: 22, color: p.color,
                               filter: `drop-shadow(0 0 6px ${p.color})` }}>{p.glyph}</span>
                <span style={{ fontSize: 13, color: 'var(--fg)', fontWeight: 500 }}>{p.label}</span>
                <span style={{ fontSize: 10, color: 'var(--fg-3)' }}>{p.subtitle}</span>
              </div>
            ))}
          </div>
        </div>

        <div style={{ paddingBottom: 24 }}>
          <GlowButton onClick={onStart}>開始導航</GlowButton>
          <div style={{ marginTop: 14, textAlign: 'center' }}>
            <button onClick={onSignIn} style={{
              background: 'transparent', border: 'none', cursor: 'pointer',
              color: 'var(--fg-3)', fontSize: 12,
            }}>已有命盤？登入查看 ›</button>
          </div>
        </div>
      </div>
    </ScreenShell>
  );
}

// ─────────────────────────────────────────────────────────────
// SCREEN 2 — Profile / Birth info
// ─────────────────────────────────────────────────────────────
function ProfileScreen({ onBack, onSubmit, initial = {} }) {
  const [form, setForm] = useState({
    name: initial.name || '',
    gender: initial.gender || 'female',
    date: initial.date || '1991-08-14',
    hour: initial.hour ?? 11,
    place: initial.place || '台北市',
  });
  const set = (k, v) => setForm(s => ({ ...s, [k]: v }));

  const HOURS = ['子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥'];
  const PLACES = ['台北市','新北市','台中市','高雄市','台南市','桃園市','其他'];

  return (
    <ScreenShell>
      <TopBar onBack={onBack} title="基本資料" progress="1 / 3"/>

      <div style={{ marginTop: 8 }}>
        <h2 style={{ margin: '0 0 4px', fontSize: 26, fontWeight: 700, letterSpacing: '0.02em' }}>
          你的命盤從這裡<br/>開始建立
        </h2>
        <p style={{ margin: 0, fontSize: 13, color: 'var(--fg-3)' }}>
          資料只用於計算，永遠不會公開或外流
        </p>
      </div>

      <div style={{ marginTop: 24, display: 'flex', flexDirection: 'column', gap: 16 }}>
        <Field label="姓名">
          <input value={form.name} onChange={e => set('name', e.target.value)}
                 placeholder="輸入你的名字"
                 style={inputStyle}/>
        </Field>

        <Field label="性別">
          <Segmented
            value={form.gender}
            onChange={v => set('gender', v)}
            options={[{value:'female',label:'女'},{value:'male',label:'男'},{value:'other',label:'其他'}]}
          />
        </Field>

        <Field label="出生年月日">
          <input type="date" value={form.date} onChange={e => set('date', e.target.value)}
                 style={inputStyle}/>
        </Field>

        <Field label="出生時辰" hint="若不確定，可選「子時 / 不詳」">
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(6, 1fr)', gap: 6 }}>
            {HOURS.map((h, i) => (
              <button key={h} onClick={() => set('hour', i*2 + 1)}
                style={{
                  background: form.hour === i*2+1 ? 'rgba(176,124,255,0.18)' : 'rgba(255,255,255,0.04)',
                  border: `1px solid ${form.hour === i*2+1 ? 'var(--purple)' : 'var(--line)'}`,
                  borderRadius: 10, padding: '8px 0', cursor: 'pointer',
                  color: form.hour === i*2+1 ? 'var(--purple)' : 'var(--fg-2)',
                  fontSize: 13, fontWeight: form.hour === i*2+1 ? 600 : 400,
                  fontFamily: 'inherit',
                  transition: 'all 120ms cubic-bezier(.2,.8,.2,1)',
                }}>{h}</button>
            ))}
          </div>
        </Field>

        <Field label="出生地">
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
            {PLACES.map(p => (
              <button key={p} onClick={() => set('place', p)}
                style={{
                  background: form.place === p ? 'rgba(43,212,168,0.18)' : 'rgba(255,255,255,0.04)',
                  border: `1px solid ${form.place === p ? 'var(--neon-green)' : 'var(--line)'}`,
                  borderRadius: 99, padding: '6px 14px', cursor: 'pointer',
                  color: form.place === p ? 'var(--neon-green)' : 'var(--fg-2)',
                  fontSize: 13, fontFamily: 'inherit',
                }}>{p}</button>
            ))}
          </div>
        </Field>
      </div>

      <div style={{ height: 100 }}/>

      <BottomCTA>
        <GlowButton onClick={() => onSubmit(form)} disabled={!form.name}>
          下一步：填寫問卷
        </GlowButton>
      </BottomCTA>
    </ScreenShell>
  );
}

function Field({ label, hint, children }) {
  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 8 }}>
        <span style={{ fontSize: 12, color: 'var(--fg-2)', letterSpacing: '0.08em' }}>{label}</span>
        {hint && <span style={{ fontSize: 10, color: 'var(--fg-3)' }}>{hint}</span>}
      </div>
      {children}
    </div>
  );
}
const inputStyle = {
  width: '100%', boxSizing: 'border-box',
  background: 'rgba(255,255,255,0.04)',
  border: '1px solid var(--line)', borderRadius: 12,
  padding: '12px 14px', color: 'var(--fg)', fontSize: 15,
  fontFamily: 'inherit', outline: 'none',
};
function Segmented({ value, onChange, options }) {
  return (
    <div style={{
      display: 'flex', background: 'rgba(255,255,255,0.04)',
      border: '1px solid var(--line)', borderRadius: 12, padding: 4,
    }}>
      {options.map(o => (
        <button key={o.value} onClick={() => onChange(o.value)}
          style={{
            flex: 1, background: value === o.value
              ? 'linear-gradient(120deg, rgba(176,124,255,0.25), rgba(255,93,162,0.20))'
              : 'transparent',
            border: 'none', borderRadius: 8, padding: '8px 0', cursor: 'pointer',
            color: value === o.value ? 'var(--fg)' : 'var(--fg-3)',
            fontSize: 14, fontWeight: value === o.value ? 600 : 400,
            fontFamily: 'inherit',
            transition: 'all 120ms cubic-bezier(.2,.8,.2,1)',
          }}>{o.label}</button>
      ))}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// SCREEN 3 — Quiz
// TODO [BlockLib-extract]: QuizScreen → '問卷收集 Block' candidate.
// QUIZ_CAT / PHASE_INFO 為可配置的題庫分類，未來可由 block config 傳入。
// ─────────────────────────────────────────────────────────────

// 注意：本測驗為「傾向分析」參考工具，非正式 DISC / MBTI 認證測驗。
const QUIZ_CAT = {
  disc:       { label:'DISC 傾向分析',       color:'var(--blue)' },
  pressure:   { label:'業務抗壓與職涯適配', color:'var(--coral)' },
  motivation: { label:'職涯轉換動機',       color:'var(--neon-green)' },
  mbti:       { label:'MBTI 風格',           color:'var(--purple)' },
  bazi:       { label:'八字驗證',            color:'var(--gold)' },
  support:    { label:'支持系統需求',        color:'var(--neon-teal)' },
};
const PHASE_INFO = {
  1: { label:'Phase 1', subtitle:'傾向分析 + 抗壓評估', color:'var(--neon-teal)' },
  2: { label:'Phase 2', subtitle:'風格探索 + 流年分析（已解鎖）', color:'var(--purple)' },
};

// TODO [BlockLib-extract]: QuizScreen UX shell — supports section / phase config via props.
// phaseConfig and categoryConfig can be injected by block template for non-recruitment use cases.
function QuizScreen({ onBack, onComplete, questions, phase = 1 }) {
  const [idx, setIdx] = useState(0);
  const [answers, setAnswers] = useState({});

  if (!questions || questions.length === 0) return <ScreenShell><LoadingDots/></ScreenShell>;

  const q         = questions[idx];
  const total     = questions.length;
  // q.section (future field) → QUIZ_CAT label → category string
  const cat       = QUIZ_CAT[q.category] || { label: q.category || '問卷', color:'var(--purple)' };
  const sectionLabel = q.section || cat.label;
  const phaseInfo = PHASE_INFO[phase] || PHASE_INFO[1];

  // estimated remaining time (~8 sec / question)
  const estMin  = Math.ceil((total - idx) * 8 / 60);
  const estText = estMin <= 1 ? '< 1 分鐘' : `約 ${estMin}–${estMin + 1} 分鐘`;

  // category tabs — show only when ≤ 3 unique categories (short quiz)
  // long quiz uses a single section pill instead
  const categories  = Array.from(new Set(questions.map(qq => qq.category)));
  const showTabRow  = categories.length <= 3;

  // windowed dots: at most 9, centered around current question
  const WIN = 9, half = Math.floor(WIN / 2);
  let dStart = Math.max(0, idx - half);
  let dEnd   = Math.min(total - 1, dStart + WIN - 1);
  if (dEnd - dStart < WIN - 1) dStart = Math.max(0, dEnd - WIN + 1);
  const dotWindow = Array.from({ length: dEnd - dStart + 1 }, (_, i) => dStart + i);

  // back: prev question → quiz start → parent back
  const goBack = () => idx > 0 ? setIdx(idx - 1) : onBack();

  const pick = (opt) => {
    const newAnswers = { ...answers, [q.id]: opt.id };
    setAnswers(newAnswers);
    setTimeout(() => {
      if (idx + 1 < total) setIdx(idx + 1);
      else onComplete(newAnswers, phase);
    }, 240);
  };

  return (
    <ScreenShell>
      <TopBar onBack={goBack} title="問卷" progress={`${idx+1} / ${total}`}/>

      <div style={{ marginTop: 8 }}>

        {/* Phase chip + estimated remaining time */}
        <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between' }}>
          <div style={{
            display:'inline-flex', alignItems:'center', gap: 6,
            padding:'4px 10px', borderRadius: 99,
            background:`${phaseInfo.color}1A`, color: phaseInfo.color,
            border:`1px solid ${phaseInfo.color}33`,
            fontSize: 11, letterSpacing:'0.16em',
          }}>
            <span style={{ fontWeight:600 }}>{phaseInfo.label}</span>
            <span style={{ opacity:0.7 }}>{phaseInfo.subtitle}</span>
          </div>
          <span style={{ fontSize:11, color:'var(--fg-4)' }}>{estText}</span>
        </div>

        {/* Category tabs (≤3) OR section pill (long quiz) */}
        {showTabRow ? (
          <div style={{ display:'flex', gap: 8, marginTop: 12 }}>
            {categories.map(c => {
              const m      = QUIZ_CAT[c] || { label: c, color:'var(--fg-3)' };
              const active = c === q.category;
              return (
                <div key={c} style={{
                  flex:1, textAlign:'center', padding:'8px 0', borderRadius:10,
                  background: active ? 'rgba(255,255,255,0.04)' : 'transparent',
                  border:`1px solid ${active ? m.color : 'transparent'}`,
                  color: active ? m.color : 'var(--fg-3)',
                  fontSize:13, fontWeight: active ? 600 : 400,
                }}>{m.label}</div>
              );
            })}
          </div>
        ) : (
          <div style={{ marginTop:10 }}>
            <span style={{
              display:'inline-block',
              padding:'3px 10px', borderRadius: 99,
              background:`${cat.color}22`, border:`1px solid ${cat.color}44`,
              color: cat.color, fontSize:12, fontWeight:600,
            }}>{sectionLabel}</span>
          </div>
        )}

        {/* Progress: full-width bar + windowed dots + percentage */}
        <div style={{ marginTop:14 }}>
          <div style={{ height:3, borderRadius:99, background:'rgba(255,255,255,0.06)', overflow:'hidden' }}>
            <div style={{
              width:`${(idx + 1) / total * 100}%`, height:'100%',
              borderRadius:99, background: cat.color,
              boxShadow:`0 0 8px ${cat.color}`,
              transition:'width 300ms ease',
            }}/>
          </div>
          <div style={{ display:'flex', alignItems:'center', gap:3, marginTop:8 }}>
            {dStart > 0 && <span style={{ fontSize:10, color:'var(--fg-4)', marginRight:2 }}>…</span>}
            {dotWindow.map(i => (
              <div key={i} style={{
                width: i === idx ? 14 : 6, height:6, borderRadius:99, flexShrink:0,
                background: i <= idx ? cat.color : 'rgba(255,255,255,0.12)',
                opacity: i === idx ? 1 : i < idx ? 0.65 : 0.3,
                boxShadow: i === idx ? `0 0 6px ${cat.color}` : 'none',
                transition:'all 200ms ease',
              }}/>
            ))}
            {dEnd < total - 1 && <span style={{ fontSize:10, color:'var(--fg-4)', marginLeft:2 }}>…</span>}
            <span style={{ marginLeft:'auto', fontSize:11, color:'var(--fg-4)',
                           fontFamily:'var(--font-mono)', whiteSpace:'nowrap' }}>
              {Math.round((idx + 1) / total * 100)}%
            </span>
          </div>
        </div>

        {/* Question card */}
        <div key={q.id} style={{ marginTop:24 }}>
          {/* Section label + back-one-question button */}
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:12 }}>
            <div style={{ fontSize:11, color: cat.color, letterSpacing:'0.3em' }}>
              {sectionLabel} · 第 {idx+1} 題
            </div>
            {idx > 0 && (
              <button onClick={() => setIdx(idx - 1)} style={{
                background:'transparent', border:'none', cursor:'pointer',
                color:'var(--fg-3)', fontSize:12, fontFamily:'inherit',
                display:'flex', alignItems:'center', gap:3, padding:'2px 0',
              }}>‹ 上一題</button>
            )}
          </div>

          <h2 style={{
            margin:0, fontSize:22, lineHeight:1.5, fontWeight:600,
            color:'var(--fg)', maxWidth:320,
          }}>{q.prompt}</h2>

          <div style={{ marginTop:28 }}>

            {/* contrast — 2-up card; both cards identical weight when unselected */}
            {/* TODO [BlockLib-extract]: contrast UX is assessment-agnostic — extract to BlockLib CardPicker */}
            {q.kind === 'contrast' && (
              <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:10 }}>
                {q.options.map((opt) => {
                  const _sel = answers[q.id] === opt.id;
                  return (
                    <button key={opt.id} onClick={() => pick(opt)} style={{
                      background: _sel
                        ? 'linear-gradient(165deg, rgba(176,124,255,0.22), rgba(255,93,162,0.14))'
                        : 'rgba(255,255,255,0.04)',
                      border:`1px solid ${_sel ? 'rgba(176,124,255,0.5)' : 'var(--line)'}`,
                      boxShadow: _sel ? '0 0 16px rgba(176,124,255,0.2)' : 'none',
                      transition:'all 160ms ease',
                      borderRadius:18, padding:'24px 16px', minHeight:160,
                      cursor:'pointer',
                      display:'flex', flexDirection:'column', justifyContent:'center',
                      textAlign:'left', color:'var(--fg)', fontFamily:'inherit',
                    }}>
                      <div style={{ fontSize:18, fontWeight:600 }}>{opt.label}</div>
                      {opt.sub && <div style={{ fontSize:12, color:'var(--fg-3)', marginTop:4 }}>{opt.sub}</div>}
                    </button>
                  );
                })}
              </div>
            )}

            {/* choice — vertical list */}
            {q.kind === 'choice' && (
              <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
                {q.options.map(opt => (
                  <button key={opt.id} onClick={() => pick(opt)} style={{
                    background:'rgba(255,255,255,0.04)',
                    border:'1px solid var(--line)',
                    borderRadius:14, padding:'16px 18px', cursor:'pointer',
                    textAlign:'left', color:'var(--fg)', fontFamily:'inherit',
                    display:'flex', justifyContent:'space-between', alignItems:'center',
                  }}>
                    <div>
                      <div style={{ fontSize:15, fontWeight:500 }}>{opt.label}</div>
                      {opt.sub && <div style={{ fontSize:11, color:'var(--fg-3)', marginTop:3 }}>{opt.sub}</div>}
                    </div>
                    <span style={{ color:'var(--fg-3)' }}>›</span>
                  </button>
                ))}
              </div>
            )}

            {/* scale — 1–N circular buttons */}
            {q.kind === 'scale' && (
              <div>
                <div style={{ display:'flex', justifyContent:'space-between', alignItems:'center', gap:8 }}>
                  {q.options.map((opt, i) => (
                    <button key={opt.id} onClick={() => pick(opt)} style={{
                      flex:1, aspectRatio:'1/1',
                      background:'rgba(255,255,255,0.04)',
                      border:'1px solid var(--line)',
                      borderRadius:'50%', cursor:'pointer',
                      color:'var(--fg)', fontSize:18, fontWeight:500,
                      fontFamily:'var(--font-mono)',
                    }}>{i+1}</button>
                  ))}
                </div>
                <div style={{ display:'flex', justifyContent:'space-between', marginTop:10, fontSize:11, color:'var(--fg-3)' }}>
                  <span>{q.options[0].label}</span>
                  <span>{q.options[q.options.length-1].label}</span>
                </div>
              </div>
            )}

          </div>
        </div>
      </div>
    </ScreenShell>
  );
}

// ─────────────────────────────────────────────────────────────
// SCREEN 4 — AI Analysis Loading
// ─────────────────────────────────────────────────────────────
function LoadingScreen({ onDone, runAnalysis, candidateId }) {
  const [step, setStep] = useState({ pct: 0, label: '啟動 AI 引擎' });
  useEffect(() => {
    let cancelled = false;
    runAnalysis(candidateId, (s) => { if (!cancelled) setStep(s); })
      .then(({ reportId }) => { if (!cancelled) setTimeout(() => onDone(reportId), 400); });
    return () => { cancelled = true; };
  }, [candidateId]);

  return (
    <ScreenShell bg="radial-gradient(ellipse at center, #2A1F4D 0%, #0B0E18 55%, #06070D 100%)" pad={false} scrollable={false}>
      <div style={{ height: '100%', display: 'flex', flexDirection: 'column',
                    alignItems: 'center', justifyContent: 'center', padding: 24,
                    position: 'relative' }}>
        <div style={{ position: 'absolute', inset: 0, opacity: 0.5 }}>
          <Particles count={36}/>
        </div>

        {/* Rotating multi-ring */}
        <div style={{ animation: 'spin 12s linear infinite' }}>
          <MultiRing a={0.78} b={0.62} c={0.55} size={200}/>
        </div>
        <div style={{ position: 'absolute', textAlign: 'center', marginTop: -8 }}>
          <div className="num" style={{
            fontSize: 44, fontWeight: 600, color: 'var(--fg)',
            background: 'linear-gradient(120deg, #FFFFFF, #B07CFF)',
            WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent',
          }}>{step.pct}<span style={{ fontSize: 18, color: 'var(--fg-3)' }}>%</span></div>
        </div>

        <div style={{ marginTop: 60, textAlign: 'center' }}>
          <div style={{ fontSize: 11, color: 'var(--purple)', letterSpacing: '0.3em', marginBottom: 8 }}>
            AI ANALYSIS
          </div>
          <div style={{ fontSize: 18, fontWeight: 500, color: 'var(--fg)' }}>
            {step.label}
          </div>
        </div>

        {/* progress bar */}
        <div style={{ marginTop: 20, width: 240, height: 4, borderRadius: 99,
                      background: 'rgba(255,255,255,0.08)', overflow: 'hidden' }}>
          <div style={{
            width: `${step.pct}%`, height: '100%',
            background: 'linear-gradient(90deg, #2BD4A8, #5BA9FF 40%, #B07CFF 70%, #FF5DA2)',
            transition: 'width 400ms cubic-bezier(.2,.8,.2,1)',
            boxShadow: '0 0 8px rgba(176,124,255,0.6)',
          }}/>
        </div>

        <div style={{ marginTop: 40, fontSize: 11, color: 'var(--fg-3)', maxWidth: 280, textAlign: 'center', lineHeight: 1.8 }}>
          交叉計算 八字流年 × 心理學維度 × 原生家庭<br/>
          為你產出 AI 職涯導航參考報告
        </div>
      </div>
    </ScreenShell>
  );
}

// ─────────────────────────────────────────────────────────────
// SCREEN 4.5 — Paywall (隔在 Phase 1 與 Phase 2 之間)
// ─────────────────────────────────────────────────────────────
function PaywallScreen({ content, onBack, onUnlock, onSkip }) {
  const [selected, setSelected] = useState('month');
  const [submitting, setSubmitting] = useState(false);

  if (!content) return <ScreenShell><LoadingDots/></ScreenShell>;

  const unlock = async () => {
    setSubmitting(true);
    await onUnlock(selected);
    setSubmitting(false);
  };

  return (
    <ScreenShell bg="radial-gradient(ellipse at top, #2A1F4D 0%, #0B0E18 55%, #06070D 100%)">
      <TopBar onBack={onBack} title=""/>

      <div style={{ position: 'absolute', inset: 0, opacity: 0.35, pointerEvents: 'none' }}>
        <Particles count={20}/>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginTop: 4 }}>
        {/* lock orb */}
        <div style={{ position: 'relative', marginBottom: 18 }}>
          <Blob size={84}/>
          <div style={{
            position: 'absolute', inset: 0, display: 'flex',
            alignItems: 'center', justifyContent: 'center',
          }}>
            <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="2"
                 strokeLinecap="round" strokeLinejoin="round" style={{ filter:'drop-shadow(0 0 6px rgba(255,255,255,0.8))' }}>
              <rect x="4" y="11" width="16" height="10" rx="2"/>
              <path d="M8 11V7a4 4 0 018 0v4"/>
            </svg>
          </div>
        </div>

        <div style={{ fontSize: 10, color: 'var(--purple)', letterSpacing: '0.36em', fontWeight: 600 }}>{content.eyebrow}</div>
        <h2 style={{ margin: '6px 0 8px', fontSize: 28, fontWeight: 700, textAlign: 'center', letterSpacing: '0.02em' }}>
          {content.heading}
        </h2>
        <p style={{ margin: 0, fontSize: 13, color: 'var(--fg-2)', lineHeight: 1.85, textAlign: 'center', whiteSpace: 'pre-line' }}>
          {content.pitch}
        </p>
      </div>

      {/* includes list */}
      <Card pad={16} style={{ marginTop: 22,
        background: 'linear-gradient(165deg, #1A1738 0%, #271A3E 100%)',
        border: '1px solid rgba(176,124,255,0.25)' }}>
        <div style={{ fontSize: 11, color: 'var(--purple)', letterSpacing: '0.2em', marginBottom: 10 }}>付費後可解鎖</div>
        <ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 8 }}>
          {content.includes.map((it, i) => (
            <li key={i} style={{ display: 'flex', alignItems: 'flex-start', gap: 10, fontSize: 13, color: 'var(--fg)' }}>
              <span style={{
                flexShrink: 0, marginTop: 4, width: 14, height: 14, borderRadius: '50%',
                background: 'linear-gradient(135deg, #2BD4A8, #5BA9FF)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
              }}>
                <svg width="8" height="8" viewBox="0 0 24 24" fill="none" stroke="#fff" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
                  <polyline points="20 6 9 17 4 12"/>
                </svg>
              </span>
              <span>{it}</span>
            </li>
          ))}
        </ul>
      </Card>

      {/* plan selector */}
      <div style={{ marginTop: 16, display: 'flex', flexDirection: 'column', gap: 10 }}>
        {content.plans.map(p => {
          const active = p.id === selected;
          return (
            <button key={p.id} onClick={() => setSelected(p.id)} style={{
              textAlign: 'left', cursor: 'pointer',
              background: active ? 'linear-gradient(120deg, rgba(176,124,255,0.18), rgba(255,93,162,0.10))' : 'rgba(255,255,255,0.04)',
              border: `1.5px solid ${active ? 'var(--purple)' : 'var(--line)'}`,
              borderRadius: 16, padding: '14px 16px',
              display: 'flex', alignItems: 'center', gap: 14,
              fontFamily: 'inherit', color: 'var(--fg)', position: 'relative',
              transition: 'all 140ms cubic-bezier(.2,.8,.2,1)',
            }}>
              <div style={{
                flexShrink: 0, width: 22, height: 22, borderRadius: '50%',
                border: `2px solid ${active ? 'var(--purple)' : 'var(--line-strong)'}`,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                background: active ? 'var(--purple)' : 'transparent',
              }}>
                {active && <span style={{ width: 8, height: 8, borderRadius: '50%', background: '#fff' }}/>}
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span style={{ fontSize: 15, fontWeight: 600 }}>{p.label}</span>
                  {p.recommended && (
                    <span style={{
                      fontSize: 10, padding: '2px 8px', borderRadius: 99,
                      background: 'linear-gradient(120deg, #B07CFF, #FF5DA2)',
                      color: '#fff', fontWeight: 600,
                    }}>推薦</span>
                  )}
                </div>
                <div style={{ fontSize: 11, color: 'var(--fg-3)', marginTop: 2 }}>{p.sub}</div>
              </div>
              <div style={{ textAlign: 'right' }}>
                <div className="num" style={{ fontSize: 22, fontWeight: 600,
                                              color: active ? 'var(--fg)' : 'var(--fg-2)' }}>
                  NT$ {p.price}
                </div>
                <div style={{ fontSize: 10, color: 'var(--fg-3)' }}>{p.id === 'month' ? '/ 月' : '/ 一次'}</div>
              </div>
            </button>
          );
        })}
      </div>

      <div style={{ marginTop: 12, fontSize: 10, color: 'var(--fg-3)', textAlign: 'center' }}>
        付款協力：{content.provider}
      </div>

      <div style={{ marginTop: 16 }}>
        <GlowButton onClick={unlock} disabled={submitting}>
          {submitting ? '連線中…' : '解鎖 Phase 2'}
        </GlowButton>
      </div>

      <div style={{ marginTop: 12, textAlign: 'center' }}>
        <button onClick={onSkip} style={{
          background: 'transparent', border: 'none', cursor: 'pointer',
          color: 'var(--fg-3)', fontSize: 12, fontFamily: 'inherit',
        }}>跳過，檢視 Phase 1 簡略報告 ›</button>
      </div>

      <div style={{ marginTop: 10, fontSize: 10, color: 'var(--fg-4)', textAlign: 'center', lineHeight: 1.7 }}>
        {content.footnote}
      </div>

      <div style={{ height: 24 }}/>
    </ScreenShell>
  );
}

// ─────────────────────────────────────────────────────────────
// SCREEN 5 — Dashboard (今日命運總覽)
// TODO [BlockLib-extract]: DashboardScreen → 'Dashboard 分數卡片 Block' candidate.
// MultiRing / PillarCard / ActionCard 為通用 UI 元件，分數資料可由 ScoreSet 介面傳入。
// ─────────────────────────────────────────────────────────────
function DashboardScreen({ profile, report, onAction, onSchedule, onOpenReport, onHome }) {
  if (!report || !profile) return <ScreenShell><LoadingDots/></ScreenShell>;
  const s = report.scores;
  const rings = { a: s.tianMing/100, b: s.dili/100, c: s.renhe/100 };

  return (
    <ScreenShell>
      <TopBar
        title="今日命運總覽"
        onBack={onHome}
        progress={profile.id}
        right={
          <button onClick={onOpenReport} style={{
            background: 'linear-gradient(135deg, rgba(176,124,255,0.18), rgba(255,93,162,0.18))',
            border: '1px solid rgba(176,124,255,0.3)',
            padding: '6px 12px', borderRadius: 99, color: 'var(--purple)',
            fontSize: 12, fontFamily: 'inherit', cursor: 'pointer',
          }}>個人報告 ›</button>
        }
      />

      <div style={{ marginTop: 8 }}>
        <div style={{ fontSize: 28, fontWeight: 700, letterSpacing: '0.02em' }}>
          {profile.name}
        </div>
        <div style={{ fontSize: 12, color: 'var(--fg-3)', marginTop: 2 }}>
          {report.bazi.decade} · {report.bazi.year} · {profile.mbti}
        </div>
      </div>

      {/* Main rings card */}
      <div style={{ marginTop: 16 }}>
        <Card style={{ background: 'linear-gradient(165deg, #141930 0%, #0E1224 100%)' }} pad={14}>
          <div style={{ display: 'flex', alignItems: 'flex-start', gap: 10 }}>
            <div style={{ flexShrink: 0, marginTop: -2 }}>
              <MultiRing a={rings.a} b={rings.b} c={rings.c} size={132}/>
            </div>
            <div style={{ flex: 1, minWidth: 0, paddingTop: 2 }}>
              <div style={{ fontSize: 13, color: 'var(--fg)', fontWeight: 600, marginBottom: 6, letterSpacing: '0.05em' }}>事業版圖</div>
              <DashRow label="天命覺醒" value={`${s.tianMing}/100`} color="var(--neon-green)"/>
              <DashRow label="能量共振" value={`${s.resonance}/100`} color="var(--neon-teal)"/>
              <DashRow label="天 · 地 · 人" value={`${s.tianshi}·${s.dili}·${s.renhe}`} color="var(--pink-soft)"/>
              <DashRow label="整體匹配" value={`${s.fit}%`} color="var(--neon-teal)"/>
            </div>
            <div style={{ flexShrink: 0, width: 70, paddingTop: 2 }}>
              <DashSmall label="事業轉折" value={s.careerTurn} color="var(--magenta)"/>
              <DashSmall label="貴人機遇" value={s.benefactor} color="var(--neon-green)"/>
              <DashSmall label="動機指數" value={s.motivation} color="var(--gold)"/>
            </div>
          </div>
          <div style={{ marginTop: 12 }}><TickStrip/></div>
        </Card>
      </div>

      {/* Three pillar cards */}
      <div style={{ display: 'flex', gap: 10, marginTop: 14 }}>
        <PillarCard color="var(--gold)"      label="天時" score={s.tianshi} caption={report.bazi.year}/>
        <PillarCard color="var(--neon-green)"label="地利" score={s.dili}    caption="位能評估"/>
        <PillarCard color="var(--magenta)"   label="人和" score={s.renhe}   caption={profile.mbti}/>
      </div>

      {/* Action cards */}
      <div style={{ marginTop: 14 }}>
        <SectionHead title="今日行動建議" count={report.actions.length}/>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginTop: 10 }}>
          {report.actions.map((a, i) => (
            <ActionCard key={a.id} action={a} accent={['var(--gold)','var(--neon-green)','var(--magenta)'][i % 3]}
                        onClick={() => onAction(a)}/>
          ))}
        </div>
      </div>

      {/* Schedule CTA */}
      <div style={{ marginTop: 18 }}>
        <Card pad={16} style={{ background: 'linear-gradient(120deg, rgba(176,124,255,0.18), rgba(255,93,162,0.10))',
                                border: '1px solid rgba(176,124,255,0.3)' }}>
          <div style={{ fontSize: 11, color: 'var(--purple)', letterSpacing: '0.3em' }}>NEXT STEP</div>
          <div style={{ fontSize: 18, fontWeight: 600, marginTop: 6 }}>預約職涯面談</div>
          <div style={{ fontSize: 12, color: 'var(--fg-2)', marginTop: 6, lineHeight: 1.6 }}>
            流年走偏財，建議在 30 天內完成決策。<br/>
            選擇 30 分鐘的深度對談，我們為你準備命盤對位。
          </div>
          <div style={{ marginTop: 14 }}>
            <GlowButton onClick={onSchedule}>預約 30 分鐘面談</GlowButton>
          </div>
        </Card>
      </div>

      <div style={{ height: 24 }}/>
    </ScreenShell>
  );
}

function DashRow({ label, value, color }) {
  return (
    <div style={{ marginTop: 4, display: 'flex', alignItems: 'baseline', gap: 4, whiteSpace: 'nowrap', fontSize: 11.5 }}>
      <span style={{ color: 'var(--fg-2)' }}>{label}</span>
      <span style={{ color: 'var(--fg-3)', opacity: 0.5 }}>:</span>
      <span className="num" style={{ color, fontSize: 14, fontWeight: 500 }}>{value}</span>
    </div>
  );
}
function DashSmall({ label, value, color }) {
  return (
    <div style={{ marginBottom: 6, whiteSpace: 'nowrap' }}>
      <div style={{ fontSize: 11, color: 'var(--fg-2)' }}>{label}</div>
      <div className="num" style={{ fontSize: 14, color, fontWeight: 500 }}>{value}</div>
    </div>
  );
}
function SectionHead({ title, count }) {
  return (
    <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', padding: '0 2px' }}>
      <span style={{ fontSize: 13, color: 'var(--fg)', fontWeight: 600, letterSpacing: '0.05em' }}>{title}</span>
      {count !== undefined && <span style={{ fontSize: 11, color: 'var(--fg-3)' }} className="num">{count}</span>}
    </div>
  );
}

function PillarCard({ color, label, score, caption }) {
  const pct = Math.min(100, score) / 100;
  return (
    <div style={{
      flex: 1, background: 'var(--bg-card)',
      border: '1px solid var(--line)', borderRadius: 18, padding: 12,
      position: 'relative', overflow: 'hidden',
    }}>
      <div style={{ position: 'absolute', top: -10, right: -10, width: 60, height: 60,
                    borderRadius: '50%', background: color, opacity: 0.12, filter: 'blur(20px)' }}/>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between' }}>
        <span style={{ fontSize: 12, color: 'var(--fg-2)' }}>{label}</span>
        <span style={{ width: 6, height: 6, borderRadius: 99, background: color,
                       boxShadow: `0 0 6px ${color}` }}/>
      </div>
      <div className="num" style={{ fontSize: 26, fontWeight: 600, color: 'var(--fg)', marginTop: 4, lineHeight: 1 }}>
        {score}
      </div>
      <div style={{ marginTop: 6, height: 4, borderRadius: 99, background: 'rgba(255,255,255,0.06)' }}>
        <div style={{ width: `${pct*100}%`, height: '100%', borderRadius: 99, background: color,
                       boxShadow: `0 0 6px ${color}` }}/>
      </div>
      <div style={{ fontSize: 10, color: 'var(--fg-3)', marginTop: 6, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
        {caption}
      </div>
    </div>
  );
}

function ActionCard({ action, accent, onClick }) {
  const iconMap = { meet: '◐', reflect: '✦', connect: '✺', study: '✧' };
  return (
    <button onClick={onClick} style={{
      width: '100%', textAlign: 'left',
      background: 'var(--bg-card)', border: '1px solid var(--line)',
      borderRadius: 16, padding: 14, cursor: 'pointer',
      display: 'flex', gap: 12, alignItems: 'center',
      fontFamily: 'inherit', color: 'var(--fg)',
    }}>
      <div style={{
        flexShrink: 0, width: 40, height: 40, borderRadius: 12,
        background: `linear-gradient(135deg, ${accent}33, ${accent}11)`,
        border: `1px solid ${accent}44`,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        color: accent, fontSize: 20,
        filter: `drop-shadow(0 0 4px ${accent}33)`,
      }}>{iconMap[action.kind] || '◇'}</div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--fg)' }}>{action.title}</div>
        <div style={{ fontSize: 11, color: 'var(--fg-3)', marginTop: 2 }}>{action.subtitle}</div>
      </div>
      <div style={{ fontSize: 11, color: accent, fontWeight: 500, whiteSpace: 'nowrap' }}>{action.ctaLabel} ›</div>
    </button>
  );
}

// ─────────────────────────────────────────────────────────────
// SCREEN 6 — Personalised Report
// TODO [BlockLib-extract]: ReportScreen → 'AI 報告生成 Block' candidate.
// TONE_LABELS 為語氣設定層，未來可由 block config / 客戶模板傳入。
// ─────────────────────────────────────────────────────────────
const TONE_LABELS = {
  spiritual: { eyebrow:'靈魂解讀', verdict:'導航結論', talent:'靈魂原型', moment:'流年使命', family:'原生家庭力量', quote:'靈魂召喚', why:'為什麼靈魂不選歸路', cta:'預約靈魂對話' },
  data:      { eyebrow:'評估結果', verdict:'業務適配概述', talent:'能力分布', moment:'動機走勢', family:'家庭背景分析', quote:'關鍵提醒', why:'為什麼現在適合加入', cta:'預約 30 分鐘面談' },
  hybrid:    { eyebrow:'FOR', verdict:'VERDICT', talent:'天賦解讀', moment:'流年時機', family:'原生家庭力量', quote:'核心語錄', why:'為什麼適合現在加入', cta:'預約 30 分鐘職涯面談' },
};

function getUserVerdict(fit) {
  if (fit >= 85) return '你的命盤能量與這個舞台高度共鳴，時機、動機與資源在這個節點聚合，是向前一步的好時節。';
  if (fit >= 70) return '你具備在這個方向發展的核心潛能，透過一次深入對話，能更清楚看見屬於你的位置。';
  if (fit >= 55) return '你正處於醞釀與探索的階段，每個選擇都在累積能量，值得慢慢聆聽內心的方向。';
  return '你的命盤揭示了獨特的節奏與韌性，當前時機在靜中等待，這不是停滯而是蓄勢。';
}

function ReportScreen({ profile, report, onBack, onSchedule, tone = 'hybrid' }) {
  if (!report || !profile) return <ScreenShell><LoadingDots/></ScreenShell>;
  const s = report.scores;
  const L = TONE_LABELS[tone] || TONE_LABELS.hybrid;
  const aiReport = report.aiReport || null;
  const aiUser   = aiReport && aiReport.userReport   ? aiReport.userReport   : null;
  const aiSafety = aiReport && aiReport.safety       ? aiReport.safety       : null;

  return (
    <ScreenShell>
      <TopBar onBack={onBack} title="AI 職涯導航參考報告"
              right={<button style={{
                background: 'rgba(255,255,255,0.06)', border: '1px solid var(--line)',
                width: 36, height: 36, borderRadius: 12, cursor: 'pointer',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
              }}>
                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="var(--fg-2)" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M4 12v8a2 2 0 002 2h12a2 2 0 002-2v-8M16 6l-4-4-4 4M12 2v14"/>
                </svg>
              </button>}/>

      <div style={{ marginTop: 8 }}>
        <div style={{ fontSize: 11, color: 'var(--fg-3)', letterSpacing: '0.3em' }}>{L.eyebrow} · {profile.name}</div>
        <div style={{ fontSize: 26, fontWeight: 700, marginTop: 4 }}>
          {aiUser ? aiUser.title : '你的事業版圖'}
        </div>
        <div style={{ fontSize: 12, color: 'var(--fg-3)', marginTop: 2 }}>
          {report.bazi.dayMaster} · {report.bazi.decade} · {report.bazi.year}
        </div>
      </div>

      {/* AI Opening — 個人化開場段落，無 aiReport 時不顯示 */}
      {aiUser && aiUser.opening && (
        <div style={{
          marginTop: 14, padding: '12px 14px', borderRadius: 12,
          background: 'rgba(176,124,255,0.06)',
          border: '1px solid rgba(176,124,255,0.14)',
          fontSize: 13, lineHeight: 1.85, color: 'var(--fg-2)',
        }}>
          <div style={{ fontSize: 9, color: 'var(--purple)', letterSpacing: '0.28em', marginBottom: 6 }}>AI · 個人化導航</div>
          {aiUser.opening}
        </div>
      )}

      {/* Hero — fit score + verdict */}
      <Card style={{ marginTop: 18, background: 'linear-gradient(165deg, #1F1A38 0%, #2B1F3D 100%)',
                     border: '1px solid rgba(176,124,255,0.25)' }} pad={18}>
        <div style={{ display: 'flex', alignItems: 'flex-start', gap: 14 }}>
          <div style={{ position: 'relative' }}>
            <CircleScore value={s.fit} size={92} color="var(--purple)"/>
          </div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 10, color: 'var(--purple)', letterSpacing: '0.3em' }}>{L.verdict}</div>
            <div style={{ fontSize: 14, color: 'var(--fg)', marginTop: 4, lineHeight: 1.65 }}>
              {getUserVerdict(s.fit)}
            </div>
          </div>
        </div>
      </Card>

      {/* AI 人格風格卡 — 有 aiReport 時顯示 */}
      {aiUser && aiUser.personalityStyle && (
        <Card pad={14} style={{ marginTop: 16,
          background: 'rgba(91,169,255,0.05)',
          border: '1px solid rgba(91,169,255,0.18)' }}>
          <div style={{ fontSize: 9, color: 'var(--blue)', letterSpacing: '0.28em', marginBottom: 6 }}>行動風格傾向</div>
          <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--fg)', lineHeight: 1.55, marginBottom: 6 }}>
            {aiUser.personalityStyle.headline}
          </div>
          <div style={{ fontSize: 12, color: 'var(--fg-3)', lineHeight: 1.8 }}>
            {aiUser.personalityStyle.detail}
          </div>
        </Card>
      )}

      {/* Radar — 5 axes */}
      <Section title={L.talent} subtitle="心理學 × 八字 × 原生家庭">
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <Radar values={[
            { label:'動機', value: s.motivation/200 },
            { label:'天時', value: s.tianshi/100 },
            { label:'地利', value: s.dili/100 },
            { label:'人和', value: s.renhe/100 },
            { label:'貴人', value: s.benefactor/100 },
          ]} size={160}/>
          <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 6 }}>
            <Stars filled={report.talent.stars}/>
            <div style={{ fontSize: 11, color: 'var(--fg-3)', marginTop: 6, lineHeight: 1.8 }}>
              影響力導向，<br/>適合具備舞台的職位。<br/>動機驅動偏中高。
            </div>
          </div>
        </div>
      </Section>

      {/* 流年時機 */}
      <Section title={L.moment} subtitle={`${report.bazi.decade} · ${report.bazi.year}`}>
        <div style={{ marginLeft: -4 }}>
          <PotentialChart data={{ gold: report.chartSeries.motivation, magenta: report.chartSeries.events }}
                          w={350} h={120}/>
        </div>
        <div style={{ display: 'flex', gap: 6, marginTop: 4, flexWrap: 'wrap' }}>
          <Chip color="var(--gold)" text="流年走偏財"/>
          <Chip color="var(--neon-green)" text="驛馬星啟動"/>
          <Chip color="var(--magenta)" text="貴人月份：6 / 9 / 11"/>
        </div>
      </Section>

      {/* 地利 · 單位資源匹配 */}
      <Section title="地利 · 單位資源匹配" subtitle="攝影棚 / 遊戲池 / 家庭支援">
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8 }}>
          <DiliCell label="攝影棚"   sub="個人品牌" value={report.diliBreakdown?.studio || 70}        color="var(--purple)"/>
          <DiliCell label="遊戲池"   sub="業務隊伍" value={report.diliBreakdown?.gamePool || 70}      color="var(--neon-green)"/>
          <DiliCell label="家庭支援" sub="原生需求" value={report.diliBreakdown?.familySupport || 70} color="var(--gold)"/>
        </div>
      </Section>

      {/* 原生家庭力量 */}
      <Section title={L.family} subtitle="DISC + 家庭問卷交叉">
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
          <MiniStat label="安全感" value={62} color="var(--neon-green)"/>
          <MiniStat label="匱乏驅動" value={48} color="var(--magenta)"/>
          <MiniStat label="責任承擔" value={78} color="var(--gold)"/>
          <MiniStat label="自我表達" value={84} color="var(--purple)"/>
        </div>
      </Section>

      {/* Quote */}
      {tone !== 'data' && (
        <Card pad={16} style={{
          marginTop: 16,
          background: 'linear-gradient(120deg, rgba(176,124,255,0.10), rgba(255,93,162,0.06))',
          border: '1px solid rgba(176,124,255,0.18)',
        }}>
          <div style={{ fontSize: 10, color: 'var(--purple)', letterSpacing: '0.3em', marginBottom: 8 }}>{L.quote}</div>
          <div style={{ fontSize: 15, lineHeight: 1.9, color: 'var(--fg)', whiteSpace: 'pre-line' }}>
            {(aiUser && aiUser.coreMotivation && aiUser.coreMotivation.resonanceStatement)
              || (report.interpretation && report.interpretation.quote)
              || report.quote}
          </div>
        </Card>
      )}

      {/* AI 成長建議 — 有 aiReport 時顯示 */}
      {aiUser && aiUser.growthSuggestion && (
        <div style={{
          marginTop: 16, padding: '10px 14px', borderRadius: 12,
          background: 'rgba(43,212,168,0.05)',
          border: '1px solid rgba(43,212,168,0.15)',
          fontSize: 12, lineHeight: 1.8, color: 'var(--fg-3)',
        }}>
          <div style={{ fontSize: 9, color: 'var(--neon-teal)', letterSpacing: '0.28em', marginBottom: 4 }}>面談前建議</div>
          {aiUser.growthSuggestion}
        </div>
      )}

      {/* 為什麼適合加入 */}
      <Section title={L.why}>
        {report.interpretation && report.interpretation.userSummary ? (
          <div style={{ fontSize: 12, color: 'var(--fg-3)', lineHeight: 1.8, marginBottom: 10 }}>
            {report.interpretation.userSummary}
          </div>
        ) : null}
        <ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 8 }}>
          {(report.interpretation && report.interpretation.highlights && report.interpretation.highlights.length > 0)
            ? report.interpretation.highlights.map((text, i) => {
                const COLORS = ['var(--gold)', 'var(--neon-green)', 'var(--magenta)', 'var(--purple)', 'var(--neon-teal)', 'var(--blue)'];
                return <ReasonRow key={i} color={COLORS[i % COLORS.length]} idx={String(i + 1).padStart(2, '0')} text={text}/>;
              })
            : <>
                <ReasonRow color="var(--gold)"      idx="01" text="天時：流年走偏財，是建立業務管道的最佳窗口"/>
                <ReasonRow color="var(--neon-green)"idx="02" text="地利：高創單位的個人品牌資源匹配你的天賦"/>
                <ReasonRow color="var(--magenta)"   idx="03" text="人和：人和指數高，適合走推薦制 × 影響型業務"/>
              </>
          }
        </ul>
      </Section>

      {/* 顧問備注（HR 可見，僅在有動態解讀時顯示）— TODO [BlockLib-extract]: advisorNotes 可由 block config 控制顯示對象 */}
      {report.interpretation && report.interpretation.advisorNotes && report.interpretation.advisorNotes.length > 0 && (
        <div style={{
          marginTop: 16, padding: '12px 14px', borderRadius: 12,
          background: 'rgba(254,188,46,0.05)',
          border: '1px solid rgba(254,188,46,0.18)',
        }}>
          <div style={{ fontSize: 10, color: 'var(--gold)', letterSpacing: '0.25em', marginBottom: 6 }}>顧問備注</div>
          {report.interpretation.advisorNotes.map((note, i) => (
            <div key={i} style={{ fontSize: 11, color: 'var(--fg-3)', lineHeight: 1.75 }}>· {note}</div>
          ))}
        </div>
      )}

      {/* 法律聲明 — TODO [BlockLib-extract]: 聲明文字可由 block config 傳入，各客戶自訂 */}
      <div style={{
        marginTop: 20, padding: '12px 16px', borderRadius: 12,
        background: 'rgba(255,255,255,0.02)',
        border: '1px solid var(--line)',
        fontSize: 11, color: 'var(--fg-4)', lineHeight: 1.9, textAlign: 'center',
      }}>
        {aiSafety && aiSafety.disclaimer
          ? aiSafety.disclaimer
          : '本報告僅作為職涯探索與面談參考，不作為正式心理診斷，亦不作為錄取或人事決策的唯一依據。'}
        {aiSafety && aiSafety.confidenceNote && (
          <div style={{ marginTop: 6, opacity: 0.75 }}>{aiSafety.confidenceNote}</div>
        )}
      </div>

      <div style={{ height: 16 }}/>
      <GlowButton onClick={onSchedule}>{L.cta}</GlowButton>
      <div style={{ height: 32 }}/>
    </ScreenShell>
  );
}

// Dili cell — 3-up breakdown of 地利 resources
function DiliCell({ label, sub, value, color }) {
  const r = 22, cx = 28, cy = 28;
  const C = 2 * Math.PI * r;
  return (
    <div style={{ background: 'rgba(255,255,255,0.04)', border: '1px solid var(--line)',
                  borderRadius: 12, padding: 10, display: 'flex', alignItems: 'center', gap: 10 }}>
      <svg width="56" height="56" viewBox="0 0 56 56">
        <circle cx={cx} cy={cy} r={r} fill="none" stroke="rgba(255,255,255,0.06)" strokeWidth="4"/>
        <circle cx={cx} cy={cy} r={r} fill="none" stroke={color} strokeWidth="4" strokeLinecap="round"
                strokeDasharray={`${C * value/100} ${C}`}
                transform={`rotate(-90 ${cx} ${cy})`}
                style={{ filter: `drop-shadow(0 0 4px ${color})` }}/>
        <text x={cx} y={cy+4} textAnchor="middle" fontSize="12" fontWeight="600" fill="var(--fg)" fontFamily="var(--font-mono)">{value}</text>
      </svg>
      <div>
        <div style={{ fontSize: 11, color: 'var(--fg)', fontWeight: 500 }}>{label}</div>
        <div style={{ fontSize: 9, color: 'var(--fg-3)' }}>{sub}</div>
      </div>
    </div>
  );
}

function Section({ title, subtitle, children }) {
  return (
    <div style={{ marginTop: 18 }}>
      <div style={{ padding: '0 2px 8px' }}>
        <div style={{ fontSize: 13, color: 'var(--fg)', fontWeight: 600, letterSpacing: '0.05em' }}>{title}</div>
        {subtitle && <div style={{ fontSize: 11, color: 'var(--fg-3)', marginTop: 2 }}>{subtitle}</div>}
      </div>
      <Card pad={14}>{children}</Card>
    </div>
  );
}
function MiniStat({ label, value, color }) {
  return (
    <div style={{ background: 'rgba(255,255,255,0.04)', borderRadius: 12, padding: '10px 12px',
                  border: '1px solid var(--line)' }}>
      <div style={{ fontSize: 11, color: 'var(--fg-2)' }}>{label}</div>
      <div className="num" style={{ fontSize: 22, color, fontWeight: 500, marginTop: 2 }}>{value}</div>
      <div style={{ marginTop: 6, height: 3, borderRadius: 99, background: 'rgba(255,255,255,0.06)' }}>
        <div style={{ width: `${value}%`, height: '100%', borderRadius: 99, background: color }}/>
      </div>
    </div>
  );
}
function Chip({ color, text }) {
  return (
    <span style={{
      fontSize: 11, padding: '4px 10px', borderRadius: 99,
      background: `${color}1A`, color, border: `1px solid ${color}33`,
    }}>{text}</span>
  );
}
function ReasonRow({ color, idx, text }) {
  return (
    <li style={{ display: 'flex', alignItems: 'flex-start', gap: 10, padding: '8px 0' }}>
      <span className="num" style={{
        flexShrink: 0, width: 28, height: 28, borderRadius: 8,
        background: `${color}1A`, color, border: `1px solid ${color}33`,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontSize: 11, fontWeight: 600,
      }}>{idx}</span>
      <span style={{ fontSize: 13, lineHeight: 1.7, color: 'var(--fg-2)' }}>{text}</span>
    </li>
  );
}

// Circle score for hero
function CircleScore({ value, size = 90, color = 'var(--purple)' }) {
  const r = size/2 - 6, cx = size/2, cy = size/2;
  const C = 2 * Math.PI * r;
  return (
    <div style={{ position: 'relative', width: size, height: size }}>
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
        <circle cx={cx} cy={cy} r={r} fill="none" stroke="rgba(255,255,255,0.06)" strokeWidth="6"/>
        <circle cx={cx} cy={cy} r={r} fill="none" stroke={color} strokeWidth="6" strokeLinecap="round"
                strokeDasharray={`${C * value/100} ${C}`}
                transform={`rotate(-90 ${cx} ${cy})`}
                style={{ filter: `drop-shadow(0 0 6px ${color})` }}/>
      </svg>
      <div style={{
        position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column',
        alignItems: 'center', justifyContent: 'center',
      }}>
        <span className="num" style={{ fontSize: 28, fontWeight: 600, color: 'var(--fg)', lineHeight: 1 }}>{value}</span>
        <span style={{ fontSize: 9, color: 'var(--fg-3)', letterSpacing: '0.2em' }}>FIT</span>
      </div>
    </div>
  );
}

// 5-axis radar
function Radar({ values, size = 160 }) {
  const cx = size/2, cy = size/2, r = size/2 - 14;
  const n = values.length;
  const pt = (i, k) => {
    const a = -Math.PI/2 + (i / n) * 2 * Math.PI;
    return [cx + Math.cos(a) * r * k, cy + Math.sin(a) * r * k];
  };
  const rings = [0.25, 0.5, 0.75, 1];
  const polygonPts = (k) => Array.from({ length: n }).map((_, i) => pt(i, k).join(',')).join(' ');
  const valPolygon = values.map((v, i) => pt(i, v.value).join(',')).join(' ');

  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
      <defs>
        <radialGradient id="radarGrad" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor="#B07CFF" stopOpacity="0.45"/>
          <stop offset="100%" stopColor="#FF5DA2" stopOpacity="0.15"/>
        </radialGradient>
      </defs>
      {rings.map(k => (
        <polygon key={k} points={polygonPts(k)} fill="none" stroke="rgba(255,255,255,0.06)"/>
      ))}
      {Array.from({ length: n }).map((_, i) => {
        const [x, y] = pt(i, 1);
        return <line key={i} x1={cx} y1={cy} x2={x} y2={y} stroke="rgba(255,255,255,0.05)"/>;
      })}
      <polygon points={valPolygon} fill="url(#radarGrad)" stroke="var(--purple)" strokeWidth="1.5"
               style={{ filter: 'drop-shadow(0 0 4px rgba(176,124,255,0.6))' }}/>
      {values.map((v, i) => {
        const [x, y] = pt(i, v.value);
        return <circle key={i} cx={x} cy={y} r="3" fill="#fff"
                       style={{ filter: 'drop-shadow(0 0 3px #fff)' }}/>;
      })}
      {values.map((v, i) => {
        const [x, y] = pt(i, 1.18);
        return (
          <text key={i} x={x} y={y} textAnchor="middle" fontSize="10"
                fill="var(--fg-2)" dy="3">{v.label}</text>
        );
      })}
    </svg>
  );
}

// ─────────────────────────────────────────────────────────────
// Shared helpers
// ─────────────────────────────────────────────────────────────
function GlowButton({ children, onClick, disabled }) {
  return (
    <button onClick={onClick} disabled={disabled} style={{
      width: '100%',
      background: disabled
        ? 'rgba(255,255,255,0.06)'
        : 'linear-gradient(120deg, #B07CFF 0%, #FF5DA2 100%)',
      border: 'none', borderRadius: 16, padding: '16px 24px',
      color: '#fff', fontSize: 16, fontWeight: 600,
      fontFamily: 'inherit',
      cursor: disabled ? 'not-allowed' : 'pointer',
      opacity: disabled ? 0.4 : 1,
      boxShadow: disabled ? 'none' : '0 8px 24px rgba(176,124,255,0.35), 0 0 0 1px rgba(255,255,255,0.08) inset',
      transition: 'all 120ms cubic-bezier(.2,.8,.2,1)',
    }}>{children}</button>
  );
}

function BottomCTA({ children }) {
  return (
    <div style={{
      position: 'sticky', bottom: 0, marginTop: 'auto',
      padding: '14px 0 8px',
      background: 'linear-gradient(180deg, rgba(11,14,24,0) 0%, rgba(11,14,24,0.95) 35%, var(--bg-page) 100%)',
    }}>{children}</div>
  );
}

function LoadingDots() {
  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center',
                  height: '100%', gap: 6 }}>
      {[0,1,2].map(i => (
        <span key={i} style={{
          width: 6, height: 6, borderRadius: '50%', background: 'var(--purple)',
          animation: `pulse 1s ease-in-out ${i*0.15}s infinite`,
        }}/>
      ))}
    </div>
  );
}

function Particles({ count = 24 }) {
  const dots = useMemo(() => Array.from({ length: count }).map((_, i) => ({
    x: Math.random() * 100, y: Math.random() * 100,
    s: 1 + Math.random() * 2, d: 2 + Math.random() * 4,
    o: 0.2 + Math.random() * 0.6,
  })), [count]);
  return (
    <svg width="100%" height="100%" style={{ position: 'absolute', inset: 0 }}>
      {dots.map((p, i) => (
        <circle key={i} cx={`${p.x}%`} cy={`${p.y}%`} r={p.s}
                fill="#B07CFF" opacity={p.o}
                style={{ filter: 'drop-shadow(0 0 3px #B07CFF)',
                         animation: `twinkle ${p.d}s ease-in-out ${i*0.1}s infinite alternate` }}/>
      ))}
    </svg>
  );
}

// expose
Object.assign(window, {
  WelcomeScreen, ProfileScreen, QuizScreen, LoadingScreen, PaywallScreen,
  DashboardScreen, ReportScreen,
  GlowButton, ScreenShell, TopBar, BottomCTA, Particles,
});
