/* ─── 인터랙티브 도구 11종 그리드 + 자가 마운트 + 잠금 모달 ────────────────────── */ /* 기존 파일 수정 없이, 매치업 섹션 다음에 자기 자신을 삽입한다. */ (function injectToolsStyles() { if (document.getElementById("__tools_styles")) return; const css = ` .tool-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:14px} @media (max-width: 1080px){ .tool-grid{grid-template-columns:repeat(2,1fr)} } @media (max-width: 600px){ .tool-grid{grid-template-columns:1fr} } .tool-card{ position:relative;overflow:hidden; background:var(--card);border:1px solid var(--hairline);border-radius:var(--r-xl); padding:18px;display:flex;flex-direction:column;gap:10px;min-height:172px;cursor:pointer; transition:border-color .15s, transform .15s, background .15s; } .tool-card:hover{border-color:var(--hairline-strong);transform:translateY(-2px);background:var(--card-2)} .tool-card .tc-icon{ width:38px;height:38px;border-radius:10px; display:flex;align-items:center;justify-content:center; background:linear-gradient(135deg, color-mix(in oklab, var(--mlb) 28%, var(--card-2)), color-mix(in oklab, var(--kbo) 26%, var(--card-2))); color:#fff; } .tool-card h3{margin:0;font-size:15.5px;font-weight:700;letter-spacing:-0.02em;line-height:1.3} .tool-card p{margin:0;font-size:12.5px;color:var(--text-2);line-height:1.5;text-wrap:pretty} .tool-card .tc-foot{display:flex;align-items:center;justify-content:space-between;margin-top:auto;padding-top:6px} .tool-card .tc-time{font-family:var(--num);font-size:11px;color:var(--text-3)} .tool-card .tc-stars{display:inline-flex;gap:1px;color:var(--warn);font-size:10px;line-height:1;position:absolute;top:18px;right:18px} .tool-card .tc-stars.dim{color:var(--text-3)} .tool-card.locked{cursor:pointer} .tool-card.locked .tc-inner{filter:blur(2.5px) saturate(0.6) brightness(0.85); opacity:0.55; pointer-events:none} .tool-card.locked::after{ content:"";position:absolute;inset:0;background:linear-gradient(180deg, rgba(11,14,20,0.0) 0%, rgba(11,14,20,0.55) 100%); pointer-events:none; } .tool-card .lock-stamp{ position:absolute;left:50%;top:50%;transform:translate(-50%,-50%) rotate(-6deg); z-index:2;display:inline-flex;align-items:center;gap:6px; font-family:var(--num);font-weight:700;font-size:11px;letter-spacing:0.18em; padding:6px 12px;border-radius:6px;color:#fff; background:rgba(255,75,75,0.18);border:1.5px solid var(--mlb); text-transform:uppercase; } /* fullscreen tool overlay */ .tool-overlay{ position:fixed;inset:0;z-index:80;background:rgba(11,14,20,0.78); backdrop-filter:blur(14px) saturate(140%);-webkit-backdrop-filter:blur(14px) saturate(140%); display:flex;align-items:stretch;justify-content:center;overflow-y:auto; animation: fadeIn .2s ease-out; } @keyframes fadeIn{from{opacity:0}to{opacity:1}} .tool-overlay-inner{ width:100%;max-width:1280px;margin:24px;background:var(--bg); border:1px solid var(--hairline);border-radius:var(--r-2xl); overflow:hidden;display:flex;flex-direction:column; } .tool-overlay-hd{ display:flex;align-items:center;justify-content:space-between; padding:18px 24px;border-bottom:1px solid var(--hairline); background:linear-gradient(180deg, #131822 0%, #0F141C 100%); } .tool-overlay-hd h2{margin:0;font-size:18px;font-weight:700;letter-spacing:-0.02em} .tool-overlay-hd .eb{font-size:11px;color:var(--text-3);letter-spacing:0.12em;text-transform:uppercase;margin-bottom:4px} .tool-close{ width:36px;height:36px;border-radius:10px;border:1px solid var(--hairline); background:transparent;color:var(--text-2);cursor:pointer; display:inline-flex;align-items:center;justify-content:center; } .tool-close:hover{background:rgba(255,255,255,0.05);color:var(--text)} /* lock email modal */ .lock-modal{ position:fixed;inset:0;z-index:90;background:rgba(11,14,20,0.78); backdrop-filter:blur(14px);display:flex;align-items:center;justify-content:center;padding:24px; animation: fadeIn .15s ease-out; } .lock-modal-inner{ width:100%;max-width:440px;background:var(--card);border:1px solid var(--hairline); border-radius:var(--r-xl);padding:28px; } /* dream team builder */ .dt-wrap{display:grid;grid-template-columns:1.1fr 1fr;gap:18px;padding:20px 24px} @media (max-width: 880px){ .dt-wrap{grid-template-columns:1fr} } .dt-panel{background:var(--card);border:1px solid var(--hairline);border-radius:var(--r-lg);padding:16px} .dt-slot{ display:grid;grid-template-columns:24px 1fr auto;gap:10px;align-items:center; padding:10px 12px;background:rgba(255,255,255,0.02);border:1px dashed var(--hairline); border-radius:10px;min-height:48px; } .dt-slot.filled{border-style:solid;background:var(--card-2)} .dt-slot .order{font-family:var(--num);font-weight:700;font-size:13px;color:var(--text-3);text-align:center} .dt-slot.filled .order{color:var(--mlb)} .dt-slot .empty{color:var(--text-3);font-size:13px} .dt-slot .remove{ appearance:none;border:0;background:transparent;color:var(--text-3);cursor:pointer; width:24px;height:24px;border-radius:6px;display:inline-flex;align-items:center;justify-content:center; } .dt-slot .remove:hover{background:rgba(255,255,255,0.05);color:var(--mlb)} .pp-list{display:flex;flex-direction:column;gap:6px;max-height:520px;overflow-y:auto;padding-right:4px} .pp-list::-webkit-scrollbar{width:6px} .pp-list::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.08);border-radius:3px} .pp-row{ display:grid;grid-template-columns:36px 1fr auto auto;gap:10px;align-items:center; padding:8px 10px;border-radius:10px;cursor:pointer;border:1px solid transparent; } .pp-row:hover{background:rgba(255,255,255,0.03);border-color:var(--hairline)} .pp-row.added{opacity:0.4;cursor:not-allowed} .pp-row .pp-av{ width:36px;height:36px;border-radius:50%;display:flex;align-items:center;justify-content:center; color:#fff;font-family:var(--num);font-weight:700;font-size:13px; } .pp-row .pp-name{font-size:13.5px;font-weight:600;line-height:1.2} .pp-row .pp-sub{font-size:11px;color:var(--text-3);margin-top:2px;font-family:var(--num)} .pp-row .pp-stat{font-family:var(--num);font-size:12px;color:var(--text-2);text-align:right;min-width:54px} .pp-row .pp-add{ width:26px;height:26px;border-radius:7px;background:rgba(255,255,255,0.04); border:1px solid var(--hairline);color:var(--text-2);cursor:pointer; display:inline-flex;align-items:center;justify-content:center;font-size:14px;line-height:1; } .pp-row.added .pp-add{background:var(--mlb-soft);color:var(--mlb);border-color:transparent} .chip-row{display:flex;flex-wrap:wrap;gap:6px} .chip{ display:inline-flex;align-items:center;gap:4px; padding:6px 10px;border-radius:999px;background:rgba(255,255,255,0.04); border:1px solid var(--hairline);color:var(--text-2);font-size:12px;cursor:pointer; font-family:var(--kr);font-weight:500; } .chip.on{background:var(--mlb-soft);color:var(--mlb);border-color:transparent} .chip.on.kbo{background:var(--kbo-soft);color:var(--kbo)} .dt-search{ display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:10px; background:rgba(255,255,255,0.04);border:1px solid var(--hairline); } .dt-search input{flex:1;background:transparent;border:0;color:var(--text);font:500 13px var(--kr);outline:none} .dt-search input::placeholder{color:var(--text-3)} .dt-summary{ display:grid;grid-template-columns:repeat(4,1fr);gap:10px; padding:14px 18px;background:var(--card-2);border-top:1px solid var(--hairline); } .dt-summary .k{font-size:10.5px;color:var(--text-3);letter-spacing:0.04em} .dt-summary .v{font-family:var(--num);font-size:18px;font-weight:700;margin-top:2px} /* share card preview */ .share-stage{ width:100%;max-width:360px;aspect-ratio:1080/1350; background:linear-gradient(180deg,#0B0E14 0%, #161B22 100%); border:1px solid var(--hairline);border-radius:var(--r-lg); padding:18px;display:flex;flex-direction:column;gap:10px;color:var(--text); } .share-stage .stage-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;flex:1} .share-stage .sg-cell{ background:rgba(255,255,255,0.04);border:1px solid var(--hairline);border-radius:10px; padding:8px 8px 10px;display:flex;flex-direction:column;align-items:center;gap:4px; } .share-stage .sg-cell .pp-av{width:34px;height:34px;font-size:11px} .share-stage .sg-cell .n{font-size:11px;font-weight:600} .share-stage .sg-cell .o{font-family:var(--num);font-size:9.5px;color:var(--mlb);font-weight:700} .share-stage .stage-foot{ display:flex;align-items:center;justify-content:space-between;padding-top:6px;border-top:1px solid var(--hairline); font-size:10px;color:var(--text-3);letter-spacing:0.06em;text-transform:uppercase; } /* heatzone */ .hz-wrap{display:grid;grid-template-columns:240px 1fr 260px;gap:18px;padding:20px 24px} @media (max-width: 980px){ .hz-wrap{grid-template-columns:1fr} } .hz-stage{ background:var(--card);border:1px solid var(--hairline);border-radius:var(--r-lg); padding:24px;display:flex;flex-direction:column;align-items:center;gap:18px; } .hz-zone{ width:100%;max-width:360px;aspect-ratio:1/1; display:grid;grid-template-columns:repeat(5,1fr);gap:4px; padding:14px;background:rgba(255,255,255,0.02);border:1px solid var(--hairline);border-radius:16px; position:relative; } .hz-cell{ position:relative;border-radius:6px;cursor:pointer;border:1px solid rgba(255,255,255,0.04); transition:transform .12s, box-shadow .12s; } .hz-cell:hover{transform:scale(1.04);box-shadow:0 0 0 2px var(--mlb)} .hz-cell.strike{border-color:rgba(255,255,255,0.12)} .hz-cell-tip{ position:absolute;left:50%;bottom:calc(100% + 6px);transform:translateX(-50%); background:var(--card-2);border:1px solid var(--hairline-strong);border-radius:8px; padding:8px 10px;min-width:120px;font-size:11px;color:var(--text-2); pointer-events:none;z-index:5;white-space:nowrap; box-shadow:0 12px 32px -10px rgba(0,0,0,0.6); } .hz-cell-tip .tipnum{font-family:var(--num);font-size:14px;font-weight:700;color:var(--text);letter-spacing:-0.02em} .hz-list{display:flex;flex-direction:column;gap:6px} .hz-list .row{ display:grid;grid-template-columns:18px 28px 1fr auto;gap:8px;align-items:center; padding:8px 10px;border-radius:8px;background:rgba(255,255,255,0.02); border:1px solid var(--hairline); } .hz-list .row .rk{font-family:var(--num);font-size:11px;color:var(--text-3);font-weight:600} .hz-list .row .mini{ width:24px;height:24px;display:grid;grid-template-columns:repeat(3,1fr);gap:1px; border:1px solid var(--hairline);border-radius:3px;padding:1px; } .hz-list .row .mini i{border-radius:1px;background:rgba(255,255,255,0.08)} .hz-list .row .v{font-family:var(--num);font-size:12px;font-weight:700} .hz-list .row .desc{font-size:11.5px;color:var(--text-2)} `; const tag = document.createElement("style"); tag.id = "__tools_styles"; tag.textContent = css; document.head.appendChild(tag); })(); /* ─── Tools data ────────────────────────────────────────────────────── */ const TOOLS = [ { id:"dreamteam", name:"드림팀 빌더", desc:"KBO·MLB 섞어 9명 라인업 + 선발 5명. 인스타 카드까지.", stars:3, ready:true, image:"images/sections/tool-dreamteam.png", icon: () }, { id:"wrapped", name:"시즌 결산 카드", desc:"한 시즌을 한 장에. 자동 집계되는 ‘당신의 2026’.", stars:3, image:"images/sections/tool-season-wrap.png", icon: () }, { id:"daily", name:"데일리 픽 챌린지", desc:"매일 한 문제. 30일 누적 정답에 황금 뱃지.", stars:2, image:"images/sections/tool-daily-pick.png", icon: () }, { id:"sim", name:"타구 시뮬레이터", desc:"발사각·타구속도 두 슬라이더로 홈런 확률 계산.", stars:3, image:"images/sections/tool-ball-sim.png", icon: () }, { id:"park", name:"구장 비교기", desc:"같은 타구, 잠실·펜웨이·사직·다저 어디서 홈런인가.", stars:2, image:"images/sections/tool-park-compare.png", icon: () }, { id:"streak", name:"30일 챌린지", desc:"매일 출석하고 푸시 알림으로 뱃지를 모은다.", stars:2, image:"images/sections/tool-30day.png", icon: () }, { id:"heatzone", name:"히트존 매핑", desc:"9구역 호버. 그 코스에서 타자가 어떻게 치는지.", stars:3, ready:true, image:"images/sections/tool-heatzone.png", icon: () }, { id:"whatif", name:"What-if 슬럼프", desc:"‘5월 슬럼프가 없었다면’ 가정만으로 시즌 다시 보기.", stars:3, image:"images/sections/tool-whatif.png", icon: () }, { id:"team-wrap", name:"응원팀 결산 카드", desc:"‘두산 팬의 2026’. 팀 전용 한 장 결산.", stars:2, image:"images/sections/tool-team-wrap.png", icon: () }, { id:"forecast", name:"다음 시즌 예측", desc:"내년 한국인 MLB 최고 활약 선수. 적중률도 공개.", stars:3, image:"images/sections/tool-forecast.png", icon: () }, { id:"legend", name:"레전드 vs 현역 1대1", desc:"박찬호 전성기 vs 류현진 현재. 가상 매치업.", stars:3, image:"images/sections/tool-legend.png", icon: () }, ]; function Stars({ n, dim }) { return ( {Array.from({length:3}).map((_,i)=>())} ); } function LockModal({ tool, onClose }) { const [email, setEmail] = React.useState(""); const [done, setDone] = React.useState(false); return (
e.stopPropagation()}>
곧 공개

{tool.name}

{tool.desc} 출시되면 가장 먼저 알려드릴게요.

{e.preventDefault();console.log("notify",tool.id,email);setDone(true);}}> setEmail(e.target.value)} placeholder="이메일 주소"/>
); } function ToolCard({ tool, onOpen }) { return (
onOpen(tool)}> {tool.image && (
)} {!tool.ready && 곧 공개}
{tool.icon}

{tool.name}

{tool.desc}

약 5분 {tool.ready && 열기 →}
); } function ToolsSection() { const [openTool, setOpenTool] = React.useState(null); const [locked, setLocked] = React.useState(null); const onOpen = (t) => { if (t.ready) setOpenTool(t.id); else setLocked(t); }; return (
인터랙티브 도구

직접 만져보는 야구 데이터

{TOOLS.length}개 · 2종 공개 · 9종 준비 중
{TOOLS.map(t => )}
※ 모든 도구는 데이터 기반 예측·참고용 분석 자료로 제공됩니다.
{openTool === "dreamteam" && window.ToolDreamteam && setOpenTool(null)}/>} {openTool === "heatzone" && window.ToolHeatzone && setOpenTool(null)}/>} {locked && setLocked(null)}/>}
); } /* ─── 자가 마운트: #matchup 다음에 자기 컨테이너를 삽입한다 ───────────────────── */ (function mountToolsAfterMatchup() { function mount() { if (document.getElementById("__tools_mount")) return; const matchup = document.getElementById("matchup"); if (!matchup) { setTimeout(mount, 80); return; } const host = document.createElement("div"); host.id = "__tools_mount"; matchup.insertAdjacentElement("afterend", host); ReactDOM.createRoot(host).render(); } if (document.readyState === "complete" || document.readyState === "interactive") { setTimeout(mount, 50); } else { document.addEventListener("DOMContentLoaded", () => setTimeout(mount, 50)); } })(); window.ToolsSection = ToolsSection;