-
-
-
-
-
-
-
-
- {ACTIONS.map((a) => (
-
- ))}
+
+
+
+
+
+ 안녕하세요!
저는 호령이에요.
당신의 길을 비춰드릴게요.
+
+
-
-
+
+
+ {FEATURES.map((feature) => (
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+ 새로운 기회가 찾아오는 날입니다.
+
+
+ 작은 실천이 큰 변화를 만듭니다. 주변의 조언에 귀 기울여 보세요.
+
+
+ } label="재물운" value="80" />
+ } label="연애운" value="70" />
+ } label="건강운" value="75" />
+ } label="직장운" value="82" />
+
+
+
+
+
+
+
+
+
+
+
+
+ {error &&
{error}
}
+
+
+ {loading ? '호령이 풀이 중...' : '사주풀이 시작하기'}
+ {!loading && }
+
+
+
+
+
+
+
);
}
+
+function MiniTrust({ icon, title, desc }) {
+ return (
+
+ {icon}
+
+ {title}
+ {desc}
+
+
+ );
+}
+
+function ScorePill({ icon, label, value }) {
+ return (
+
+ {icon}
+ {label}
+ {value}
+
+ );
+}
+
+function DarkInputRow({ label, children }) {
+ return (
+
+ );
+}
diff --git a/src/pages/saju/views/match-result.desktop.jsx b/src/pages/saju/views/match-result.desktop.jsx
new file mode 100644
index 0000000..38b8054
--- /dev/null
+++ b/src/pages/saju/views/match-result.desktop.jsx
@@ -0,0 +1,232 @@
+import React from 'react';
+import { useNavigate } from 'react-router-dom';
+import DesktopHero from '../_shell/DesktopHero';
+import DesktopFooter from '../_shell/DesktopFooter';
+import PanelHeader from '../_shell/PanelHeader';
+import {
+ IconChevron, IconHeart, IconPaw, IconSparkle, IconSun, IconUser,
+} from '../_shell/Icons';
+import hexA from '../_shell/helpers/hexA';
+
+export default function MatchResultDesktop({ result }) {
+ const navigate = useNavigate();
+ const interp = result?.interpretation_json || {};
+ const score = Math.round(result?.score || interp.score || 86);
+ const names = {
+ a: result?.person_a?.name || '나',
+ b: result?.person_b?.name || '상대방',
+ };
+ const strengths = interp.strengths?.length ? interp.strengths : ['서로에게 긍정적인 영향을 주며 함께 목표를 이루기 좋아요.'];
+ const challenges = interp.challenges?.length ? interp.challenges : ['감정 표현 방식이 달라 오해가 생길 수 있으니 배려가 필요해요.'];
+ const summary = interp.summary || '두 분은 서로의 부족한 부분을 채워주며 함께 성장해 나갈 수 있는 좋은 인연이에요. 서로의 다름을 인정하고 존중한다면 더욱 길고 단단한 관계로 발전할 수 있습니다.';
+
+ return (
+
+ 두 분의 인연을
제가 잘 살펴봤어요!
함께 행복한 길을 걸어가세요.}
+ />
+
+
+
+
+
+
+
+
+ 궁합 점수
+
+
+
+ {score}점
+
+
+ 상위권의 좋은 궁합이에요.
+
+
+
+
+
+ } label="성향 궁합" score={Math.min(100, score + 2)} desc="가치관과 성향이 조화를 이룹니다." />
+ } label="대화 궁합" score={Math.max(0, score - 4)} desc="편안한 대화를 나눌 수 있어요." />
+ } label="연애 궁합" score={Math.min(100, score + 4)} desc="설렘과 안정감을 함께 줍니다." />
+ } label="결혼 궁합" score={Math.max(0, score - 2)} desc="함께 미래를 그리기 좋은 균형입니다." />
+
+
+
+
+
+
+
+
+
+
+
+
+ 서로를 북돋우는 상생의 기운이 강합니다.
+
+
+
+
+
+
{summary}
+
+ 서로에게 따뜻한 빛이 되어주는 인연입니다.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+function PersonSummary({ label, name, chipColor, chipBg }) {
+ return (
+
+
{label}
+
{name}
+
양력
+
+
+
+
+
+ );
+}
+
+function SubScoreCard({ color, icon, label, score, desc }) {
+ return (
+
+
+
+
+ {score}점
+
+
{desc}
+
+ );
+}
+
+function Circle({ label, sub, color, center }) {
+ return (
+
+ {label}
+ {sub}
+
+ );
+}
+
+function SummaryItem({ color, title, desc }) {
+ return (
+
+ );
+}
+
+function buttonPrimary() {
+ return {
+ padding: '14px 26px', borderRadius: 999, background: '#1F2A44', color: '#F7F2E8',
+ border: '1px solid rgba(212,175,55,0.4)', fontSize: 14, fontWeight: 800,
+ display: 'flex', alignItems: 'center', gap: 8,
+ };
+}
+
+function buttonGhost() {
+ return {
+ padding: '14px 26px', borderRadius: 999, background: '#FBF7EF', color: '#1F2A44',
+ border: '1px solid rgba(31,42,68,0.22)', fontSize: 14, fontWeight: 800,
+ display: 'flex', alignItems: 'center', gap: 8,
+ };
+}
+
+function SpeechIcon({ size = 16, stroke = '#3A5A8C' }) {
+ return (
+
+ );
+}
+
+function RingIcon({ size = 18, stroke = '#A67B3F' }) {
+ return (
+
+ );
+}
diff --git a/src/pages/saju/views/match.desktop.jsx b/src/pages/saju/views/match.desktop.jsx
index 57f547d..565ff85 100644
--- a/src/pages/saju/views/match.desktop.jsx
+++ b/src/pages/saju/views/match.desktop.jsx
@@ -1,10 +1,209 @@
import React from 'react';
-import MatchMobile from './match.mobile.jsx';
+import DesktopHero from '../_shell/DesktopHero';
+import DesktopFooter from '../_shell/DesktopFooter';
+import PanelHeader from '../_shell/PanelHeader';
+import PrimaryButton from '../_shell/PrimaryButton';
+import {
+ IconCalendar, IconClock, IconHeart, IconPaw, IconSparkle, IconUser,
+} from '../_shell/Icons';
+import hexA from '../_shell/helpers/hexA';
-export default function MatchDesktop(props) {
+function pad(n) { return String(n).padStart(2, '0'); }
+function dateValue(person) {
+ if (!person.year || !person.month || !person.day) return '';
+ return `${person.year}-${pad(person.month)}-${pad(person.day)}`;
+}
+function timeValue(person) {
+ if (person.hour === '' || person.hour == null) return '';
+ return `${pad(person.hour)}:00`;
+}
+function onDate(person, onChange, event) {
+ const value = event.target.value;
+ if (!value) return onChange({ ...person, year: '', month: '', day: '' });
+ const [year, month, day] = value.split('-');
+ return onChange({ ...person, year: parseInt(year, 10), month: parseInt(month, 10), day: parseInt(day, 10) });
+}
+function onTime(person, onChange, event) {
+ const value = event.target.value;
+ if (!value) return onChange({ ...person, hour: null });
+ const [hour] = value.split(':');
+ return onChange({ ...person, hour: parseInt(hour, 10) });
+}
+
+export default function MatchDesktop({
+ personA, personB, onChangeA, onChangeB, onSubmit, loading, error,
+}) {
return (
-
-
+
+ 두 분의 인연을
제가 잘 살펴봐드릴게요!
함께 행복한 길을 걸어가시길 바라요.
}
+ />
+
+
+
+
+
+ );
+}
+
+function PersonCard({ label, chipColor, chipBg, avatarBg, person, onChange }) {
+ const activeGender = person.gender || 'male';
+ return (
+
+
+
{label}
+
onChange({ ...person, name: event.target.value })}
+ placeholder="이름"
+ style={{
+ flex: 1, minWidth: 120, padding: '12px 14px', borderRadius: 10,
+ border: '1px solid rgba(31,42,68,0.12)', background: '#FBF7EF',
+ color: '#1F2A44', fontSize: 15, fontWeight: 700,
+ }}
+ />
+
{person.calendar_type === 'lunar' ? '음력' : '양력'}
+
+
+
+
+
+
+ }>
+ onDate(person, onChange, event)} style={fieldInputStyle} />
+
+
+
+
+
}>
+
onTime(person, onChange, event)} style={fieldInputStyle} />
+
+
+ {[
+ ['male', '남'],
+ ['female', '여'],
+ ].map(([value, text]) => {
+ const active = activeGender === value;
+ return (
+
+ );
+ })}
+
+
+
);
}
+
+function FieldPill({ icon, children }) {
+ return (
+
+ {icon}
+ {children}
+
+ );
+}
+
+const fieldInputStyle = {
+ flex: 1,
+ minWidth: 0,
+ border: 'none',
+ background: 'transparent',
+ color: '#1F2A44',
+ fontSize: 14,
+ fontFamily: 'inherit',
+ padding: '11px 0',
+};
+
+const selectStyle = {
+ border: '1px solid rgba(31,42,68,0.12)',
+ borderRadius: 10,
+ background: '#FBF7EF',
+ color: '#1F2A44',
+ fontSize: 14,
+ fontFamily: 'inherit',
+ padding: '0 12px',
+};
diff --git a/src/pages/saju/views/saju.desktop.jsx b/src/pages/saju/views/saju.desktop.jsx
index 2f47a3c..bb15177 100644
--- a/src/pages/saju/views/saju.desktop.jsx
+++ b/src/pages/saju/views/saju.desktop.jsx
@@ -1,10 +1,499 @@
import React from 'react';
-import SajuMobile from './saju.mobile.jsx';
+import { useNavigate } from 'react-router-dom';
+import DesktopHero from '../_shell/DesktopHero';
+import DesktopFooter from '../_shell/DesktopFooter';
+import PanelHeader from '../_shell/PanelHeader';
+import OrnamentBloom from '../_shell/OrnamentBloom';
+import { IconChevron, IconPaw } from '../_shell/Icons';
+import deriveTraits from '../_shell/helpers/deriveTraits';
+import daeunLabel from '../_shell/helpers/daeunLabel';
+import hexA from '../_shell/helpers/hexA';
+
+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',
+};
+const STEM_EL = { '甲': 'wood', '乙': 'wood', '丙': 'fire', '丁': 'fire', '戊': 'earth', '己': 'earth', '庚': 'metal', '辛': 'metal', '壬': 'water', '癸': 'water' };
+const BRANCH_EL = { '子': 'water', '丑': 'earth', '寅': 'wood', '卯': 'wood', '辰': 'earth', '巳': 'fire', '午': 'fire', '未': 'earth', '申': 'metal', '酉': 'metal', '戌': 'earth', '亥': 'water' };
+
+const PILLAR_LABELS = { year: '년주', month: '월주', day: '일주', hour: '시주' };
+
+function elementsByEngId(scores = {}) {
+ const out = {};
+ for (const [key, value] of Object.entries(scores || {})) {
+ const id = HANJA_TO_ID[key] || key;
+ if (ID_TO_KO[id]) out[id] = Number(value) || 0;
+ }
+ return out;
+}
+
+function maxElement(elementsObj) {
+ return ['wood', 'fire', 'earth', 'metal', 'water']
+ .map((id) => ({ id, value: Math.round(elementsObj[id] || 0), color: ID_TO_COLOR[id] }))
+ .reduce((best, item) => (item.value > best.value ? item : best), { id: 'metal', value: 0, color: '#D4AF37' });
+}
+
+function normalizePillar(pillar = {}, key) {
+ const stem = pillar.stem || '-';
+ const branch = pillar.branch || '-';
+ return {
+ id: key,
+ label: PILLAR_LABELS[key],
+ cheongan: {
+ ch: stem,
+ ko: pillar.stem_kr || '',
+ mark: stem && STEM_EL[stem] ? `(${ID_TO_KO[STEM_EL[stem]]})` : '',
+ color: ID_TO_COLOR[STEM_EL[stem]] || '#1F2A44',
+ },
+ jiji: {
+ ch: branch,
+ ko: pillar.branch_kr || '',
+ mark: branch && BRANCH_EL[branch] ? `(${ID_TO_KO[BRANCH_EL[branch]]})` : '',
+ color: ID_TO_COLOR[BRANCH_EL[branch]] || '#1F2A44',
+ },
+ sipsin: pillar.ten_god || '-',
+ jijang: pillar.hidden_stems || pillar.fortune || '-',
+ };
+}
+
+function readingToDesktopData(reading) {
+ const saju = reading?.saju_data || {};
+ const elementsObj = elementsByEngId(reading?.analysis_data?.element_scores);
+ const strongest = maxElement(elementsObj);
+ const pillars = ['year', 'month', 'day', 'hour'].map((key) => normalizePillar(saju[key], key));
+ const daeun = (reading?.daeun_data || []).map((item) => ({
+ age: `${item.age}~${item.age + 9}세`,
+ rawAge: item.age,
+ gan: item.stem || item.gan || '-',
+ label: daeunLabel(item.age),
+ current: item.start_year <= new Date().getFullYear() && new Date().getFullYear() <= item.end_year,
+ startYear: item.start_year,
+ endYear: item.end_year,
+ }));
+ const fallbackDaeun = [0, 10, 20, 30, 40, 50, 60, 70].map((age, index) => ({
+ age: `${age}~${age + 9}세`,
+ rawAge: age,
+ gan: ['戊', '丁', '丙', '乙', '甲', '癸', '壬', '辛'][index],
+ label: daeunLabel(age),
+ current: age === 30,
+ }));
+
+ return {
+ name: reading?.name || '백호',
+ gender: reading?.gender === 'female' ? '여' : '남',
+ birth: `${reading?.birth_year || '1990'}년 ${reading?.birth_month || '01'}월 ${reading?.birth_day || '01'}일 ${reading?.birth_hour ?? '10'}:00`,
+ lunar: reading?.calendar_type === 'lunar' ? '음력 입력' : '양력 입력',
+ birthPlace: reading?.birth_place || '서울특별시',
+ ilgan: pillars[2]?.cheongan || { ch: '庚', color: '#3A5A8C' },
+ pillars,
+ elementsObj,
+ ohaeng: ['wood', 'fire', 'earth', 'metal', 'water'].map((id) => ({
+ id, ko: ID_TO_KO[id], ch: ID_TO_CH[id],
+ value: Math.round(elementsObj[id] || ({ wood: 20, fire: 35, earth: 25, metal: 55, water: 30 }[id])),
+ color: ID_TO_COLOR[id],
+ })),
+ strongest,
+ summary: reading?.interpretation_json?.summary || '의리가 강하고 책임감이 뛰어난 흐름입니다. 목표를 정하면 끝까지 해내는 추진력과 원칙을 중시하는 태도가 장점으로 드러납니다.',
+ traits: deriveTraits(elementsObj, []),
+ daeun: daeun.length ? daeun : fallbackDaeun,
+ dayMasterStrength: reading?.analysis_data?.day_master_strength,
+ };
+}
export default function SajuDesktop({ reading }) {
+ const navigate = useNavigate();
+ const data = readingToDesktopData(reading);
+
return (
-
-
+
+ 사주의 흐름을 읽고,
당신의 길을 밝혀드립니다.
}
+ />
+
+
+
navigate('/saju')} />
+
+
+
+
+
+
+
+
+
+ t.ko || t.label)} />
+
+
+
+
+
+
+ navigate('/saju/me')} />
+
+
+
+
+ );
+}
+
+function BasicInfoBar({ data, onEdit }) {
+ return (
+
+
+
+
+
+
+
+
양 · 일간 {data.ilgan.ch}} />
+
+
+
+ );
+}
+
+function InfoCol({ label, value }) {
+ return (
+
+ );
+}
+
+function SajuStructureCard({ data }) {
+ return (
+
+
+
+
+
+ |
+ {data.pillars.map((pillar) => (
+
+ {pillar.id === 'day' && (
+ 일간
+ )}
+ {pillar.label}
+ |
+ ))}
+
+
+
+ pillar.cheongan)} day />
+ pillar.jiji)} day />
+ pillar.sipsin)} />
+ pillar.jijang)} mono />
+
+
+
+ ※ 일간(나)을 중심으로 사주의 흐름과 균형을 해석합니다.
+
+
+ );
+}
+
+const thStyle = ({ active = false } = {}) => ({
+ padding: '8px 4px 12px',
+ textAlign: 'center',
+ borderBottom: '1px solid rgba(31,42,68,0.08)',
+ background: active ? 'rgba(106,76,124,0.06)' : 'transparent',
+ position: 'relative',
+});
+
+function Row({ label, cells, day }) {
+ return (
+
+ | {label} |
+ {cells.map((cell, index) => {
+ const isDay = index === 2 && day;
+ return (
+
+ {cell.ch}
+
+ {cell.ko} {cell.mark}
+
+ |
+ );
+ })}
+
+ );
+}
+
+function RowText({ label, cells, mono }) {
+ return (
+
+ | {label} |
+ {cells.map((cell, index) => (
+ {String(cell || '-')} |
+ ))}
+
+ );
+}
+
+function OhaengCard({ data }) {
+ const strongest = maxElement(data.elementsObj);
+ return (
+
+
+
+ {data.ohaeng.map((element) => {
+ const height = Math.min(100, Math.max(8, (element.value / 60) * 100));
+ return (
+
+
+
+ {element.ko}({element.ch})
+
+
+ );
+ })}
+
+
+
+ {ID_TO_KO[strongest.id]}({ID_TO_CH[strongest.id]})의 기운이 강한 사주입니다.
+
+
+ 강한 기운을 바탕으로 장점을 살리고 부족한 기운은 생활 습관과 관계에서 보완해 보세요.
+
+
+
+ );
+}
+
+function HoryungInsightCard({ data }) {
+ const strongest = maxElement(data.elementsObj);
+ const items = [
+ { title: `일간이 ${data.ilgan.ch}이시네요.`, desc: '단단한 중심과 자기 기준을 갖고 흐름을 읽는 힘이 있습니다.' },
+ { title: `${ID_TO_KO[strongest.id]}(${ID_TO_CH[strongest.id]})의 기운이 두드러져요.`, desc: '해당 기운의 장점을 생활과 일의 방향으로 살려보세요.' },
+ { title: '균형을 보완하면 더욱 좋아요.', desc: '강한 기운만 밀어붙이기보다 부족한 기운을 의식하면 흐름이 부드러워집니다.' },
+ { title: '지금의 선택이 미래의 나를 만듭니다.', desc: '작은 실천을 꾸준히 쌓는 시기로 삼아보세요.' },
+ ];
+ return (
+
+
+
+ {items.map((item, index) => (
+
+
{index + 1}
+
+
{item.title}
+
{item.desc}
+
+
+ ))}
+
+
+
+ 지금의 선택이
미래의 나를 만듭니다.
+
+
+
+
+ );
+}
+
+function TraitDeskCard({ color, iconName, title, body, bullets }) {
+ return (
+
+
+ {body &&
{body}
}
+ {bullets && (
+
+ {bullets.map((item) => (
+ -
+ · {item}
+
+ ))}
+
+ )}
+
+ );
+}
+
+function TraitIcon({ name, color, size }) {
+ const common = { width: size, height: size, viewBox: '0 0 24 24', fill: 'none', stroke: color, strokeWidth: '1.7', strokeLinecap: 'round', strokeLinejoin: 'round' };
+ if (name === 'heart') return
;
+ if (name === 'challenge') return
;
+ if (name === 'lead') return
;
+ if (name === 'adapt') return
;
+ return
;
+}
+
+function DaeunDeskCard({ data }) {
+ const current = data.daeun.find((item) => item.current) || data.daeun[0];
+ return (
+
+
+
+
대운 흐름
+ 10년 단위 운의 흐름을 살펴보세요.
+
+
+
+ {data.daeun.map((item, index) => (
+
+
+ {index < data.daeun.length - 1 && (
+
+
+
+ )}
+
+ ))}
+
+
+
+ 현재
+ 대운 해설 ({current?.age})
+
+
+ 자기 확장과 기반을 다지는 시기입니다.
+ 꾸준한 노력과 인내가 결실을 맺고, 커리어와 재정적 성장이 기대됩니다.
+
+
+
+
+ );
+}
+
+function DaeunNodeDesk({ age, gan, label, current }) {
+ return (
+
+ {current && (
+
현재
+ )}
+
{age}
+
+ {gan}
+
+
{label}
+
+ );
+}
+
+function ConsultCTA({ onClick }) {
+ return (
+
+
+
+
+ 1:1 PERSONAL CONSULT
+
+
+ 더 깊은 해석이 필요하신가요?
+
+
+ 개인 맞춤 상담을 통해 당신의 사주를 더 깊이 이해하고 명확한 방향을 찾아보세요.
+
+
+
);
}
diff --git a/src/pages/saju/views/today.desktop.jsx b/src/pages/saju/views/today.desktop.jsx
index e9caa33..120f361 100644
--- a/src/pages/saju/views/today.desktop.jsx
+++ b/src/pages/saju/views/today.desktop.jsx
@@ -1,10 +1,245 @@
import React from 'react';
-import TodayMobile from './today.mobile.jsx';
+import { useNavigate } from 'react-router-dom';
+import DesktopFooter from '../_shell/DesktopFooter';
+import Mascot from '../_shell/Mascot';
+import PanelHeader from '../_shell/PanelHeader';
+import {
+ IconClock, IconHeart, IconMoney, IconPaw, IconSparkle, IconStar, IconSun,
+} from '../_shell/Icons';
+import hexA from '../_shell/helpers/hexA';
+
+const SCORE_LABELS = [
+ { key: 'wealth', label: '재물운', color: '#D4AF37', icon: IconMoney, desc: '안정적인 흐름, 수입에 긍정적인 변화가 있어요.' },
+ { key: 'romance', label: '연애운', color: '#D89098', icon: IconHeart, desc: '진심이 통하는 하루, 관계가 한층 가까워져요.' },
+ { key: 'social', label: '건강운', color: '#4E6B5C', icon: LeafIcon, desc: '컨디션이 무난해요. 규칙적인 관리가 필요해요.' },
+ { key: 'career', label: '직장운', color: '#3A5A8C', icon: BriefcaseIcon, desc: '업무 성과가 좋아요. 기획력이 빛을 발합니다.' },
+];
export default function TodayDesktop({ reading }) {
+ const navigate = useNavigate();
+ const scores = reading?.fortune_scores || {};
+ const lucky = reading?.lucky || {};
+ const overall = Math.round(scores.overall || 78);
+ const today = new Date().toLocaleDateString('ko-KR', {
+ year: 'numeric', month: '2-digit', day: '2-digit', weekday: 'short',
+ });
+
return (
-
-
+
+
+
+ 홈 › 오늘의 운세
+
+
+
+
+
+
+
+
+
+
오늘의 운세
+
오늘의 흐름을 한눈에 확인해 보세요.
+
+
+
+
+
+
+
+
오늘의 종합운
+
+ {overall}/100
+
+
+ {[1, 2, 3, 4, 5].map((i) => )}
+
+
+
+
+ 새로운 기회가 찾아오는 날입니다.
+
+
+ 작은 실천이 큰 변화를 만듭니다. 주변의 조언에 귀 기울여 보세요.
+ 따뜻한 말 한마디가 당신의 하루를 빛나게 할 것입니다.
+
+
+
+
+
+ {SCORE_LABELS.map((item) => (
+
+ ))}
+
+
+
+
+
+ {(Array.isArray(lucky.color) ? lucky.color : ['#1F2A44', '#E8C76B', '#6B4423', '#D89098', '#F7F2E8']).map((color) => (
+
+ ))}
+
+
+
+
+
+ {lucky.time || '오전 10시 ~ 12시'}
+
+
+
+
+ 기회는 준비된 마음을
늘 찾아옵니다.
+
+
+
+
+ 충동적인 결정은 피하고,
여유를 가지세요.
+
+
+
+
+
+
+
더 깊이 알고 싶으신가요?
+
+ 오늘의 운세를 넘어, 당신만을 위한 정밀한 사주 분석으로 인생의 방향을 찾아드려요.
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+function FortuneCard({ label, value, icon: IconComponent, desc, color }) {
+ return (
+
+
+
+ {React.createElement(IconComponent, { size: 20, stroke: color })}
+
+
{label}
+
+
+ {value}/100
+
+
{desc}
);
}
+
+function SmallCard({ color, icon: IconComponent, title, sub, children }) {
+ return (
+
+
+ {React.createElement(IconComponent, { size: 15, stroke: color })}
+
+ )} />
+
{sub}
+ {children}
+
+ );
+}
+
+function buttonPrimary() {
+ return {
+ padding: '14px 24px', borderRadius: 999, background: '#1F2A44', color: '#F7F2E8',
+ border: '1px solid rgba(212,175,55,0.4)', fontSize: 14, fontWeight: 800,
+ boxShadow: '0 4px 14px rgba(31,42,68,0.25), inset 0 1px 0 rgba(212,175,55,0.3)',
+ display: 'flex', alignItems: 'center', gap: 8, whiteSpace: 'nowrap',
+ };
+}
+
+function buttonGhost() {
+ return {
+ padding: '14px 24px', borderRadius: 999, background: 'transparent', color: '#1F2A44',
+ border: '1px solid rgba(31,42,68,0.25)', fontSize: 14, fontWeight: 800,
+ display: 'flex', alignItems: 'center', gap: 8, whiteSpace: 'nowrap',
+ };
+}
+
+function LeafIcon({ size = 16, stroke = '#4E6B5C' }) {
+ return (
+
+ );
+}
+
+function BriefcaseIcon({ size = 16, stroke = '#3A5A8C' }) {
+ return (
+
+ );
+}
+
+function WarnIcon({ size = 14, stroke = '#C04A4A' }) {
+ return (
+
+ );
+}
diff --git a/src/pages/saju/views/today.mobile.jsx b/src/pages/saju/views/today.mobile.jsx
index f827e7e..05ff27a 100644
--- a/src/pages/saju/views/today.mobile.jsx
+++ b/src/pages/saju/views/today.mobile.jsx
@@ -70,7 +70,7 @@ export default function TodayMobile({ reading }) {
)}
-
navigate(`/saju/result?rid=${reading?.id || ''}`)}>
+ navigate(reading?.id ? `/saju/result?rid=${reading.id}` : '/saju/result')}>
내 사주 자세히 보기