One Menu, Every Korea
크리켓 서울의 메뉴는 한국의 모든 면에서 영감을 얻습니다. 음식 문화, 도시와 시골의 대비, 뚜렷한 사계절, 그리고 한국만의 감성. 이 요소들을 크리켓의 시선으로 풀어 동시대의 칵테일로 옮깁니다.
Tap System
한국식 칵테일을 탭 시스템으로 제공해 가볍고 편하게 즐기도록 했습니다. 손님은 무알콜과 알콜 중에서 고를 수 있습니다.
Onggi & Bamboo Aging
옹기와 대나무에 숙성한 칵테일은 오크와 달리 더 부드럽고, 은은한 산미를 더합니다. 나무통이 아닌 한국의 그릇으로 시간을 담습니다.
Locally Sourced
음식과 칵테일을 오직 한국 현지 재료로만 만듭니다. 지역 자원을 산업 안에서 실제로 지속 가능하게 쓰는 방식을 믿습니다.
Sharing Project
크리켓 서울은 지역의 양조장과 장인, 예술가와 손잡고 그들의 술과 작업을 칵테일로 풀어냅니다. 크리켓에서 시작한 지역 막걸리 양조장과의 협업처럼, 재료와 장인정신과 현대의 바 문화를 잇는 새로운 방식을 이어갑니다. 목표는 하나입니다. 한국의 아름다움을 더 많은 사람과 나누는 것.
`).join("");
}
/* ===== 전통주 도감 렌더 ===== */
let soolFilter="all";
const soolChips=document.getElementById("soolChips");
function renderSoolChips(){
soolChips.innerHTML=`${esc(t('chips.all'))} `+CATS.map(c=>`${esc(t('cat.'+c.k+'.label'))} `).join("");
soolChips.querySelectorAll(".chip").forEach(ch=>{ch.classList.toggle("on",ch.dataset.k===soolFilter);ch.onclick=()=>{soolFilter=ch.dataset.k;soolChips.querySelectorAll(".chip").forEach(x=>x.classList.toggle("on",x===ch));renderSool();};});
}
function siteLink(id){
const u=SITES[id];
if(!u) return "";
return `${esc(t('site.official'))} ↗ `;
}
/* 양조장 공식 사이트. 검색으로 찾은 뒤 실제로 열어 회사명·주소·제품을 확인한 것만 넣는다.
확인 못 한 곳은 비워둔다 (틀린 링크는 없느니만 못함) */
const SITES={
boksundoga:"https://boksoon.com/",
sucre:"https://jubangjangbrewery.com/",
fogmag:"https://dalseong.co/",
"ellyeop-takju":"http://www.ellyeoppyunjoo.com/",
"ellyeop-cheongju":"http://www.ellyeoppyunjoo.com/",
ihwaju:"http://sool.ksdb.co.kr/product/product_010100.asp",
"inner-nectar":"http://www.bewaterbrew.com/",
"inner-flow":"http://www.bewaterbrew.com/",
"inner-calm":"http://www.bewaterbrew.com/",
pungjeong:"https://hwayang.co/",
hwajeonilchwi:"https://hwajeonilchwi.com/",
"gyeongseong-gwahaju":"https://soolawon.co.kr/",
"daetong-daeip":"http://chusungju.co.kr/",
"sahwa-yuja":"https://sahwa.co.kr/",
"omirose-premier":"https://omynara.com/",
"omirose-yeon":"https://omynara.com/",
"omirose-gyeol":"https://omynara.com/",
"gowoon-oak":"https://omynara.com/",
"gowoon-baekja":"https://omynara.com/",
"kiwi-sool":"https://sooldogajeju.com/",
moonbaesool:"https://www.moonbaesool.co.kr/",
ryu24:"https://ryu-distillery.com/",
damsol:"https://www.solsongju.com/",
"hwayo-xp":"https://hwayo.com/",
soorok:"https://danongbio.co.kr/",
"kione-eagle":"https://threesocieties.co.kr/",
"kione-tiger":"https://threesocieties.co.kr/",
"kione-unicorn":"https://threesocieties.co.kr/",
"kione-signature":"https://threesocieties.co.kr/",
"kione-batch8":"https://threesocieties.co.kr/",
"kione-edward":"https://threesocieties.co.kr/",
"ggeek-pale":"https://www.ggeekbeer.com/",
"ggeek-porter":"https://www.ggeekbeer.com/",
chusa40:"https://xn--vf4b19u.com/",
chusa50:"https://xn--vf4b19u.com/",
mongro:"https://xn--vf4b19u.com/"
};
function bBody(b){
const r=rzOf(b.id);
if(!r) return `${esc(b.desc)}${siteLink(b.id)}
`;
let h=``;
if(r.oneLine) h+=`
“${esc(r.oneLine)}”
`;
if(r.taste) h+=`
${esc(lbl('taste'))} ${esc(r.taste)}
`;
if(r.feature) h+=`
${esc(lbl('feature'))} ${esc(r.feature)}
`;
if(r.history) h+=`
${esc(lbl('history'))} ${esc(r.history)}
`;
h+=siteLink(b.id);
return h+`
`;
}
function renderSool(){
const host=document.getElementById("soolList");
const cats=CATS.filter(c=>soolFilter==="all"||c.k===soolFilter);
host.innerHTML=cats.map(c=>{
const list=BOTTLES.filter(b=>b.cat===c.k);
return `${esc(t('cat.'+c.k+'.label'))} ${list.length}
${esc(t('cat.'+c.k+'.desc'))}
${list.map(b=>{const rk=(RES.ko||{})[b.id];return `
${esc(b.kr)}
${esc(b.name)}
${b.abv}% ${priceStr(b)}
${b.region?`${esc(regName(b.region))} `:`${esc(fl('unknown'))} `}${b.flag?`${esc(fl('verify'))} `:''}${rk&&rk.conf==='low'?`${esc(fl('low'))} `:''}
${bBody(b)}
`;}).join("")}
`;
}).join("");
}
renderSool();
/* ===== 도별 인터랙티브 지도 ===== */
const SVGNS="http://www.w3.org/2000/svg";
// 도시(region) → 시도 코드
const PROV_OF={seoul:'11',incheon:'23',yangpyeong:'31',hwaseong:'31',yongin:'31',yeoju:'31',gimpo:'31',guri:'31',namyangju:'31',hoengseong:'32',chuncheon:'32',cheongju:'33',chungju:'33',yeongdong:'33',gongju:'34',yesan:'34',daejeon:'25',daegu:'22',andong:'37',sangju:'37',mungyeong:'37',gimhae:'38',hamyang:'38',changwon:'38',sacheon:'38',ulsan:'26',jeonju:'35',sunchang:'35',gochang:'35',damyang:'36',naju:'36',jeju:'39',goyang:'31'};
function cityXY(la,lo){const p=MAPDATA.proj;return [(lo*p.cosLat-p.minX)*p.S+p.pad,(-la-p.minY)*p.S+p.pad];}
let activeProv=null, zoomed=false, vbAnim=null;
let VB={x:0,y:0,w:0,h:0};
const BACKTXT={ko:"← 전체 지도",en:"← Whole map",zh:"← 全国地图",ja:"← 全体マップ"};
function el(tag,attrs){const e=document.createElementNS(SVGNS,tag);for(const k in attrs)e.setAttribute(k,attrs[k]);return e;}
function setVB(x,y,w,h){VB={x,y,w,h};document.getElementById("mapsvg").setAttribute("viewBox",x.toFixed(1)+" "+y.toFixed(1)+" "+w.toFixed(1)+" "+h.toFixed(1));}
function animVB(tx,ty,tw,th,dur,done){
const s={...VB},t0=performance.now();
if(vbAnim)cancelAnimationFrame(vbAnim);
const ease=k=>k<.5?4*k*k*k:1-Math.pow(-2*k+2,3)/2;
(function step(now){
const k=Math.min(1,(now-t0)/dur),e=ease(k);
setVB(s.x+(tx-s.x)*e,s.y+(ty-s.y)*e,s.w+(tw-s.w)*e,s.h+(th-s.h)*e);
scaleOverlay();
if(k<1)vbAnim=requestAnimationFrame(step);else{vbAnim=null;if(done)done();}
})(performance.now());
}
// 줌 배율에 맞춰 글자·점·선 크기를 화면상 일정하게 유지
function scaleOverlay(){
const s=VB.w/MAPDATA.vbW;
document.querySelectorAll("#mapMuni .muni").forEach(p=>{p.setAttribute("stroke-dasharray",(3.2*s).toFixed(2)+" "+(2.4*s).toFixed(2));});
document.querySelectorAll("#mapDyn .mdot").forEach(d=>d.setAttribute("r",(4.6*s).toFixed(2)));
document.querySelectorAll("#mapDyn .mhit").forEach(d=>d.setAttribute("r",(30*s).toFixed(2)));
document.querySelectorAll("#mapDyn .mdot-label").forEach(t=>t.setAttribute("font-size",(9*s).toFixed(2)));
document.querySelectorAll("#mapDyn .prov-label").forEach(t=>t.setAttribute("font-size",(16*s).toFixed(2)));
}
function buildMap(){
const svg=document.getElementById("mapsvg");
svg.setAttribute("preserveAspectRatio","xMidYMid meet");
setVB(0,0,MAPDATA.vbW,MAPDATA.vbH);
const provCount={};BOTTLES.forEach(b=>{if(b.region&&PROV_OF[b.region])provCount[PROV_OF[b.region]]=(provCount[PROV_OF[b.region]]||0)+1;});
svg.innerHTML="";
// 작은 광역시는 도에 가려지지 않게 나중에 그린다
const METRO=["11","21","22","23","24","25","26","29"];
const ordered=[...MAPDATA.provinces].sort((a,b)=>(METRO.indexOf(a.code)>=0?1:0)-(METRO.indexOf(b.code)>=0?1:0));
ordered.forEach(p=>{
const path=el("path",{class:"prov"+(provCount[p.code]?" has":"")+(METRO.indexOf(p.code)>=0?" metro":""),id:"prov-"+p.code,d:p.d});
path.addEventListener("click",e=>{e.stopPropagation();activateProv(p.code);});
svg.appendChild(path);
});
svg.appendChild(el("g",{id:"mapMuni"})); // 시군구 점선
svg.appendChild(el("g",{id:"mapDyn"})); // 라벨+양조지 점
}
function activateProv(code){
activeProv=code;zoomed=true;
const svg=document.getElementById("mapsvg");
[...svg.querySelectorAll(".prov")].forEach(pp=>{pp.classList.toggle("active",pp.id==="prov-"+code);pp.classList.toggle("dim",pp.id!=="prov-"+code);});
const activeEl=document.getElementById("prov-"+code);
const muni=document.getElementById("mapMuni"),dyn=document.getElementById("mapDyn");
svg.insertBefore(activeEl,muni);
// 시군구 경계(점선)
muni.innerHTML="";
((window.MAPMUNI||{})[code]||[]).forEach(m=>muni.appendChild(el("path",{class:"muni",d:m.d})));
// 실제 화면 확대: viewBox를 그 도의 영역으로
const bb=activeEl.getBBox();
const aspect=MAPDATA.vbW/MAPDATA.vbH;
let w=bb.width,h=bb.height;
if(w/hp.code===code);
dyn.innerHTML="";
const label=el("text",{class:"prov-label",x:cx,y:bb.y-bb.height*0.04,"text-anchor":"middle"});
label.textContent=provName(prov.code,prov.kr);dyn.appendChild(label);
const cities=Object.keys(PROV_OF).filter(k=>PROV_OF[k]===code);
cities.forEach((k,i)=>{
const cnt=BOTTLES.filter(b=>b.region===k).length; if(!cnt) return;
const[x,y]=cityXY(REG[k].la,REG[k].lo);
const pick=e=>{e.stopPropagation();selectCity(k);};
// 실제로 눌리는 영역 (투명, 점보다 훨씬 크게)
const hit=el("circle",{class:"mhit",cx:x,cy:y-3,r:30,fill:"rgba(0,0,0,0)"});
hit.dataset.k=k; hit.addEventListener("click",pick);
const dot=el("circle",{class:"mdot",cx:x,cy:y,r:4.6,style:"animation-delay:"+(i*50)+"ms"});
dot.dataset.k=k; dot.addEventListener("click",pick);
const tx=el("text",{class:"mdot-label",x:x,y:y-7,"text-anchor":"middle",style:"animation-delay:"+(i*50)+"ms"});
tx.textContent=cityName(k)+" ·"+cnt;
tx.dataset.k=k; tx.addEventListener("click",pick);
dyn.appendChild(hit);dyn.appendChild(dot);dyn.appendChild(tx);
});
scaleOverlay();
const bk=document.getElementById("mapBack");
bk.textContent=BACKTXT[LANG]||BACKTXT.ko;bk.classList.add("show");
}
function zoomOutMap(){
zoomed=false;activeProv=null;
const svg=document.getElementById("mapsvg");
[...svg.querySelectorAll(".prov")].forEach(pp=>pp.classList.remove("active","dim"));
document.getElementById("mapMuni").innerHTML="";
document.getElementById("mapDyn").innerHTML="";
document.getElementById("mapBack").classList.remove("show");
animVB(0,0,MAPDATA.vbW,MAPDATA.vbH,700);
const panel=document.getElementById("mapPanel");
panel.innerHTML=`${esc(t('map.panel0.t'))}
${esc(t('map.panel0.b'))}
`;
}
function selectCity(k){
const list=BOTTLES.filter(b=>b.region===k);
const panel=document.getElementById("mapPanel");
panel.innerHTML=`${esc(regName(k))} · ${list.length}${esc(t('map.count'))} ${esc(t('map.here'))}
`;
document.querySelectorAll(".mdot").forEach(d=>d.classList.toggle("sel", d.dataset.k===k));
// 아래 목록으로 부드럽게 이동
const y=panel.getBoundingClientRect().top+window.scrollY-navH()-12;
window.scrollTo({top:Math.max(0,y),behavior:"smooth"});
}
/* 공정 단계 버튼 → 그림 펼치기 (한 번에 하나) */
document.querySelectorAll(".stepb").forEach(b=>b.addEventListener("click",()=>{
const st=b.closest(".step"), was=st.classList.contains("open");
document.querySelectorAll(".step.open").forEach(o=>{if(o!==st)o.classList.remove("open");});
st.classList.toggle("open",!was);
if(!was){
const im=st.querySelector("img");
if(im&&!im.src&&im.dataset.src)im.src=im.dataset.src;
setTimeout(()=>{const r=st.getBoundingClientRect();
if(r.topim.addEventListener("click",()=>{
lbImg.src=im.src||im.dataset.src; lb.classList.add("on");}));
lb.addEventListener("click",closeLb);
document.addEventListener("keydown",e=>{if(e.key==="Escape")closeLb();});
}
buildMap();
document.getElementById("mapBack").addEventListener("click",e=>{e.stopPropagation();zoomOutMap();});
function selectRegion(k){ // 도감/칵테일에서 지도로 올 때: 해당 도 활성 + 도시 선택
const code=PROV_OF[k]; if(code) activateProv(code);
selectCity(k);
document.getElementById("mapPanel").scrollIntoView({behavior:"smooth",block:"nearest"});
}
/* ===== 한 페이지 스크롤 + 카테고리 바로가기 ===== */
const secs=[...document.querySelectorAll("section[data-p]")];
const navb=[...document.querySelectorAll(".nav-b")];
function navH(){const n=document.querySelector("nav");return n?n.offsetHeight:0;}
function jumpTo(p){
const s=document.querySelector('section[data-p="'+p+'"]');if(!s)return;
const y=s.getBoundingClientRect().top+window.scrollY-navH()-6;
window.scrollTo({top:Math.max(0,y),behavior:"smooth"});
}
function show(p){jumpTo(p);} // 기존 호출 호환
navb.forEach(b=>b.onclick=()=>jumpTo(b.dataset.t));
const navin=document.getElementById("nav"), navwrap=document.getElementById("navwrap");
function navFade(){ if(!navin||!navwrap)return;
const over=navin.scrollWidth-navin.clientWidth;
navwrap.classList.toggle("more", over>2 && navin.scrollLeftnr.right-14) navin.scrollLeft+=(br.right-nr.right+14);
}
let curNav=null;
function spyNav(){
const line=navH()+70;let cur=secs[0];
for(const s of secs){if(s.getBoundingClientRect().top<=line)cur=s;}
navb.forEach(b=>b.classList.toggle("on",b.dataset.t===cur.dataset.p));
if(curNav!==cur.dataset.p){curNav=cur.dataset.p;navReveal(navb.find(b=>b.dataset.t===curNav));}
navFade();
}
window.addEventListener("scroll",spyNav,{passive:true});
window.addEventListener("resize",()=>{navFade();},{passive:true});
if(navin)navin.addEventListener("scroll",navFade,{passive:true});
function gotoMap(region){jumpTo("map");setTimeout(()=>selectRegion(region),450);}
function gotoBottle(id){
if(!byId[id])return;
if(soolFilter!=="all"){soolFilter="all";renderSoolChips();renderSool();applyReveal();}
setTimeout(()=>{const e=document.getElementById("b-"+id);if(!e)return;
e.classList.add("in","open");
const y=e.getBoundingClientRect().top+window.scrollY-navH()-40;
window.scrollTo({top:Math.max(0,y),behavior:"smooth"});
e.animate([{background:"rgba(164,133,79,.28)"},{background:"transparent"}],{duration:1500});},60);
}
function gotoCat(k){soolFilter=k;renderSoolChips();renderSool();applyReveal();jumpTo("sool");}
/* ===== 귀뚜라미 사운드 (랜덤 크로스페이드 루프) ===== */
const CRICKET=["cricket1.mp3","cricket2.mp3","cricket3.mp3","cricket4.mp3"];
const VOL=0.3;
let audioOn=false, muted=false, lastIdx=-1;
const vA=new Audio(), vB=new Audio();
[vA,vB].forEach(a=>{a.preload="auto";a.volume=0;});
let cur=vA, nxt=vB;
function pickSrc(){let i;do{i=Math.floor(Math.random()*CRICKET.length);}while(i===lastIdx&&CRICKET.length>1);lastIdx=i;return CRICKET[i];}
function fadeTo(a,target,ms,done){const start=a.volume,t0=performance.now();
function step(t){const k=Math.min(1,(t-t0)/ms);a.volume=Math.max(0,Math.min(1,start+(target-start)*k));if(k<1)requestAnimationFrame(step);else if(done)done();}
requestAnimationFrame(step);}
let swapping=false;
function crossfade(){if(swapping||!audioOn)return;swapping=true;
nxt.src=pickSrc();nxt.volume=0;nxt.currentTime=0;nxt.play().catch(()=>{});
fadeTo(nxt,muted?0:VOL,650);
fadeTo(cur,0,650,()=>{try{cur.pause();}catch(_){}});
cur.ontimeupdate=null;
const tmp=cur;cur=nxt;nxt=tmp;
cur.ontimeupdate=onTU;
setTimeout(()=>{swapping=false;},680);}
function onTU(e){const a=e.target;if(a!==cur||swapping)return;
const ov=Math.min(0.45,(a.duration||1.2)*0.4);
if(a.duration && a.currentTime>=a.duration-ov) crossfade();}
function startCricket(){if(audioOn)return;audioOn=true;
cur.src=pickSrc();cur.volume=0;cur.ontimeupdate=onTU;
cur.play().then(()=>fadeTo(cur,muted?0:VOL,900)).catch(()=>{});
soundToggle.classList.add("show");}
// 안전장치: 혹시 둘 다 멈추면 즉시 재시작 (연속 재생 보장)
setInterval(()=>{if(audioOn&&!muted&&cur.paused&&nxt.paused){swapping=false;cur.src=pickSrc();cur.volume=0;cur.ontimeupdate=onTU;cur.play().then(()=>fadeTo(cur,VOL,400)).catch(()=>{});}},2500);
[vA,vB].forEach(a=>a.addEventListener("ended",()=>{if(audioOn&&!swapping&&a===cur)crossfade();}));
const soundToggle=document.getElementById("soundToggle");
soundToggle.onclick=()=>{muted=!muted;soundToggle.textContent=muted?"🔇":"🔊";
if(muted){[vA,vB].forEach(a=>fadeTo(a,0,300));}else{if(!audioOn)startCricket();else fadeTo(cur,VOL,300);}};
/* ===== 웰컴 스플래시 입장 ===== */
const splash=document.getElementById("splash");
function enter(){splash.classList.add("gone");startCricket();document.getElementById("langToggle").classList.add("show");setTimeout(()=>{try{splash.remove();}catch(_){}} ,1000);}
document.getElementById("enterBtn").addEventListener("click",e=>{e.stopPropagation();enter();});
splash.addEventListener("click",enter);
/* ===== 스크롤 리빌 애니메이션 ===== */
const REVEAL_SEL=[".cover .philo",".sec-h",".step",".hownote",".unit",".item-c",".b-c",".catblock",".catlabel",".flight",".gcard",".about-block",".mapwrap",".maphint",".mappanel",".primer",".chips"];
const io=new IntersectionObserver(es=>es.forEach(e=>{if(e.isIntersecting){e.target.classList.add("in");io.unobserve(e.target);}}),{threshold:0.05,rootMargin:"0px 0px -30px 0px"});
function applyReveal(){
if(!("IntersectionObserver" in window)){document.querySelectorAll(".reveal").forEach(e=>e.classList.add("in"));return;}
REVEAL_SEL.forEach(sel=>document.querySelectorAll(sel).forEach(e=>{
if(e.classList.contains("in")||e.dataset.rv)return; // 이미 보였거나 이미 등록됨
e.dataset.rv="1";
e.classList.add("reveal");
const r=e.getBoundingClientRect();
if(r.top0)e.classList.add("in");else io.observe(e);
}));
}
applyReveal();
/* ===== 스크롤 낮 → 밤 ===== */
// 배경: 낮 → 파스텔 살구 → 노을 주황 → 짙은 갈색 → 어둠 (스크롤 내내 서서히)
const BG_STOPS=[
{p:0.00,c:{paper:"#e9e2d3",paper2:"#f0e9db",sage:"#d5ddc4",sage2:"#c7d1b3",line:"#38291a29"}},
{p:0.22,c:{paper:"#f3e0c6",paper2:"#f9ecd9",sage:"#dcdcba",sage2:"#cdcda8",line:"#42301c2b"}},
{p:0.42,c:{paper:"#f5cfa4",paper2:"#fbdcb8",sage:"#ddcda3",sage2:"#ccbb92",line:"#4a2f1a33"}},
{p:0.60,c:{paper:"#e8a874",paper2:"#f0b986",sage:"#d3b98d",sage2:"#c2a77c",line:"#4a2a1238"}},
{p:0.70,c:{paper:"#a45d2c",paper2:"#b56d36",sage:"#98784c",sage2:"#886940",line:"#ffe9d033"}},
{p:0.82,c:{paper:"#3f2413",paper2:"#4e2e19",sage:"#4a3a22",sage2:"#5b482d",line:"#ffe9d02e"}},
{p:1.00,c:{paper:"#080709",paper2:"#141118",sage:"#1e2a20",sage2:"#2c3a2e",line:"#e9e1d124"}}
];
// 밤하늘 별: 0.78 부터 서서히 나타남
const STAR_IN=0.72;
// 글자: 밝은 배경용 / 어두운 배경용 두 벌만 두고 한 지점에서 0.55초로 부드럽게 반전
const TEXT_DAY ={ink:"#2b1a0a",ink2:"#4a3319",mut:"#5e401f",gold:"#7d4a15"};
const TEXT_NIGHT={ink:"#f6ecdc",ink2:"#dfd0b4",mut:"#bda684",gold:"#e8be74"};
/* 글자 반전 지점은 스크롤 위치가 아니라 "그 순간 배경의 밝기"로 자동 결정한다.
섹션을 옮기거나 새 섹션을 넣어도 항상 배경 반대색 글자가 나온다. */
function srgbL(v){v/=255;return v<=0.03928?v/12.92:Math.pow((v+0.055)/1.055,2.4);}
function lumOf(css){const m=(css||"").match(/[\d.]+/g);if(!m||m.length<3)return 1;
return 0.2126*srgbL(+m[0])+0.7152*srgbL(+m[1])+0.0722*srgbL(+m[2]);}
const L_DARK=0.155, L_LIGHT=0.24;
function hx(h){h=h.replace("#","");if(h.length===6)h+="ff";
return [parseInt(h.slice(0,2),16),parseInt(h.slice(2,4),16),parseInt(h.slice(4,6),16),parseInt(h.slice(6,8),16)/255];}
function mixc(a,b,k){const A=hx(a),B=hx(b);
return "rgba("+Math.round(A[0]+(B[0]-A[0])*k)+","+Math.round(A[1]+(B[1]-A[1])*k)+","+Math.round(A[2]+(B[2]-A[2])*k)+","+(A[3]+(B[3]-A[3])*k).toFixed(3)+")";}
let nightK=-9, isNight=null, curPaper="#e9e2d3";
function updateDayNight(){
const max=Math.max(1,document.documentElement.scrollHeight-window.innerHeight);
const p=Math.min(1,Math.max(0,window.scrollY/max));
const s=document.documentElement.style;
// 배경: 구간별 보간으로 계속 서서히 변함
if(Math.abs(p-nightK)>=0.002){
nightK=p;
let i=0; while(iBG_STOPS[i+1].p) i++;
const a=BG_STOPS[i], b=BG_STOPS[i+1];
const k=Math.min(1,Math.max(0,(p-a.p)/(b.p-a.p)));
for(const key in a.c) s.setProperty("--"+key, mixc(a.c[key], b.c[key], k));
curPaper=mixc(a.c.paper, b.c.paper, k);
const stars=document.getElementById("stars");
if(stars){const o=Math.min(1,Math.max(0,(p-STAR_IN)/(1-STAR_IN)));
stars.style.opacity=o.toFixed(3); stars.style.visibility=o>0.01?"visible":"hidden";}
// 해는 위에서 천천히 지고, 달은 아래에서 떠오른다
const sun=document.getElementById("sun"), moon=document.getElementById("moon");
const sm=(v,a,b)=>Math.min(1,Math.max(0,(v-a)/(b-a)));
if(sun){ sun.style.top=(6+p*118).toFixed(1)+"vh";
sun.style.opacity=(1-sm(p,0.26,0.52)).toFixed(3); }
if(moon){ moon.style.top=(128-sm(p,0.46,1)*111).toFixed(1)+"vh";
moon.style.opacity=sm(p,0.50,0.74).toFixed(3); }
}
// 글자: 배경 밝기를 재서 자동 반전 (히스테리시스로 경계에서 깜빡이지 않게)
const L=lumOf(curPaper);
const want = isNight ? (L{e.innerHTML=t(e.dataset.i18n);});
navb.forEach(b=>{b.textContent=t("nav."+b.dataset.t);});
setTimeout(navFade,0);
renderCocktails();renderFoods();renderSoolChips();renderSool();
if(activeProv){const a=activeProv;activeProv=null;activateProv(a);}
else{const panel=document.getElementById("mapPanel");
panel.innerHTML=`${esc(t('map.panel0.t'))}
${esc(t('map.panel0.b'))}
`;}
document.querySelectorAll(".langbtn").forEach(x=>x.classList.toggle("on",x.dataset.l===LANG));
const bk=document.getElementById("mapBack"); if(bk)bk.textContent=BACKTXT[LANG]||BACKTXT.ko;
applyReveal(); nightK=-1; updateDayNight();
}
function setLang(l){LANG=l;applyLang();}
document.querySelectorAll(".langbtn").forEach(b=>b.addEventListener("click",e=>{e.stopPropagation();setLang(b.dataset.l);document.getElementById("langPop").classList.remove("show");}));
const langPop=document.getElementById("langPop");
document.getElementById("langToggle").onclick=e=>{e.stopPropagation();langPop.classList.toggle("show");};
document.addEventListener("click",()=>langPop.classList.remove("show"));
applyLang();