Written by

in

GS25 오늘의 운세

:root{
–gs-sky:#28B5F5; –gs-deep:#0FA3E1; –gs-orange:#FF7A00;
–ink:#1f2937; –muted:#6b7280; –bg:#f6fbff; –card:#fff; –ring:rgba(40,181,245,.35);
}
*{box-sizing:border-box}
html,body{margin:0;background:var(–bg);color:var(–ink);font-family:-apple-system,Segoe UI,Roboto,Pretendard,system-ui,sans-serif}
.container{max-width:760px;margin:24px auto;padding:16px}
.header{display:flex;align-items:center;gap:10px;margin-bottom:12px}
.logo .gs{font-weight:800;font-size:24px}
.logo .n25{font-weight:900;font-size:26px;color:var(–gs-sky)}
.card{background:var(–card);border-radius:16px;border:1px solid rgba(15,163,225,.15);box-shadow:0 6px 18px rgba(15,163,225,.08);overflow:hidden}
.hero{background:linear-gradient(135deg,var(–gs-sky),var(–gs-deep));color:#fff;padding:20px}
.hero h1{margin:0 0 6px 0;font-size:22px}
.hero p{margin:0;opacity:.95}
.body{padding:16px}
.badge{margin-left:auto;font-size:12px;color:var(–muted)}

.pickers{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}
@media (max-width:640px){.pickers{grid-template-columns:repeat(2,1fr)}}
.label{font-size:12px;color:var(–muted);margin:6px 0 2px 4px}
.wheel{height:160px;overflow-y:auto;scroll-snap-type:y mandatory;background:#fff;border:1px solid #e5e7eb;border-radius:12px;position:relative}
.wheel::-webkit-scrollbar{width:6px}
.wheel::-webkit-scrollbar-thumb{background:#e5e7eb;border-radius:6px}
.item{height:40px;display:flex;align-items:center;justify-content:center;scroll-snap-align:center;color:#374151}
.item.sel{font-weight:800;color:#111}
.highlight{position:absolute;left:6px;right:6px;top:calc(50% – 20px);height:40px;border-radius:10px;border:1px dashed rgba(15,163,225,.4);background:rgba(40,181,245,.06);pointer-events:none}

.nameRow{display:flex;gap:8px;margin:12px 0}
.nameRow input{flex:1;border:1px solid #e5e7eb;border-radius:12px;padding:12px 14px;font-size:15px;outline:none}
.nameRow input:focus{border-color:var(–gs-sky);box-shadow:0 0 0 4px var(–ring)}
.btnRow{display:flex;gap:8px;justify-content:flex-end}
.btn{background:var(–gs-orange);color:#fff;border:0;border-radius:12px;padding:12px 16px;font-weight:800;cursor:pointer;box-shadow:0 6px 16px rgba(255,122,0,.2);transition:.15s}
.btn.secondary{background:#fff;color:var(–gs-deep);border:1px solid rgba(15,163,225,.35);box-shadow:none}
.btn:hover{transform:translateY(-1px)}

.grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;margin-top:12px}
@media (max-width:640px){.grid{grid-template-columns:1fr}}
.tile{border:1px solid #e5e7eb;border-radius:14px;padding:12px;background:#fff}
.tile h3{margin:0 0 6px 0;font-size:14px;color:var(–muted);font-weight:700}
.tile .val{font-size:16px;font-weight:800}
.kv{display:flex;align-items:center;gap:8px}
.kv .dot{width:14px;height:14px;border-radius:50%}
.small{font-size:12px;color:var(–muted);margin-top:8px}

오늘의 운세 (출생 연·월·일·시)

휠에서 출생 정보를 고르고 이름을 입력한 뒤 운세 보기 버튼을 눌러보세요.

출생 연도
시간

총운

키워드

사랑/인연

금전/재물

일/사업

건강

럭키 아이템

럭키 컬러

럭키 넘버

럭키 타임

프로필

※ 같은 출생 정보와 같은 날에는 결과가 고정됩니다. (API 시드 기반)

// === 설정 ===
const API_BASE = “https://gs25deocksu-fortune.t01040454570.workers.dev/api/fortune”;

// 날짜 표시
document.getElementById(“today”).textContent =
new Date().toLocaleDateString(“ko-KR”,{year:”numeric”,month:”long”,day:”numeric”,weekday:”short”});

// 휠 빌더
function buildWheel(el, items, unit, selected){
el.innerHTML = ‘

‘;
items.forEach(v=>{
const d=document.createElement(“div”);
d.className=”item”; d.dataset.value=v; d.textContent=unit?`${v}${unit}`:v;
el.appendChild(d);
});
const idx=Math.max(0, items.indexOf(selected));
el.scrollTop = idx*40;
el.addEventListener(“scroll”, ()=>{ clearTimeout(el._t); el._t=setTimeout(()=>snapTo(el),80); });
snapTo(el);
}
function snapTo(el){
const i = Math.round(el.scrollTop/40);
el.scrollTo({ top:i*40, behavior:”smooth” });
[…el.querySelectorAll(“.item”)].forEach((n,ix)=> n.classList.toggle(“sel”, ix===i));
}
function getSelected(el){
const i = Math.round(el.scrollTop/40);
const items=[…el.querySelectorAll(“.item”)];
return parseInt(items[i]?.dataset.value || items[0].dataset.value,10);
}

// 데이터
const yearWheel = document.getElementById(“wheel-year”);
const monthWheel= document.getElementById(“wheel-month”);
const dayWheel = document.getElementById(“wheel-day”);
const hourWheel = document.getElementById(“wheel-hour”);
const now = new Date();
const YEARS = Array.from({length:100},(_,i)=> now.getFullYear()-i);
const MONTHS= Array.from({length:12},(_,i)=> i+1);
function daysIn(y,m){ return new Date(y,m,0).getDate(); }
function rebuildDays(){
const y=getSelected(yearWheel), m=getSelected(monthWheel);
const D=daysIn(y,m), cur=Math.min(getSelected(dayWheel)||1, D);
buildWheel(dayWheel, Array.from({length:D},(_,i)=>i+1), “일”, cur);
}

// 초기화
buildWheel(yearWheel, YEARS, “년”, now.getFullYear());
buildWheel(monthWheel, MONTHS, “월”, now.getMonth()+1);
rebuildDays();
buildWheel(hourWheel, Array.from({length:24},(_,i)=>i), “시”, 9);
[“wheel-year”,”wheel-month”].forEach(id=>{
const el=document.getElementById(id);
el.addEventListener(“scroll”, ()=>{ clearTimeout(el._re); el._re=setTimeout(rebuildDays,120); });
});

// API 호출
async function fetchFortune(){
const y=getSelected(yearWheel), m=getSelected(monthWheel), d=getSelected(dayWheel), h=getSelected(hourWheel);
const name=document.getElementById(“name”).value.trim();
const params = new URLSearchParams({ y,m,d,h, tz:”Asia/Seoul”, lang:”ko” });
if (name) params.set(“name”, name);

const res = await fetch(`${API_BASE}?${params.toString()}`, { cache:”no-store” });
const j = await res.json();
if (j.error) throw new Error(j.error);

// 바인딩
byId(“overall”).textContent = j.overall;
byId(“tip”).textContent = j.tip;
byId(“love”).textContent = j.love;
byId(“money”).textContent = j.money;
byId(“work”).textContent = j.work;
byId(“health”).textContent = j.health;
byId(“item”).textContent = j.item;
byId(“colorDot”).style.background = j.color.hex;
byId(“colorName”).textContent = `${j.color.name} (${j.color.hex})`;
byId(“number”).textContent = j.number;
byId(“time”).textContent = j.time;
byId(“keywords”).textContent= j.keywords.join(” · “);
byId(“profile”).textContent = `서양 별자리: ${j.profile.western} / 띠: ${j.profile.zodiac} / 시지: ${j.profile.hourSign}`;
}
function byId(id){ return document.getElementById(id); }

document.getElementById(“btnGo”).addEventListener(“click”, async ()=>{
try{ await fetchFortune(); } catch(e){ alert(“운세 호출 실패: “+e.message); }
});
document.getElementById(“btnCopy”).addEventListener(“click”, ()=>{
const t=[
`🌟 GS25 오늘의 운세 (${document.getElementById(‘today’).textContent})`,
`총운: ${byId(‘overall’).textContent}`,
`Tip: ${byId(‘tip’).textContent}`,
`사랑: ${byId(‘love’).textContent}`,
`금전: ${byId(‘money’).textContent}`,
`일: ${byId(‘work’).textContent}`,
`건강: ${byId(‘health’).textContent}`,
`아이템: ${byId(‘item’).textContent}`,
`컬러: ${byId(‘colorName’).textContent}`,
`넘버: ${byId(‘number’).textContent}`,
`럭키 타임: ${byId(‘time’).textContent}`,
`키워드: ${byId(‘keywords’).textContent}`,
`프로필: ${byId(‘profile’).textContent}`
].join(“n”);
navigator.clipboard.writeText(t).then(()=> alert(“운세를 복사했어요!”));
});

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *