diff --git a/src/pages/saju/views/saju.mobile.jsx b/src/pages/saju/views/saju.mobile.jsx
new file mode 100644
index 0000000..7c0dd0c
--- /dev/null
+++ b/src/pages/saju/views/saju.mobile.jsx
@@ -0,0 +1,424 @@
+import React, { useState } from 'react';
+import { useNavigate } from 'react-router-dom';
+import TopRibbon from '../_shell/TopRibbon';
+import TitleBlock from '../_shell/TitleBlock';
+import Mascot from '../_shell/Mascot';
+import MascotBubble from '../_shell/MascotBubble';
+import OrnateFrame from '../_shell/OrnateFrame';
+import OrnamentBloom from '../_shell/OrnamentBloom';
+import PrimaryButton from '../_shell/PrimaryButton';
+import { IconChevron, IconSparkle } from '../_shell/Icons';
+import deriveTraits from '../_shell/helpers/deriveTraits';
+import daeunLabel from '../_shell/helpers/daeunLabel';
+import hexA from '../_shell/helpers/hexA';
+
+// 한자 element key → english id (deriveTraits 입력 표준화)
+const HANJA_TO_ID = { '木': 'wood', '火': 'fire', '土': 'earth', '金': 'metal', '水': 'water' };
+const ID_TO_KO = { wood: '목', fire: '화', earth: '토', metal: '금', water: '수' };
+const ID_TO_CH = { wood: '木', fire: '火', earth: '土', metal: '金', water: '水' };
+const ID_TO_COLOR = {
+ wood: '#4E6B5C', fire: '#C04A4A', earth: '#A67B3F',
+ metal: '#D4AF37', water: '#3A5A8C',
+};
+
+function elementsByEngId(scores) {
+ if (!scores) return {};
+ const out = {};
+ for (const [hanja, val] of Object.entries(scores)) {
+ const id = HANJA_TO_ID[hanja];
+ if (id) out[id] = val;
+ }
+ return out;
+}
+
+function pillarStemColor(saju, pillarKey) {
+ const stem = saju?.[pillarKey]?.stem;
+ // 천간 → 오행 매핑 (간략 — 핵심 색만)
+ const STEM_EL = { '甲':'wood','乙':'wood','丙':'fire','丁':'fire','戊':'earth','己':'earth','庚':'metal','辛':'metal','壬':'water','癸':'water' };
+ return ID_TO_COLOR[STEM_EL[stem]] || '#1F2A44';
+}
+
+function pillarBranchColor(saju, pillarKey) {
+ const branch = saju?.[pillarKey]?.branch;
+ const BRANCH_EL = { '子':'water','丑':'earth','寅':'wood','卯':'wood','辰':'earth','巳':'fire','午':'fire','未':'earth','申':'metal','酉':'metal','戌':'earth','亥':'water' };
+ return ID_TO_COLOR[BRANCH_EL[branch]] || '#1F2A44';
+}
+
+const TABS = [
+ ['basic', '기본정보'],
+ ['chart', '사주명식'],
+ ['flow', '운세흐름'],
+ ['traits', '성향분석'],
+];
+
+export default function SajuMobile({ reading }) {
+ const [tab, setTab] = useState('basic');
+ const navigate = useNavigate();
+ const elementsObj = elementsByEngId(reading?.analysis_data?.element_scores);
+ const traits = deriveTraits(elementsObj, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ {TABS.map(([id, label]) => {
+ const active = tab === id;
+ return (
+
+ );
+ })}
+
+
+
+
+ {tab === 'basic' && setTab('chart')} />}
+ {tab === 'chart' && }
+ {tab === 'flow' && }
+ {tab === 'traits' && navigate(`/saju/today?rid=${reading?.id || ''}`)} />}
+
+
+ );
+}
+
+function BasicTab({ reading, traits, onResult }) {
+ const r = reading || {};
+ const rows = [
+ ['생년월일', `${r.birth_year}년 ${r.birth_month}월 ${r.birth_day}일 (${r.calendar_type === 'lunar' ? '음력' : '양력'})`],
+ ['시간', r.birth_hour != null ? `${r.birth_hour}시` : '시간 미상'],
+ ['성별', r.gender === 'female' ? '여' : '남'],
+ ['사주', [r.saju_data?.year, r.saju_data?.month, r.saju_data?.day, r.saju_data?.hour].filter(Boolean).map((p) => `${p.stem}${p.branch}`).join(' ') || '-'],
+ ];
+ const summary = reading?.interpretation_json?.summary || '풀이 결과를 준비 중입니다.';
+ return (
+
+
+ {rows.map(([label, value], idx) => (
+
+
{label}
+
{value || '-'}
+
+ ))}
+
+
+
+ 사주 요약
+ {summary}
+
+
+
+
+ {traits.slice(0, 5).map((t) => ())}
+
+
+
+
+
+ );
+}
+
+function TraitChip({ ko, color }) {
+ // color는 'var(--el-fire)' 같은 CSS var. swatch에 직접 사용.
+ return (
+
+ );
+}
+
+function ChartTab({ reading, elementsObj }) {
+ const saju = reading?.saju_data || {};
+ const ohaengArr = ['wood', 'fire', 'earth', 'metal', 'water'].map((id) => ({
+ id, ko: ID_TO_KO[id], ch: ID_TO_CH[id],
+ value: Math.round(elementsObj?.[id] || 0),
+ color: ID_TO_COLOR[id],
+ }));
+ const strongest = ohaengArr.reduce((a, b) => (a.value > b.value ? a : b), { value: 0 });
+ const dms = reading?.analysis_data?.day_master_strength;
+ return (
+
+
+
+
+ 사주 명식
+ 일간 중심 해석
+
+
+ {['year', 'month', 'day', 'hour'].map((pk) => (
+
+ ))}
+
+
+
+
+
+
+ 오행 분석
+
+
+ {ohaengArr.map((o) => ())}
+
+ {strongest.value > 0 && (
+
+
+ {strongest.ko}({strongest.ch})의 기운이 강한 사주입니다.
+
+
+ )}
+ {dms && (
+
+
+ 일간 강도: {dms.result} · {dms.score}점
+
+ {dms.reasons && dms.reasons.length > 0 && (
+
+ {dms.reasons.join(' · ')}
+
+ )}
+
+ )}
+
+
+ );
+}
+
+const PILLAR_LABELS = { year: '년주', month: '월주', day: '일주', hour: '시주' };
+
+function PillarColumn({ pillarKey, pillar, stemColor, branchColor }) {
+ const isDay = pillarKey === 'day';
+ if (!pillar) {
+ return (
+
+ {PILLAR_LABELS[pillarKey]}
-
+
+ );
+ }
+ return (
+
+ {isDay && (
+
일간
+ )}
+
{PILLAR_LABELS[pillarKey]}
+
+
+
+
{pillar.ten_god || '-'}
+
{pillar.fortune || ''}
+
+ );
+}
+
+function CharBox({ char, sub, color }) {
+ return (
+
+
{char || '?'}
+
{sub || ''}
+
+ );
+}
+
+function OhaengBar({ ko, ch, value, color }) {
+ return (
+
+ );
+}
+
+function FlowTab({ reading }) {
+ const daeun = reading?.daeun_data || [];
+ const currentYear = new Date().getFullYear();
+ const enriched = daeun.map((d) => ({
+ ...d,
+ label: daeunLabel(d.age),
+ current: d.start_year <= currentYear && currentYear <= d.end_year,
+ }));
+ const current = enriched.find((x) => x.current);
+ return (
+
+
+
+
+ 대운 흐름
+ 10년 단위
+
+
+ 10년 주기로 변화하는 운의 흐름을 확인하세요.
+
+
+ {enriched.map((du, i) => ())}
+
+
+ {current && (
+
+
현재 대운 · {current.age}~{current.age + 9}세
+
+ {current.stem}{current.branch} · {current.label}
+
+
+ {current.start_year}년 ~ {current.end_year}년 — 이 시기는 {current.label} 단계로,
+ 10년 간의 운기 흐름을 차분히 살펴보세요.
+
+
+ )}
+
+ );
+}
+
+function DaeunNode({ age, stem, label, current }) {
+ return (
+
+ {current && (
+
현재
+ )}
+
{age}세
+
+ {stem}
+
+
{label}
+
+ );
+}
+
+function TraitsTab({ traits, onToday }) {
+ return (
+
+
+
+
+ 타고난 성향
+
+
+ {traits.map((t) => ())}
+
+
+
+
+ );
+}