/* HBMIC main v6 for Cafe24 builder: load after #hbMain, Anime.js loaded in
*/
document.getElementById('hbMain').classList.add('js', matchMedia('(prefers-reduced-motion: reduce)').matches ? 'rm' : 'm');
(function () {
'use strict';
var root = document.getElementById('hbMain');
if (!root) return;
var RM = root.classList.contains('rm');
var A = window.anime;
if (!A) { root.classList.remove('js'); root.classList.add('rm'); RM = true; }
/* ================= language (same rules as hbmic-translation-client.js) ================= */
var LANGS = ['ko', 'en', 'zh-CN', 'ja', 'vi', 'id'];
var SHORT = { 'ko': 'KO', 'en': 'EN', 'zh-CN': 'ZH', 'ja': 'JA', 'vi': 'VI', 'id': 'ID' };
function normLang(v) {
v = String(v || '').toLowerCase().replace('_', '-');
if (v === 'zh' || v === 'zh-cn') return 'zh-CN';
for (var i = 0; i < LANGS.length; i++) if (LANGS[i].toLowerCase() === v || LANGS[i].toLowerCase() === v.split('-')[0]) return LANGS[i];
return '';
}
function pageLang() {
try { var u = normLang(new URL(location.href).searchParams.get('lang')); if (u) return u; } catch (e) {}
var gm = document.cookie.match(/(?:^|;\s*)googtrans=[^;]*/g), m = gm ? [0, gm[gm.length - 1].replace(/^;?\s*googtrans=/, '')] : null; // last cookie wins, same as hbmic-translation-client.js
if (m) { var c = normLang(decodeURIComponent(m[1]).split('/')[2]); if (c) return c; }
// first visit: same guess as the client (browser's first preferred locale)
var f = String((navigator.languages && navigator.languages[0]) || navigator.language || '').replace('_', '-').toLowerCase().split('-');
var reg = f.length > 1 ? f[f.length - 1].toUpperCase() : '';
if (reg === 'KR' || f[0] === 'ko') return 'ko';
if (reg === 'CN') return 'zh-CN';
if (reg === 'JP' || f[0] === 'ja') return 'ja';
if (reg === 'VN' || f[0] === 'vi') return 'vi';
if (reg === 'ID' || f[0] === 'id') return 'id';
return 'en';
}
var LANG = pageLang();
function initLang() {
var box = root.querySelector('.hb-lang');
if (!box) return;
var btn = box.querySelector('.hb-lang__btn'), list = box.querySelector('.hb-lang__list'), cur = box.querySelector('.hb-lang__cur');
function mark(l) {
cur.textContent = SHORT[l] || 'KO';
root.querySelectorAll('.gtranslate_wrapper a[data-gt-lang]').forEach(function (a) {
var on = normLang(a.getAttribute('data-gt-lang')) === l;
a.classList.toggle('gt-current-lang', on);
if (on) a.setAttribute('aria-current', 'true'); else a.removeAttribute('aria-current');
});
}
function show(v) { list.hidden = !v; btn.setAttribute('aria-expanded', v ? 'true' : 'false'); }
btn.addEventListener('click', function () { show(list.hidden); if (!list.hidden) { var a = list.querySelector('.gt-current-lang') || list.querySelector('a'); a.focus({ preventScroll: true }); } });
// registered before the translation client (it loads with defer), so this runs first
window.addEventListener('click', function (e) {
var a = e.target && e.target.closest ? e.target.closest('.gtranslate_wrapper a[data-gt-lang]') : null;
if (a) { e.preventDefault(); LANG = normLang(a.getAttribute('data-gt-lang')) || 'ko'; mark(LANG); show(false); return; }
if (!box.contains(e.target)) show(false);
}, true);
box.addEventListener('keydown', function (e) { if (e.key === 'Escape' && !list.hidden) { show(false); btn.focus(); } });
mark(LANG); show(false);
}
initLang();
/* ================= background: temporary pastel / video + WebGL ripple ================= */
var Bg = (function () {
var host = root.querySelector('.hb-bg');
var glc = host.querySelector('.hb-bg__gl');
var video = host.querySelector('.hb-bg__video');
var src = document.createElement('canvas');
src.className = 'hb-bg__src'; src.setAttribute('aria-hidden', 'true');
host.insertBefore(src, glc);
var ctx = src.getContext('2d');
var mobile = matchMedia('(max-width: 767px)').matches;
var useVideo = false;
var url = (mobile ? host.dataset.videoMobile : host.dataset.videoPc) || '';
if (url) {
video.src = url;
video.addEventListener('playing', function () { useVideo = true; host.classList.add('has-video'); });
if (!RM) video.play().catch(function () {});
}
// pastel: lavender, sky, light pink, mint (temporary)
var BLOBS = [
{ c: '205,192,247', x: .62, y: .30, r: .62, sx: .11, sy: .08, p: 41 },
{ c: '178,220,248', x: .86, y: .70, r: .70, sx: .09, sy: .10, p: 53 },
{ c: '250,205,224', x: .74, y: .92, r: .55, sx: .12, sy: .07, p: 37 },
{ c: '190,238,216', x: .95, y: .18, r: .58, sx: .08, sy: .11, p: 47 },
{ c: '214,200,250', x: .48, y: .80, r: .50, sx: .10, sy: .09, p: 59 }
];
function draw2D(t) {
var w = src.width, h = src.height, m = Math.max(w, h);
ctx.fillStyle = '#F4F2FB'; ctx.fillRect(0, 0, w, h);
for (var i = 0; i < BLOBS.length; i++) {
var b = BLOBS[i], k = t / b.p * Math.PI * 2;
var x = (b.x + Math.sin(k) * b.sx) * w, y = (b.y + Math.cos(k * .8) * b.sy) * h, r = b.r * m;
var g = ctx.createRadialGradient(x, y, 0, x, y, r);
g.addColorStop(0, 'rgba(' + b.c + ',1)'); g.addColorStop(.55, 'rgba(' + b.c + ',.45)'); g.addColorStop(1, 'rgba(' + b.c + ',0)');
ctx.fillStyle = g; ctx.fillRect(0, 0, w, h);
}
// keep the left 40-45% bright (wider on mobile because text spreads wider)
var wash = ctx.createLinearGradient(0, 0, w, 0);
if (mobile) { wash.addColorStop(0, 'rgba(255,255,255,.9)'); wash.addColorStop(.6, 'rgba(255,255,255,.62)'); wash.addColorStop(1, 'rgba(255,255,255,.15)'); }
else { wash.addColorStop(0, 'rgba(255,255,255,.96)'); wash.addColorStop(.36, 'rgba(255,255,255,.9)'); wash.addColorStop(.6, 'rgba(255,255,255,0)'); }
ctx.fillStyle = wash; ctx.fillRect(0, 0, w, h);
}
// ---- WebGL ----
var gl = null, prog, tex, U = {}, N = 32;
var pts = new Float32Array(N * 4), ptI = 0;
var mouse = { x: -9999, y: -9999, amt: 0, target: 0, last: 0 };
var VS = 'attribute vec2 p;varying vec2 v;void main(){v=p*.5+.5;gl_Position=vec4(p,0.,1.);}';
var FS = [
'precision highp float;',
'uniform sampler2D u_tex;uniform vec2 u_res;uniform float u_time;uniform vec4 u_pts[32];uniform vec3 u_mouse;uniform vec2 u_scale;uniform vec2 u_off;',
'varying vec2 v;',
'void main(){',
' vec2 px=v*u_res; vec2 disp=vec2(0.); float shade=0.;',
' for(int i=0;i<32;i++){',
' vec4 q=u_pts[i]; float age=u_time-q.z;',
' if(q.w<=0.||age<0.||age>2.8) continue;',
' vec2 d=px-q.xy; float dist=length(d)+.001;',
' float r=age*240.; float band=exp(-pow((dist-r)/80.,2.));',
' float amp=q.w*exp(-age*1.5)*smoothstep(0.,.18,age);',
' float w=sin((dist-r)*.05)*band*amp;',
' disp+=d/dist*w; shade+=w;',
' }',
' vec2 dm=px-u_mouse.xy; float g=exp(-dot(dm,dm)/(2.*160.*160.))*u_mouse.z;',
' disp+=-dm/160.*g*.55+vec2(sin(px.y*.03+u_time*1.6),cos(px.x*.03+u_time*1.3))*g*.45;',
' vec2 off=disp*15./u_res;',
' vec2 t=u_off+(v+off)*u_scale; vec2 ca=off*.5*u_scale;',
' vec3 col=vec3(texture2D(u_tex,t+ca).r,texture2D(u_tex,t).g,texture2D(u_tex,t-ca).b);',
' col+=shade*.055+g*.025;',
' gl_FragColor=vec4(clamp(col,0.,1.),1.);',
'}'
].join('\n');
function sh(type, s) { var o = gl.createShader(type); gl.shaderSource(o, s); gl.compileShader(o); if (!gl.getShaderParameter(o, gl.COMPILE_STATUS)) throw new Error(gl.getShaderInfoLog(o)); return o; }
try {
gl = glc.getContext('webgl', { alpha: false, antialias: false, premultipliedAlpha: false, preserveDrawingBuffer: false });
if (!gl) throw new Error('no webgl');
prog = gl.createProgram();
gl.attachShader(prog, sh(gl.VERTEX_SHADER, VS)); gl.attachShader(prog, sh(gl.FRAGMENT_SHADER, FS));
gl.linkProgram(prog); if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) throw new Error('link');
gl.useProgram(prog);
var buf = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
var loc = gl.getAttribLocation(prog, 'p'); gl.enableVertexAttribArray(loc); gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
['u_tex', 'u_res', 'u_time', 'u_pts', 'u_mouse', 'u_scale', 'u_off'].forEach(function (n) { U[n] = gl.getUniformLocation(prog, n); });
tex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.uniform1i(U.u_tex, 0);
} catch (e) { gl = null; host.classList.add('no-gl'); }
var dpr = 1, cw = 1, ch = 1, lastVT = -2, isIdle = false;
function resize() {
var r = host.getBoundingClientRect();
cw = Math.max(1, r.width); ch = Math.max(1, r.height);
dpr = Math.min(window.devicePixelRatio || 1, 1.5);
glc.width = Math.round(cw * dpr); glc.height = Math.round(ch * dpr);
src.width = 420; src.height = Math.max(1, Math.round(420 * ch / cw)); // blurred background, low resolution is enough
if (gl) gl.viewport(0, 0, glc.width, glc.height);
}
function source() { return useVideo && video.readyState >= 2 ? video : src; }
function fit(s) {
var sw = s.videoWidth || s.width, shh = s.videoHeight || s.height, sa = sw / shh, ca = cw / ch;
return sa > ca ? [ca / sa, 1, (1 - ca / sa) / 2, 0] : [1, sa / ca, 0, (1 - sa / ca) / 2];
}
function render(now) {
var t = now / 1000;
if (!useVideo) draw2D(RM ? 0 : t);
if (!gl) return;
var s = source();
// 11/11 13:20 speed: upload a video frame only when it changed (video 24-30fps, screen 60-144Hz); skip drawing when nothing moves
var vid = s === video;
// 11/11 13:30 speed: mouse still for 3.2s (no ripple left) -> show the real