diff --git a/src/pages/saju/Saju.css b/src/pages/saju/Saju.css deleted file mode 100644 index 7f24cc1..0000000 --- a/src/pages/saju/Saju.css +++ /dev/null @@ -1,430 +0,0 @@ -/* saju-page scope — 다른 페이지에 영향 없음 */ -.saju-page { - /* 베이스 */ - --saju-cream: #FAF6EE; - --saju-paper: #F2EAD8; - --saju-ink: #2E2D45; - --saju-ink-deep: #1F1D38; - - /* 액센트 */ - --saju-gold: #D4A574; - --saju-gold-deep: #B5874E; - --saju-apricot: #C58F76; - --saju-rose: #D9A2A6; - --saju-jade: #4B7065; - --saju-violet: #6A5285; - - /* 카테고리 (3 ActionCard) */ - --saju-today-bg: #4B7065; - --saju-gunghab-bg: #A8736E; - --saju-saju-bg: #4F4A78; - - /* 점수 카테고리 (4 ScoreCard) */ - --saju-wealth: #D4A574; - --saju-romance: #D9A2A6; - --saju-social: #4B7065; - --saju-career: #6A5285; - - min-height: 100vh; - background: var(--saju-cream); - color: var(--saju-ink); - font-family: 'Pretendard', sans-serif; - padding: 0; - margin: 0; -} - -.saju-page * { box-sizing: border-box; } - -.saju-page .saju-h1, -.saju-page .saju-h2, -.saju-page .saju-h3 { - font-family: 'Noto Serif KR', 'Pretendard', serif; - font-weight: 700; - letter-spacing: -0.02em; - color: var(--saju-ink); - margin: 0; -} - -.saju-page .saju-h1 { font-size: clamp(2.5rem, 4vw, 3.5rem); line-height: 1.2; } -.saju-page .saju-h2 { font-size: clamp(1.8rem, 3vw, 2.5rem); line-height: 1.3; } -.saju-page .saju-h3 { font-size: clamp(1.2rem, 2vw, 1.5rem); } - -/* 호령 마스코트 */ -.horyung-mascot { display: block; object-fit: contain; } -.horyung-mascot--sm { width: 80px; height: auto; } -.horyung-mascot--md { width: 180px; height: auto; } -.horyung-mascot--lg { width: 320px; height: auto; } - -/* 상단 네비게이션 */ -.saju-nav { - display: flex; - align-items: center; - justify-content: space-between; - padding: 1rem 2rem; - background: var(--saju-ink); - color: var(--saju-cream); -} -.saju-nav__logo { - font-family: 'Noto Serif KR', serif; - font-size: 1.25rem; - font-weight: 700; - color: var(--saju-cream); - text-decoration: none; -} -.saju-nav__links { - display: flex; - gap: 1.5rem; - list-style: none; - padding: 0; - margin: 0; -} -.saju-nav__links a { - color: var(--saju-cream); - text-decoration: none; - font-size: 0.95rem; - opacity: 0.85; -} -.saju-nav__links a:hover { opacity: 1; } -.saju-nav__cta { - background: var(--saju-gold); - color: var(--saju-ink); - border: none; - padding: 0.5rem 1.25rem; - border-radius: 999px; - font-weight: 600; - cursor: pointer; - font-family: 'Pretendard', sans-serif; - text-decoration: none; -} - -/* Hero */ -.saju-hero { - display: grid; - grid-template-columns: 1fr 1.4fr; - gap: 3rem; - padding: 3rem 2rem; - max-width: 1400px; - margin: 0 auto; -} -.saju-hero__left { - display: flex; - flex-direction: column; - align-items: center; - gap: 1.5rem; -} -.saju-quote-box { - background: var(--saju-paper); - padding: 1rem 1.25rem; - border-radius: 12px; - border: 1px solid var(--saju-gold-deep); - color: var(--saju-ink); - font-size: 0.9rem; - line-height: 1.5; - max-width: 280px; -} -.saju-hero__right { - display: flex; - flex-direction: column; - gap: 1.5rem; - justify-content: center; -} -.saju-sub { - color: var(--saju-ink); - opacity: 0.7; - margin: 0; - line-height: 1.6; -} - -/* ActionCard */ -.saju-action-cards { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 1rem; - margin-top: 1rem; -} -.saju-action-card { - background: var(--saju-saju-bg); - color: var(--saju-cream); - padding: 1.5rem 1rem; - border-radius: 16px; - text-decoration: none; - display: flex; - flex-direction: column; - align-items: center; - gap: 0.5rem; - transition: transform 0.2s; - font-family: 'Pretendard', sans-serif; -} -.saju-action-card:hover { transform: translateY(-4px); } -.saju-action-card--today { background: var(--saju-today-bg); } -.saju-action-card--gunghab { background: var(--saju-gunghab-bg); } -.saju-action-card--saju { background: var(--saju-saju-bg); } -.saju-action-card[aria-disabled="true"] { opacity: 0.6; cursor: not-allowed; } -.saju-action-card__icon { font-size: 2rem; } -.saju-action-card__title { font-size: 1.1rem; font-weight: 700; } -.saju-action-card__desc { font-size: 0.85rem; opacity: 0.85; text-align: center; } - -/* Bottom */ -.saju-bottom { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 3rem; - padding: 3rem 2rem; - max-width: 1400px; - margin: 0 auto; - background: var(--saju-ink); - color: var(--saju-cream); - border-radius: 24px 24px 0 0; -} -.saju-form { display: flex; flex-direction: column; gap: 1rem; } -.saju-form input, -.saju-form select { - padding: 0.75rem; - border-radius: 8px; - border: 1px solid var(--saju-gold-deep); - background: var(--saju-ink-deep); - color: var(--saju-cream); - font-family: inherit; - font-size: 1rem; -} -.saju-form button { - background: var(--saju-gold); - color: var(--saju-ink); - border: none; - padding: 0.875rem; - border-radius: 999px; - font-weight: 700; - cursor: pointer; - font-family: inherit; - font-size: 1rem; -} -.saju-form button:disabled { opacity: 0.6; cursor: not-allowed; } -.saju-form__error { - background: rgba(217, 162, 166, 0.2); - color: var(--saju-rose); - padding: 0.75rem; - border-radius: 8px; - font-size: 0.9rem; -} - -/* Fortune ring */ -.saju-fortune-ring { - display: flex; - align-items: center; - justify-content: center; - position: relative; -} -.saju-fortune-ring svg { width: 200px; height: 200px; } -.saju-fortune-ring__score { - position: absolute; - font-family: 'Noto Serif KR', serif; - font-size: 2.5rem; - font-weight: 700; - color: var(--saju-ink); -} -.saju-fortune-ring__total { font-size: 0.9rem; color: var(--saju-ink); opacity: 0.6; } - -/* ScoreCard */ -.saju-score-card { - background: var(--saju-cream); - border-radius: 16px; - padding: 1.25rem; - display: flex; - flex-direction: column; - gap: 0.5rem; - border: 1px solid var(--saju-paper); -} -.saju-score-card__head { display: flex; align-items: center; gap: 0.5rem; } -.saju-score-card__icon { font-size: 1.5rem; } -.saju-score-card__title { font-weight: 700; font-size: 0.95rem; } -.saju-score-card__value { - font-family: 'Noto Serif KR', serif; - font-size: 2rem; - font-weight: 700; - color: var(--saju-ink); -} -.saju-score-card__bar { - height: 6px; - background: var(--saju-paper); - border-radius: 3px; - overflow: hidden; -} -.saju-score-card__bar > div { height: 100%; background: var(--saju-gold); transition: width 0.5s; } - -/* Lucky box */ -.saju-lucky-box { - background: var(--saju-paper); - border-radius: 16px; - padding: 1.5rem; - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 1rem; -} -.saju-lucky-box__item { text-align: center; } -.saju-lucky-box__label { font-size: 0.8rem; color: var(--saju-ink); opacity: 0.7; margin-bottom: 0.25rem; } -.saju-lucky-box__value { - font-family: 'Noto Serif KR', serif; - font-size: 1.5rem; - font-weight: 700; - color: var(--saju-ink); -} - -/* SajuPillars */ -.saju-pillars { - display: grid; - grid-template-columns: repeat(4, 1fr); - gap: 0.75rem; -} -.saju-pillar { - background: var(--saju-paper); - border-radius: 12px; - padding: 1rem; - text-align: center; -} -.saju-pillar__label { font-size: 0.8rem; color: var(--saju-ink); opacity: 0.6; margin-bottom: 0.5rem; } -.saju-pillar__stem, -.saju-pillar__branch { - font-family: 'Noto Serif KR', serif; - font-size: 1.75rem; - font-weight: 700; - display: block; -} -.saju-pillar__stem-kr, -.saju-pillar__branch-kr { font-size: 0.85rem; opacity: 0.7; } -.saju-pillar__ten-god, -.saju-pillar__fortune { font-size: 0.75rem; margin-top: 0.25rem; opacity: 0.7; } - -/* Element bars */ -.saju-element-bars { - display: flex; - flex-direction: column; - gap: 0.5rem; - padding: 1.5rem; - background: var(--saju-cream); - border-radius: 16px; -} -.saju-element-bar { - display: grid; - grid-template-columns: 60px 1fr 50px; - align-items: center; - gap: 0.75rem; -} -.saju-element-bar__label { font-size: 0.9rem; font-weight: 700; } -.saju-element-bar__track { - height: 12px; - background: var(--saju-paper); - border-radius: 6px; - overflow: hidden; -} -.saju-element-bar__fill { - height: 100%; - border-radius: 6px; - transition: width 0.5s; -} -.saju-element-bar__fill--木 { background: #4B7065; } -.saju-element-bar__fill--火 { background: #C56F5C; } -.saju-element-bar__fill--土 { background: #D4A574; } -.saju-element-bar__fill--金 { background: #B8B5A8; } -.saju-element-bar__fill--水 { background: #4A5878; } -.saju-element-bar__value { text-align: right; font-size: 0.85rem; opacity: 0.7; } - -/* Monthly flow */ -.saju-monthly-flow { - display: grid; - grid-template-columns: repeat(12, 1fr); - gap: 0.25rem; - padding: 1rem; - background: var(--saju-cream); - border-radius: 16px; -} -.saju-monthly-flow__cell { - display: flex; - flex-direction: column; - align-items: center; - padding: 0.5rem 0.25rem; - border-radius: 8px; - background: var(--saju-paper); -} -.saju-monthly-flow__month { font-size: 0.7rem; opacity: 0.7; } -.saju-monthly-flow__score { - font-family: 'Noto Serif KR', serif; - font-weight: 700; - font-size: 1rem; -} -.saju-monthly-flow__label { font-size: 0.7rem; opacity: 0.8; margin-top: 0.25rem; } - -/* Horyung quote */ -.saju-horyung-quote { - background: var(--saju-ink); - color: var(--saju-cream); - padding: 1.5rem; - border-radius: 16px; - display: flex; - gap: 1rem; - align-items: flex-start; -} -.saju-horyung-quote__text { font-size: 0.95rem; line-height: 1.6; } - -/* Interpret accordion */ -.saju-interpret-accordion { display: flex; flex-direction: column; gap: 0.5rem; } -.saju-interpret-item { - background: var(--saju-cream); - border-radius: 12px; - border: 1px solid var(--saju-paper); - overflow: hidden; -} -.saju-interpret-item__header { - padding: 1rem; - background: var(--saju-paper); - cursor: pointer; - display: flex; - justify-content: space-between; - align-items: center; - font-weight: 700; - user-select: none; -} -.saju-interpret-item__body { padding: 1rem; font-size: 0.95rem; line-height: 1.6; } -.saju-interpret-item__evidence { - background: var(--saju-paper); - padding: 0.75rem; - border-radius: 8px; - margin-top: 0.75rem; - font-size: 0.85rem; - opacity: 0.85; -} - -/* Stub */ -.saju-stub { - max-width: 480px; - margin: 5rem auto; - text-align: center; - padding: 2rem; - background: var(--saju-paper); - border-radius: 24px; -} -.saju-stub a { - display: inline-block; - margin-top: 1.5rem; - background: var(--saju-gold); - color: var(--saju-ink); - padding: 0.75rem 1.5rem; - border-radius: 999px; - text-decoration: none; - font-weight: 700; -} - -/* 반응형 */ -@media (max-width: 1280px) { - .saju-hero { grid-template-columns: 1fr; text-align: center; } - .saju-hero__left { order: 2; } - .saju-hero__right { order: 1; } - .saju-bottom { grid-template-columns: 1fr; } -} -@media (max-width: 768px) { - .saju-nav { padding: 0.75rem 1rem; flex-wrap: wrap; gap: 0.5rem; } - .saju-nav__links { display: none; } - .saju-action-cards { grid-template-columns: 1fr; } - .saju-pillars { grid-template-columns: repeat(2, 1fr); } - .saju-monthly-flow { grid-template-columns: repeat(4, 1fr); } - .horyung-mascot--lg { width: 220px; } -} diff --git a/src/pages/saju/components/ActionCard.jsx b/src/pages/saju/components/ActionCard.jsx deleted file mode 100644 index 74965ae..0000000 --- a/src/pages/saju/components/ActionCard.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import React from 'react'; -import { Link } from 'react-router-dom'; - -const ICON = { - today: '☀', - heart: '♥', - book: '📖', -}; - -export default function ActionCard({ to, icon, title, desc, variant = 'saju', disabled = false }) { - const cls = `saju-action-card saju-action-card--${variant}`; - if (disabled) { - return ( - - {ICON[icon] || '✦'} - {title} - {desc || '준비 중'} - - ); - } - return ( - - {ICON[icon] || '✦'} - {title} - {desc} - - ); -} diff --git a/src/pages/saju/components/ElementBarChart.jsx b/src/pages/saju/components/ElementBarChart.jsx deleted file mode 100644 index cfd3f6b..0000000 --- a/src/pages/saju/components/ElementBarChart.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; - -const ELEMENT_ORDER = ['木', '火', '土', '金', '水']; -const ELEMENT_KR = { '木': '목', '火': '화', '土': '토', '金': '금', '水': '수' }; - -export default function ElementBarChart({ scores }) { - if (!scores) return null; - const max = Math.max(...Object.values(scores), 1); - return ( -
- {ELEMENT_ORDER.map((e) => { - const value = scores[e] || 0; - const widthPct = (value / max) * 100; - return ( -
-
{e} ({ELEMENT_KR[e]})
-
-
-
-
{value.toFixed(1)}%
-
- ); - })} -
- ); -} diff --git a/src/pages/saju/components/FortuneRing.jsx b/src/pages/saju/components/FortuneRing.jsx deleted file mode 100644 index 17b1a6c..0000000 --- a/src/pages/saju/components/FortuneRing.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; - -export default function FortuneRing({ score, max = 100 }) { - const radius = 80; - const circumference = 2 * Math.PI * radius; - const safe = Math.max(0, Math.min(score || 0, max)); - const dashOffset = circumference - (safe / max) * circumference; - - return ( -
- - - - -
-
{safe}
-
/ {max}
-
-
- ); -} diff --git a/src/pages/saju/components/HoryungMascot.jsx b/src/pages/saju/components/HoryungMascot.jsx deleted file mode 100644 index 5244592..0000000 --- a/src/pages/saju/components/HoryungMascot.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; - -const POSE_TO_FILE = { - front: '/images/saju/horyung/horyung-front.png', - bust: '/images/saju/horyung/horyung-bust.png', - greeting: '/images/saju/horyung/horyung-greeting.png', - thinking: '/images/saju/horyung/horyung-thinking.png', - pointing: '/images/saju/horyung/horyung-pointing.png', - happy: '/images/saju/horyung/horyung-happy.png', -}; - -export default function HoryungMascot({ pose = 'front', size = 'lg', className = '' }) { - const src = POSE_TO_FILE[pose] || POSE_TO_FILE.front; - return ( - 호령 { e.target.style.visibility = 'hidden'; }} - /> - ); -} diff --git a/src/pages/saju/components/HoryungQuote.jsx b/src/pages/saju/components/HoryungQuote.jsx deleted file mode 100644 index 0dd8927..0000000 --- a/src/pages/saju/components/HoryungQuote.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import HoryungMascot from './HoryungMascot'; - -export default function HoryungQuote({ pose = 'thinking', text }) { - if (!text) return null; - return ( -
- -
{text}
-
- ); -} diff --git a/src/pages/saju/components/InterpretAccordion.jsx b/src/pages/saju/components/InterpretAccordion.jsx deleted file mode 100644 index 681b97c..0000000 --- a/src/pages/saju/components/InterpretAccordion.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import React, { useState } from 'react'; - -export default function InterpretAccordion({ items }) { - const [openKey, setOpenKey] = useState(items?.[0]?.key); - if (!items || items.length === 0) return null; - return ( -
- {items.map((it) => { - const isOpen = openKey === it.key; - return ( -
-
setOpenKey(isOpen ? null : it.key)} - role="button" - tabIndex={0} - onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') setOpenKey(isOpen ? null : it.key); }} - > - {it.title || it.key} - {isOpen ? '▾' : '▸'} -
- {isOpen && ( -
-

{it.content}

- {it.evidence && ( -
- 근거: {it.evidence.saju_element}
- 해석 논리: {it.evidence.reasoning} -
- )} -
- )} -
- ); - })} -
- ); -} diff --git a/src/pages/saju/components/LuckyBox.jsx b/src/pages/saju/components/LuckyBox.jsx deleted file mode 100644 index 847fd99..0000000 --- a/src/pages/saju/components/LuckyBox.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; - -export default function LuckyBox({ lucky }) { - if (!lucky) return null; - return ( -
-
-
럭키 컬러
-
{(lucky.color || []).join(' · ')}
-
-
-
럭키 숫자
-
{lucky.number}
-
-
-
럭키 방향
-
{lucky.direction}
-
-
- ); -} diff --git a/src/pages/saju/components/MonthlyFlow.jsx b/src/pages/saju/components/MonthlyFlow.jsx deleted file mode 100644 index 6d90f19..0000000 --- a/src/pages/saju/components/MonthlyFlow.jsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; - -const LABEL_COLOR = { - '성장': '#4B7065', - '안정': '#D4A574', - '변동': '#6A5285', - '도전': '#C58F76', - '정체': '#888', -}; - -export default function MonthlyFlow({ flow }) { - if (!flow || flow.length === 0) return null; - return ( -
- {flow.map((m) => ( -
- {m.month}월 - - {m.score} - - {m.label} -
- ))} -
- ); -} diff --git a/src/pages/saju/components/SajuInputForm.jsx b/src/pages/saju/components/SajuInputForm.jsx deleted file mode 100644 index a3bf0ec..0000000 --- a/src/pages/saju/components/SajuInputForm.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react'; - -export default function SajuInputForm({ form, onChange, onSubmit, loading, error }) { - return ( -
-

- 사주풀이 시작하기 -

- onChange('name', e.target.value)} - disabled={loading} - /> -
- onChange('year', e.target.value)} disabled={loading} min="1900" max="2100" /> - onChange('month', e.target.value)} disabled={loading} min="1" max="12" /> - onChange('day', e.target.value)} disabled={loading} min="1" max="31" /> -
-
- onChange('hour', e.target.value)} disabled={loading} min="0" max="23" /> - - -
- {error &&
{error}
} - -
- ); -} diff --git a/src/pages/saju/components/SajuNav.jsx b/src/pages/saju/components/SajuNav.jsx deleted file mode 100644 index 594b00e..0000000 --- a/src/pages/saju/components/SajuNav.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import { Link, NavLink } from 'react-router-dom'; - -export default function SajuNav() { - return ( - - ); -} diff --git a/src/pages/saju/components/SajuPillars.jsx b/src/pages/saju/components/SajuPillars.jsx deleted file mode 100644 index b847e2a..0000000 --- a/src/pages/saju/components/SajuPillars.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react'; - -const PILLAR_LABELS = { year: '년주', month: '월주', day: '일주', hour: '시주' }; - -export default function SajuPillars({ saju }) { - if (!saju) return null; - const pillars = ['year', 'month', 'day', 'hour']; - return ( -
- {pillars.map((p) => { - const data = saju[p]; - if (!data) { - return ( -
-
{PILLAR_LABELS[p]}
-
-
-
- ); - } - return ( -
-
{PILLAR_LABELS[p]}
-
- {data.stem} - ({data.stem_kr}) -
-
- {data.branch} - ({data.branch_kr}) -
-
{data.ten_god}
-
{data.fortune}
-
- ); - })} -
- ); -} diff --git a/src/pages/saju/components/ScoreCard.jsx b/src/pages/saju/components/ScoreCard.jsx deleted file mode 100644 index 22546f8..0000000 --- a/src/pages/saju/components/ScoreCard.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react'; - -const ICON_BY_CATEGORY = { - wealth: '💰', - romance: '💖', - social: '🤝', - career: '💼', -}; - -const COLOR_VAR_BY_CATEGORY = { - wealth: 'var(--saju-wealth)', - romance: 'var(--saju-romance)', - social: 'var(--saju-social)', - career: 'var(--saju-career)', -}; - -const TITLE_BY_CATEGORY = { - wealth: '재물운', - romance: '연애운', - social: '인간관계', - career: '직장운', -}; - -export default function ScoreCard({ category, score }) { - const safe = Math.max(0, Math.min(score || 0, 100)); - return ( -
-
- {ICON_BY_CATEGORY[category]} - {TITLE_BY_CATEGORY[category]} -
-
{safe}/100
-
-
-
-
- ); -}