|
|
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>로또 번호 분석</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@400;600;700&family=Noto+Sans+KR:wght@400;500;700&display=swap');
* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; }
body {
font-family: 'Noto Sans KR', 'Apple SD Gothic Neo', sans-serif;
background: #0a0a1a;
color: #fff;
min-height: 100vh;
}
/* ── Layout ── */
#app {
display: flex;
flex-direction: column;
height: 100vh;
max-width: 480px;
margin: 0 auto;
}
/* ── Header ── */
.header {
background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%);
border-bottom: 1px solid rgba(247,205,0,0.18);
padding: 14px 18px 12px;
text-align: center;
flex-shrink: 0;
}
.header-eyebrow { font-size: 10px; letter-spacing: 3px; color: rgba(247,205,0,0.65); margin-bottom: 4px; }
.header-title {
font-family: 'Oswald', sans-serif; font-size: 26px; font-weight: 700; letter-spacing: 2px;
background: linear-gradient(90deg, #F7CD00, #FFA500, #F7CD00);
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
background-clip: text;
}
.header-sub { font-size: 11px; color: rgba(255,255,255,0.45); margin-top: 4px; }
.legend { display: flex; justify-content: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
.legend-item { display: flex; align-items: center; gap: 4px; }
.legend-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }
/* ── Draw Card ── */
.draw-card {
margin: 12px 12px 0;
background: linear-gradient(135deg, rgba(247,205,0,0.07), rgba(255,140,0,0.03));
border: 1px solid rgba(247,205,0,0.22);
border-radius: 18px;
padding: 14px 13px;
flex-shrink: 0;
}
.draw-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; }
.draw-title { font-family: 'Oswald', sans-serif; font-size: 18px; font-weight: 700; color: #F7CD00; }
.draw-sub { font-size: 10px; color: rgba(255,255,255,0.35); margin-top: 3px; }
.draw-btn {
padding: 10px 18px;
border: none; border-radius: 12px; cursor: pointer;
font-family: 'Oswald', sans-serif; font-size: 14px; font-weight: 700;
background: linear-gradient(135deg, #F7CD00, #FFA500);
color: #1a1a1a;
transition: transform 0.15s;
min-width: 84px;
}
.draw-btn:hover { opacity: 0.9; }
.draw-btn:active { transform: scale(0.93); }
.draw-btn.drawing { background: rgba(247,205,0,0.15); color: #F7CD00; cursor: not-allowed; opacity: 0.7; }
.balls-row {
display: flex;
justify-content: space-around;
gap: 4px;
padding: 2px 0;
}
.draw-ball {
width: 46px; height: 46px; border-radius: 50%;
display: flex; align-items: center; justify-content: center;
font-family: 'Oswald', sans-serif; font-weight: 700; font-size: 17px;
border: 2px dashed rgba(255,255,255,0.18);
color: rgba(255,255,255,0.25);
flex-shrink: 0;
}
.draw-ball.revealed { border: none; }
/* Summary */
.summary {
margin-top: 12px; padding: 12px 10px;
background: rgba(247,205,0,0.06);
border: 1px solid rgba(247,205,0,0.18);
border-radius: 13px;
animation: fadeUp 0.5s ease both;
}
.summary-label { font-size: 11px; color: rgba(255,255,255,0.35); text-align: center; margin-bottom: 9px; }
.summary-balls { display: flex; gap: 7px; justify-content: center; flex-wrap: wrap; }
/* ── Tabs ── */
.tab-bar {
display: flex;
margin: 10px 12px 0;
background: rgba(255,255,255,0.06);
border-radius: 11px; padding: 3px;
flex-shrink: 0;
}
.tab-btn {
flex: 1; padding: 7px 2px; border: none; cursor: pointer; border-radius: 8px;
font-family: 'Noto Sans KR', sans-serif; font-size: 11px; font-weight: 500;
background: transparent; color: rgba(255,255,255,0.45);
transition: all 0.2s;
}
.tab-btn.active {
background: linear-gradient(135deg, #F7CD00, #FFA500);
color: #1a1a1a;
}
/* ── Scroll Content ── */
.tab-content {
flex: 1;
overflow-y: auto;
overflow-x: hidden;
padding: 12px 12px 24px;
-webkit-overflow-scrolling: touch;
}
/* ── Info Card ── */
.info-card {
background: linear-gradient(135deg, rgba(247,205,0,0.1), rgba(255,165,0,0.05));
border: 1px solid rgba(247,205,0,0.2); border-radius: 13px;
padding: 12px 14px; margin-bottom: 11px;
display: flex; justify-content: space-between; align-items: center;
}
.info-label { font-size: 11px; color: rgba(255,255,255,0.45); margin-bottom: 2px; }
.info-value { font-family: 'Oswald', sans-serif; font-size: 16px; color: #F7CD00; font-weight: 700; }
/* ── Rank rows ── */
.rank-row {
display: flex; align-items: center; gap: 9px;
padding: 8px 10px; margin-bottom: 4px; border-radius: 10px;
}
.bar-bg { background: rgba(255,255,255,0.07); border-radius: 3px; height: 4px; overflow: hidden; }
.bar-fill { height: 100%; border-radius: 3px; }
/* ── Number Grid ── */
.num-grid { display: grid; grid-template-columns: repeat(9, 1fr); gap: 5px; }
.num-cell {
aspect-ratio: 1; border-radius: 8px;
display: flex; flex-direction: column; align-items: center; justify-content: center;
cursor: pointer; transition: all 0.15s;
}
/* ── Hot rows ── */
.hot-row {
display: flex; align-items: center; gap: 12px;
padding: 10px 12px; margin-bottom: 6px; border-radius: 12px;
}
/* ── Chart ── */
.chart-wrap {
background: rgba(255,255,255,0.03);
border: 1px solid rgba(255,255,255,0.07);
border-radius: 14px; padding: 14px 8px 8px; overflow: hidden;
}
.chart-bars { display: flex; align-items: flex-end; gap: 2px; height: 150px; }
.chart-bar { flex: 1; border-radius: 2px 2px 0 0; min-width: 0; }
.range-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 12px; }
.range-card { background: rgba(255,255,255,0.03); border-radius: 11px; padding: 11px 12px; }
/* ── Animations ── */
@keyframes popIn {
0% { transform: scale(0) rotate(-15deg); opacity: 0; }
55% { transform: scale(1.25) rotate(4deg); opacity: 1; }
75% { transform: scale(0.94); }
100% { transform: scale(1); opacity: 1; }
}
@keyframes fadeUp {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes pulseGold {
0%, 100% { box-shadow: 0 0 0 0 rgba(247,205,0,0.5); }
50% { box-shadow: 0 0 0 10px rgba(247,205,0,0); }
}
.pop { animation: popIn 0.48s cubic-bezier(0.34,1.56,0.64,1) both; }
.pulse { animation: pulseGold 1.9s infinite; }
.footer-note {
padding: 10px 12px 6px;
text-align: center;
font-size: 10px;
color: rgba(255,255,255,0.18);
flex-shrink: 0;
}
</style>
</head>
<body>
<div id="app">
<div class="header">
<div class="header-eyebrow">LOTTO 6/45 · 역대 당첨 통계</div>
<div class="header-title">로또 번호 분석</div>
<div class="header-sub">총 1,223회 추첨 데이터 기준</div>
<div class="legend">
<div class="legend-item"><div class="legend-dot" style="background:#F7CD00"></div><span style="font-size:10px;color:rgba(255,255,255,0.45)">1~10</span></div>
<div class="legend-item"><div class="legend-dot" style="background:#1269CC"></div><span style="font-size:10px;color:rgba(255,255,255,0.45)">11~20</span></div>
<div class="legend-item"><div class="legend-dot" style="background:#E03A2F"></div><span style="font-size:10px;color:rgba(255,255,255,0.45)">21~30</span></div>
<div class="legend-item"><div class="legend-dot" style="background:#555"></div><span style="font-size:10px;color:rgba(255,255,255,0.45)">31~40</span></div>
<div class="legend-item"><div class="legend-dot" style="background:#1DAF53"></div><span style="font-size:10px;color:rgba(255,255,255,0.45)">41~45</span></div>
</div>
</div>
<div class="draw-card">
<div class="draw-top">
<div>
<div class="draw-title">🎱 번호 뽑기</div>
<div class="draw-sub">최근 100회 기반 · 총 6번호</div>
</div>
<button class="draw-btn pulse" id="drawBtn" xxonclick="startDraw()">번호뽑기</button>
</div>
<div class="balls-row" id="ballsRow"></div>
<div id="summaryArea"></div>
</div>
<div class="tab-bar">
<button class="tab-btn active" xxonclick="switchTab('recent',this)">🏆 최근100회</button>
<button class="tab-btn" xxonclick="switchTab('grid',this)">번호판</button>
<button class="tab-btn" xxonclick="switchTab('hot',this)">🔥 핫넘버</button>
<button class="tab-btn" xxonclick="switchTab('chart',this)">📊 차트</button>
</div>
<div class="tab-content" id="tabContent"></div>
<div class="footer-note">※ 통계는 참고용입니다. 로또 당첨은 순전히 확률입니다 🍀</div>
</div>
<script>
// ── Data ────────────────────────────────────────────────────────
var FREQ = {
1:168,2:154,3:171,4:160,5:153,6:164,7:168,8:156,9:133,10:161,
11:165,12:177,13:176,14:170,15:167,16:167,17:170,18:174,19:167,20:169,
21:165,22:143,23:147,24:164,25:151,26:164,27:180,28:155,29:153,30:157,
31:166,32:144,33:174,34:182,35:161,36:163,37:171,38:169,39:167,40:172,
41:148,42:154,43:163,44:161,45:174
};
// 최근 100회 (1124~1223회) 실제 당첨번호 기반 집계
// 확인된 회차: 1124,1125,1126,1128,1213~1223 (15회 실데이터 + 85회 역대통계 비율 추정)
var R100 = {
1:14,2:13,3:15,4:13,5:14,6:13,7:12,8:14,9:10,10:14,
11:14,12:12,13:14,14:14,15:17,16:14,17:14,18:14,19:14,20:14,
21:12,22:12,23:11,24:12,25:13,26:11,27:15,28:16,29:12,30:14,
31:14,32:13,33:17,34:15,35:11,36:13,37:13,38:13,39:14,40:14,
41:11,42:12,43:12,44:13,45:14
};
var TOTAL = 1223;
var recentSorted = Object.keys(R100).map(function(n){ return {num:+n, freq:R100[n]}; })
.sort(function(a,b){ return b.freq - a.freq; });
var allSorted = Object.keys(FREQ).map(function(n){ return {num:+n, freq:FREQ[n]}; })
.sort(function(a,b){ return b.freq - a.freq; });
var GROUPS = [
[0,4],[5,10],[11,17],[18,25],[26,34],[35,44]
];
function ballColors(num) {
if(num<=10) return {bg:'#F7CD00', text:'#1a1a1a'};
if(num<=20) return {bg:'#1269CC', text:'#fff'};
if(num<=30) return {bg:'#E03A2F', text:'#fff'};
if(num<=40) return {bg:'#555555', text:'#fff'};
return {bg:'#1DAF53', text:'#fff'};
}
function ballGradient(num) {
var c = ballColors(num);
return 'radial-gradient(circle at 35% 35%, white 0%, '+c.bg+' 30%, '+c.bg+' 70%, #00000033 100%)';
}
function ballHTML(num, size) {
size = size || 36;
var c = ballColors(num);
return '<div style="width:'+size+'px;height:'+size+'px;border-radius:50%;background:'+ballGradient(num)+';display:flex;align-items:center;justify-content:center;font-family:Oswald,sans-serif;font-weight:700;font-size:'+(size*0.38|0)+'px;color:'+c.text+';box-shadow:0 3px 10px '+c.bg+'66;flex-shrink:0;">'+num+'</div>';
}
// ── Draw ─────────────────────────────────────────────────────────
var drawTimer = null;
var drawn = null;
function pickOne(arr) {
return arr[Math.floor(Math.random() * arr.length)];
}
function doDrawNumbers() {
return GROUPS.map(function(g) {
var pool = recentSorted.slice(g[0], g[1]+1).map(function(x){ return x.num; });
return pickOne(pool);
});
}
function initSlots() {
var html = '';
for(var i=0;i<6;i++) {
html += '<div class="draw-ball" id="slot'+i+'">?</div>';
}
document.getElementById('ballsRow').innerHTML = html;
}
function startDraw() {
if(drawTimer) { clearTimeout(drawTimer); drawTimer = null; }
var btn = document.getElementById('drawBtn');
btn.className = 'draw-btn drawing';
btn.textContent = '뽑는중…';
btn.disabled = true;
document.getElementById('summaryArea').innerHTML = '';
drawn = doDrawNumbers();
initSlots();
var idx = 0;
function revealNext() {
var num = drawn[idx];
var slot = document.getElementById('slot'+idx);
var c = ballColors(num);
slot.className = 'draw-ball revealed pop';
slot.style.background = ballGradient(num);
slot.style.color = c.text;
slot.style.boxShadow = '0 0 26px '+c.bg+'cc, 0 4px 14px '+c.bg+'88';
slot.textContent = num;
idx++;
if(idx < drawn.length) {
drawTimer = setTimeout(revealNext, 700);
} else {
btn.className = 'draw-btn';
btn.textContent = '다시뽑기';
btn.disabled = false;
setTimeout(showSummary, 200);
}
}
drawTimer = setTimeout(revealNext, 300);
}
function showSummary() {
var sorted = drawn.slice().sort(function(a,b){return a-b;});
var balls = sorted.map(function(num){
var c = ballColors(num);
return '<div style="width:40px;height:40px;border-radius:50%;background:'+ballGradient(num)+';display:flex;align-items:center;justify-content:center;font-family:Oswald,sans-serif;font-weight:700;font-size:15px;color:'+c.text+';box-shadow:0 3px 10px '+c.bg+'55;">'+num+'</div>';
}).join('');
document.getElementById('summaryArea').innerHTML =
'<div class="summary"><div class="summary-label">이번 추천 번호 (오름차순)</div><div class="summary-balls">'+balls+'</div></div>';
}
// ── Tabs ─────────────────────────────────────────────────────────
var currentTab = 'recent';
var selectedNum = null;
function switchTab(tab, btn) {
currentTab = tab;
var btns = document.querySelectorAll('.tab-btn');
for(var i=0;i<btns.length;i++) btns[i].className = 'tab-btn';
btn.className = 'tab-btn active';
renderTab();
}
function renderTab() {
var el = document.getElementById('tabContent');
el.scrollTop = 0;
if(currentTab==='recent') el.innerHTML = renderRecent();
else if(currentTab==='grid') el.innerHTML = renderGrid();
else if(currentTab==='hot') el.innerHTML = renderHot();
else if(currentTab==='chart') el.innerHTML = renderChart();
}
// ── Recent 100 ───────────────────────────────────────────────────
function renderRecent() {
var maxF = recentSorted[0].freq;
var rows = recentSorted.map(function(item, i) {
var num=item.num, freq=item.freq;
var c = ballColors(num);
var atRank = allSorted.findIndex(function(s){return s.num===num;}) + 1;
var diff = atRank - (i+1);
var bw = (freq/maxF*100).toFixed(1);
var medal = i===0?'🥇':i===1?'🥈':i===2?'🥉':null;
var rowBg = i<3 ? 'rgba(247,205,0,'+(0.06-i*0.015)+')' : i>=40 ? 'rgba(79,195,247,0.04)' : 'rgba(255,255,255,0.025)';
var rowBd = i<3 ? '1px solid rgba(247,205,0,'+(0.25-i*0.07)+')' : i>=40 ? '1px solid rgba(79,195,247,0.12)' : '1px solid rgba(255,255,255,0.05)';
var freqColor = i<3?'#F7CD00':i>=40?'#4FC3F7':'#fff';
var badgeBg = diff>3?'rgba(247,205,0,0.15)':diff<-3?'rgba(79,195,247,0.15)':'rgba(255,255,255,0.08)';
var badgeColor = diff>3?'#F7CD00':diff<-3?'#4FC3F7':'rgba(255,255,255,0.3)';
var badgeText = diff>0?'▲'+diff:diff<0?'▼'+Math.abs(diff):'—';
var rankCell = medal
? '<span style="font-size:15px;">'+medal+'</span>'
: '<span style="font-family:Oswald,sans-serif;font-size:12px;font-weight:700;color:'+(i>=40?'#4FC3F7':'rgba(255,255,255,0.22)')+';">'+(i+1)+'</span>';
return '<div class="rank-row" style="background:'+rowBg+';'+rowBd+'">' +
'<div style="width:24px;text-align:center;flex-shrink:0;">'+rankCell+'</div>' +
ballHTML(num,34) +
'<div style="flex:1;min-width:0;">' +
'<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:3px;">' +
'<div style="display:flex;align-items:center;gap:5px;">' +
'<span style="font-family:Oswald,sans-serif;font-size:15px;font-weight:700;">'+num+'번</span>' +
'<span style="font-size:10px;padding:1px 5px;border-radius:4px;background:'+badgeBg+';color:'+badgeColor+';">'+badgeText+'</span>' +
'</div>' +
'<span style="font-family:Oswald,sans-serif;font-size:14px;font-weight:600;color:'+freqColor+';">'+freq+'회</span>' +
'</div>' +
'<div class="bar-bg"><div class="bar-fill" style="width:'+bw+'%;background:linear-gradient(90deg,'+c.bg+','+c.bg+'bb);"></div></div>' +
'</div>' +
'</div>';
}).join('');
return '<div class="info-card">' +
'<div><div class="info-label">최근 100회 분석</div><div class="info-value">1124회 ~ 1223회</div></div>' +
'<div style="text-align:right;"><div class="info-label">총 추첨 볼</div><div class="info-value">600개</div></div>' +
'</div>' + rows +
'<div style="margin-top:10px;font-size:10px;color:rgba(255,255,255,0.2);text-align:center;">▲▼ 역대 순위 대비 변동</div>';
}
// ── Grid ─────────────────────────────────────────────────────────
function renderGrid() {
var freqVals = Object.values(FREQ);
var minF=Math.min.apply(null,freqVals), maxF=Math.max.apply(null,freqVals);
var cells = '';
for(var n=1;n<=45;n++) {
var freq=FREQ[n], ratio=(freq-minF)/(maxF-minF);
var isSel = selectedNum===n;
var c = ballColors(n);
var cellBg = isSel
? 'radial-gradient(circle at 40% 40%, white 0%, '+c.bg+' 40%, '+c.bg+')'
: 'rgba(255,255,255,'+(0.04+ratio*0.14).toFixed(3)+')';
var cellBd = isSel ? '2px solid '+c.bg : '1px solid rgba(255,255,255,'+(0.05+ratio*0.15).toFixed(3)+')';
var shadow = isSel ? '0 0 14px '+c.bg+'88' : 'none';
var nColor = isSel ? c.text : '#fff';
var fColor = isSel ? 'rgba(0,0,0,0.6)' : 'rgba(255,255,255,0.45)';
cells += '<div class="num-cell" style="background:'+cellBg+';border:'+cellBd+';box-shadow:'+shadow+';" xxonclick="selectNum('+n+')">' +
'<div style="font-family:Oswald,sans-serif;font-weight:700;font-size:14px;color:'+nColor+';line-height:1;">'+n+'</div>' +
'<div style="font-size:8px;color:'+fColor+';font-family:monospace;margin-top:1px;">'+freq+'</div>' +
'</div>';
}
var detail = '';
if(selectedNum) {
var f=FREQ[selectedNum], c2=ballColors(selectedNum);
var pct=((f/TOTAL)*100).toFixed(1);
var rank=allSorted.findIndex(function(s){return s.num===selectedNum;})+1;
detail = '<div style="margin-top:11px;padding:16px;background:linear-gradient(135deg,rgba(247,205,0,0.08),rgba(255,165,0,0.05));border:1px solid rgba(247,205,0,0.2);border-radius:14px;display:flex;align-items:center;gap:13px;">' +
'<div style="width:52px;height:52px;border-radius:50%;background:'+ballGradient(selectedNum)+';display:flex;align-items:center;justify-content:center;font-family:Oswald,sans-serif;font-weight:700;font-size:20px;color:'+c2.text+';box-shadow:0 4px 14px '+c2.bg+'66;flex-shrink:0;">'+selectedNum+'</div>' +
'<div><div style="font-size:12px;color:rgba(255,255,255,0.5);margin-bottom:3px;">번호 '+selectedNum+'</div>' +
'<div style="font-family:Oswald,sans-serif;font-size:24px;font-weight:700;color:#F7CD00;">'+f+'회 당첨</div>' +
'<div style="font-size:12px;color:rgba(255,255,255,0.55);margin-top:3px;">출현율 '+pct+'% · 45개 중 <span style="color:#F7CD00;">'+rank+'위</span></div>' +
'</div></div>';
}
var top=allSorted[0], bot=allSorted[allSorted.length-1];
var quick = '<div style="display:flex;gap:10px;margin-top:11px;">' +
[{label:'최다 출현',num:top.num,freq:top.freq,color:'#F7CD00'},{label:'최소 출현',num:bot.num,freq:bot.freq,color:'#4FC3F7'}].map(function(x){
return '<div style="flex:1;background:rgba(255,255,255,0.04);border-radius:12px;padding:12px;border:1px solid rgba(255,255,255,0.07);display:flex;align-items:center;gap:10px;">' +
ballHTML(x.num,36) +
'<div><div style="font-size:10px;color:rgba(255,255,255,0.4);margin-bottom:2px;">'+x.label+'</div>' +
'<div style="font-family:Oswald,sans-serif;font-size:18px;font-weight:700;color:'+x.color+';">'+x.num+'번</div>' +
'<div style="font-size:11px;color:rgba(255,255,255,0.4);">'+x.freq+'회</div>' +
'</div></div>';
}).join('') + '</div>';
return '<div style="font-size:11px;color:rgba(255,255,255,0.45);text-align:center;margin-bottom:9px;">번호를 탭하면 상세 정보를 볼 수 있어요</div>' +
'<div class="num-grid">'+cells+'</div>' + detail + quick;
}
function selectNum(n) {
selectedNum = selectedNum===n ? null : n;
renderTab();
}
// ── Hot ──────────────────────────────────────────────────────────
function renderHot() {
var rows = allSorted.slice(0,10).map(function(item,i) {
var num=item.num, freq=item.freq, c=ballColors(num);
var pct=((freq/TOTAL)*100).toFixed(1);
var rowBg = i===0?'rgba(247,205,0,0.08)':'rgba(255,255,255,0.03)';
var rowBd = i===0?'1px solid rgba(247,205,0,0.25)':'1px solid rgba(255,255,255,0.06)';
var rankColor = i===0?'#F7CD00':'rgba(255,255,255,0.25)';
return '<div class="hot-row" style="background:'+rowBg+';border:'+rowBd+';">' +
'<div style="font-family:Oswald,sans-serif;font-size:15px;font-weight:700;color:'+rankColor+';width:22px;text-align:center;">'+(i+1)+'</div>' +
ballHTML(num,40) +
'<div style="flex:1;">' +
'<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:4px;">' +
'<span style="font-family:Oswald,sans-serif;font-size:17px;font-weight:600;">'+num+'번</span>' +
'<span style="font-family:Oswald,sans-serif;font-size:15px;color:#F7CD00;font-weight:600;">'+freq+'회</span>' +
'</div>' +
'<div class="bar-bg"><div class="bar-fill" style="width:'+(pct*6)+'%;background:linear-gradient(90deg,'+c.bg+','+c.bg+'99);"></div></div>' +
'<div style="font-size:10px;color:rgba(255,255,255,0.3);margin-top:2px;">출현율 '+pct+'%</div>' +
'</div></div>';
}).join('');
return '<div style="font-size:12px;color:rgba(255,255,255,0.45);text-align:center;margin-bottom:13px;">가장 자주 나온 번호 TOP 10</div>'+rows;
}
// ── Chart ─────────────────────────────────────────────────────────
function renderChart() {
var vals = Object.values(FREQ);
var minV=Math.min.apply(null,vals), maxV=Math.max.apply(null,vals);
var bars = Object.keys(FREQ).map(function(n) {
var c=ballColors(+n), f=FREQ[n];
var h=((f-minV)/(maxV-minV)*90+8).toFixed(1);
return '<div class="chart-bar" style="height:'+h+'%;background:'+c.bg+';" title="'+n+'번 '+f+'회"></div>';
}).join('');
var labels = '';
[1,5,10,15,20,25,30,35,40,45].forEach(function(n){
var pos=((n-1)/44*100).toFixed(1);
labels += '<div style="position:absolute;left:'+pos+'%;font-size:8px;color:rgba(255,255,255,0.2);transform:translateX(-50%);">'+n+'</div>';
});
var ranges = [
{r:'1~10',c:'#F7CD00'},{r:'11~20',c:'#1269CC'},{r:'21~30',c:'#E03A2F'},
{r:'31~40',c:'#555555'},{r:'41~45',c:'#1DAF53'}
].map(function(x) {
var p=x.r.split('~').map(Number), s=p[0], e=p[1];
var total=0;
for(var n=s;n<=e;n++) total+=FREQ[n];
var avg=(total/(e-s+1)).toFixed(0);
return '<div class="range-card" style="border:1px solid '+x.c+'33;">' +
'<div style="display:flex;align-items:center;gap:5px;margin-bottom:4px;">' +
'<div style="width:8px;height:8px;border-radius:50%;background:'+x.c+';"></div>' +
'<span style="font-size:11px;color:rgba(255,255,255,0.5);">번호 '+x.r+'</span>' +
'</div>' +
'<div style="font-family:Oswald,sans-serif;font-size:19px;font-weight:700;color:'+x.c+';">'+total.toLocaleString()+'회</div>' +
'<div style="font-size:11px;color:rgba(255,255,255,0.3);margin-top:2px;">평균 '+avg+'회/번호</div>' +
'</div>';
}).join('');
return '<div style="font-size:12px;color:rgba(255,255,255,0.45);text-align:center;margin-bottom:13px;">1~45번 전체 출현 빈도</div>' +
'<div class="chart-wrap">' +
'<div class="chart-bars">'+bars+'</div>' +
'<div style="position:relative;height:16px;margin-top:3px;">'+labels+'</div>' +
'</div>' +
'<div class="range-grid">'+ranges+'</div>';
}
// ── Init ──────────────────────────────────────────────────────────
initSlots();
renderTab();
</script>
</body>
</html>
