`;
function setup(section) {
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
const row = section.querySelector('.hf-cats__row');
const box = section.querySelector('.hf-cats__cards');
if (!row || !box) return;
section.classList.add('is-live');
const stage = section.querySelector('.hf-cats__stage');
const ask = section.querySelector('.hf-cats__ask');
const hud = section.querySelector('.hf-cats__hud');
const bar = section.querySelector('.hf-cats__bar i');
const hudNow = section.querySelector('[data-now]');
const hudName = section.querySelector('[data-name]');
const items = [...row.children];
const cards = items.map((li) => li.querySelector('.hf-cats__card'));
const names = cards.map((c) => c.querySelector('.hf-cats__en').textContent.trim());
const rtl = getComputedStyle(row).direction === 'rtl';
// كل قيمة بتتكتب بس لو اتغيرت
const written = new WeakMap();
const put = (el, prop, value) => {
let mem = written.get(el);
if (!mem) written.set(el, (mem = {}));
if (mem[prop] === value) return;
mem[prop] = value;
el.style[prop] = value;
};
const flag = (el, name, on) => el.classList.toggle(name, on);
let vh = stage.clientHeight;
let total = 0;
let max = 0;
let top = 0;
let target = 0;
let current = 0;
let pos = 0;
let posTarget = 0;
let last = 0;
let running = false;
let active = -1;
let cardsOn = false;
let hovering = false;
let holdUntil = 0;
let autoTimer = 0;
let touch = null;
let drag = null;
let dragged = false;
let forced = 0; // الظهور اللي كمّله السحب، فوق حساب السكرول
let forcing = false;
let lastC = 0;
const stops = () => Math.max(1, cards.length - 1);
const clampPos = (v) => Math.max(0, Math.min(max, v));
const snap = (v) => {
if (!max) return 0;
const step = max / stops();
return clampPos(Math.round(v / step) * step);
};
// RTL: الكارت الجاي على الشمال، فالصباع رايح يمين = قدام
const dPos = (dx) => dx * (rtl ? 1 : -1);
const hold = () => {
holdUntil = performance.now() + HOLD_MS;
};
const scheduleAuto = () => {
clearTimeout(autoTimer);
if (!cardsOn || !max) return;
autoTimer = setTimeout(() => {
if (cardsOn && !hovering && !touch && !drag && !document.hidden && performance.now() >= holdUntil) {
const step = max / stops();
const next = Math.round(posTarget / step) + 1;
posTarget = next > stops() ? 0 : clampPos(next * step);
kick();
}
scheduleAuto();
}, AUTO_MS);
};
const measure = () => {
vh = stage.clientHeight;
total = vh + vh * (C - LEAD + X + H);
section.style.height = `${total}px`;
max = Math.max(0, row.scrollWidth - document.documentElement.clientWidth);
pos = clampPos(pos);
posTarget = clampPos(posTarget);
top = section.getBoundingClientRect().top + window.scrollY;
target = window.scrollY - top;
if (!running) current = target;
apply();
};
const apply = () => {
if (current < -vh) {
forced = 0;
forcing = false;
}
const c = Math.max(clamp((current + vh * LEAD) / (vh * C)), forced);
lastC = c;
const ce = ease(c);
const h = max > 0 ? clamp(pos / max) : 0;
const shown = ce > 0.6 && current < total - vh * 0.25;
if (shown !== cardsOn) {
cardsOn = shown;
if (shown) scheduleAuto();
else clearTimeout(autoTimer);
}
flag(hud, 'is-on', ce > 0.7);
flag(ask, 'is-on', ce > 0.45);
items.forEach((li, i) => {
const k = clamp(c * 1.6 - i * 0.12);
const f = settle(k);
put(li, 'transform', `translate3d(0,${((1 - f) * 0.8 * vh).toFixed(1)}px,0) rotate(${((1 - f) * -7).toFixed(2)}deg)`);
});
put(row, 'transform', `translate3d(${(rtl ? -(1 - h) * max : -h * max).toFixed(1)}px,0,0)`);
put(bar, 'transform', `scaleX(${h.toFixed(4)})`);
const idx = ce > 0.6 ? Math.round(h * (cards.length - 1)) : -1;
if (idx !== active) {
if (active >= 0) items[active].classList.remove('is-active');
if (idx >= 0) {
items[idx].classList.add('is-active');
hudNow.textContent = String(idx + 1).padStart(2, '0');
hudName.textContent = names[idx];
if (active >= 0 && hudNow.animate) {
hudNow.animate([{ opacity: 0, transform: 'translateY(6px)' }, { opacity: 1, transform: 'none' }], { duration: 380, easing: 'cubic-bezier(.22,1,.36,1)' });
}
}
active = idx;
}
};
const loop = (now) => {
const dt = Math.min(0.05, (now - last) / 1000 || 0.016);
last = now;
const gap = target - current;
const maxLag = vh * 1.2;
if (Math.abs(gap) > maxLag) current = target - Math.sign(gap) * maxLag;
current += (target - current) * (1 - Math.exp(-dt / TAU));
if (Math.abs(target - current) < 0.3) current = target;
if (forcing) {
forced = Math.min(1, forced + dt / FORCE_SEC);
if (forced === 1) forcing = false;
}
if (pos !== posTarget) {
pos += (posTarget - pos) * (1 - Math.exp(-dt / POS_TAU));
if (Math.abs(posTarget - pos) < 0.4) pos = posTarget;
}
apply();
if (current !== target || pos !== posTarget || forcing) requestAnimationFrame(loop);
else running = false;
};
const kick = () => {
if (running) return;
running = true;
last = performance.now();
requestAnimationFrame(loop);
};
let idleTimer = 0;
window.addEventListener('scroll', () => {
target = window.scrollY - top;
flag(section, 'is-scrolling', true);
clearTimeout(idleTimer);
idleTimer = setTimeout(() => flag(section, 'is-scrolling', false), 180);
kick();
}, { passive: true });
let lastW = 0;
window.addEventListener('resize', () => {
if (window.innerWidth === lastW) return; // شريط العنوان في الموبايل بيغيّر الارتفاع بس
lastW = window.innerWidth;
measure();
});
lastW = window.innerWidth;
// السلايدر اللي فوق طوله بيتغير لما صوره تحمّل، فمكان السكشن لازم يتقاس تاني
let queued = 0;
new ResizeObserver(() => {
if (queued) return;
queued = requestAnimationFrame(() => {
queued = 0;
measure();
});
}).observe(document.body);
document.addEventListener('visibilitychange', kick);
// الصور بتتجهز بدري عشان ما تتفكّش في نص الحركة
new IntersectionObserver((entries, io) => {
if (!entries[0].isIntersecting) return;
io.disconnect();
row.querySelectorAll('img').forEach((img) => {
img.loading = 'eager';
if (img.decode) img.decode().catch(() => {});
});
}, { rootMargin: '1200px 0px' }).observe(section);
// لمعة الكارت مع الماوس (مرة في الفريم)
cards.forEach((card) => {
let pending = null;
card.addEventListener('pointermove', (event) => {
if (!pending) {
requestAnimationFrame(() => {
const b = card.getBoundingClientRect();
card.style.setProperty('--gx', `${(pending.clientX - b.left).toFixed(0)}px`);
card.style.setProperty('--gy', `${(pending.clientY - b.top).toFixed(0)}px`);
pending = null;
});
}
pending = event;
});
});
// أي سحب بالعرض بيكمّل ظهور الكروت لو لسه ما خلصش، والكروت بتتسحب معاه في نفس اللحظة
const finishReveal = () => {
if (lastC >= 1 || forcing) return;
forced = lastC;
forcing = true;
kick();
};
// السحب: لما يسيب بيكمّل بسرعته شوية ويقف على أقرب كارت
const moveTo = (value) => {
pos = posTarget = clampPos(value);
kick();
};
const fling = (samples) => {
const a = samples[0];
const b = samples[samples.length - 1];
const v = dPos(((b[1] - a[1]) / Math.max(16, b[0] - a[0])) * 16.7);
posTarget = snap(pos + v * 14);
hold();
kick();
};
box.addEventListener('pointerenter', (e) => {
if (e.pointerType === 'mouse') hovering = true;
});
box.addEventListener('pointerleave', (e) => {
if (e.pointerType === 'mouse') hovering = false;
});
stage.addEventListener('touchstart', (e) => {
const p = e.touches[0];
touch = { x: p.clientX, y: p.clientY, last: p.clientX, axis: null, samples: [[e.timeStamp, p.clientX]] };
hold();
}, { passive: true });
stage.addEventListener('touchmove', (e) => {
if (!touch || e.touches.length > 1) return;
const p = e.touches[0];
if (!touch.axis) {
const dx = p.clientX - touch.x;
const dy = p.clientY - touch.y;
if (Math.abs(dx) < 8 && Math.abs(dy) < 8) return;
touch.axis = Math.abs(dx) > Math.abs(dy) * 1.2 ? 'x' : 'y';
touch.last = p.clientX;
}
if (touch.axis !== 'x') return;
e.preventDefault();
finishReveal();
const step = p.clientX - touch.last;
touch.last = p.clientX;
touch.samples.push([e.timeStamp, p.clientX]);
if (touch.samples.length > 6) touch.samples.shift();
moveTo(pos + dPos(step));
}, { passive: false });
const endTouch = () => {
const done = touch;
touch = null;
if (done && done.axis === 'x') fling(done.samples);
};
stage.addEventListener('touchend', endTouch, { passive: true });
stage.addEventListener('touchcancel', endTouch, { passive: true });
// التاتش باد بالعرض. العجلة العادية رأسي: الصفحة بتنزل عادي
let wheelSnap = 0;
stage.addEventListener('wheel', (e) => {
if (Math.abs(e.deltaX) <= Math.abs(e.deltaY)) return;
e.preventDefault();
finishReveal();
moveTo(pos + dPos(-e.deltaX));
hold();
clearTimeout(wheelSnap);
wheelSnap = setTimeout(() => {
posTarget = snap(pos);
kick();
}, 160);
}, { passive: false });
// السحب بالماوس، والضغطة اللي آخر السحب ما بتفتحش الكارت
stage.addEventListener('pointerdown', (e) => {
if (e.pointerType !== 'mouse' || e.button !== 0) return;
drag = { x: e.clientX, last: e.clientX, id: e.pointerId, moved: false, samples: [[e.timeStamp, e.clientX]] };
});
window.addEventListener('pointermove', (e) => {
if (!drag || e.pointerId !== drag.id) return;
if (!drag.moved) {
if (Math.abs(e.clientX - drag.x) < 6) return;
drag.moved = true;
drag.last = e.clientX;
stage.classList.add('is-dragging');
finishReveal();
}
e.preventDefault();
const step = e.clientX - drag.last;
drag.last = e.clientX;
drag.samples.push([e.timeStamp, e.clientX]);
if (drag.samples.length > 6) drag.samples.shift();
moveTo(pos + dPos(step));
});
const endDrag = () => {
if (!drag) return;
const { moved, samples } = drag;
drag = null;
stage.classList.remove('is-dragging');
if (!moved) return;
dragged = true;
setTimeout(() => {
dragged = false;
}, 0);
fling(samples);
};
window.addEventListener('pointerup', endDrag);
window.addEventListener('pointercancel', endDrag);
box.addEventListener('click', (e) => {
if (!dragged) return;
dragged = false;
e.preventDefault();
e.stopPropagation();
}, true);
box.addEventListener('dragstart', (e) => e.preventDefault());
// الكيبورد: الكارت اللي خد الفوكس الشريط بيروحله
cards.forEach((link, i) => link.addEventListener('focus', () => {
if (!link.matches(':focus-visible')) return;
hold();
posTarget = clampPos((max / stops()) * i);
kick();
}));
measure();
}
// بعد السلايدر في الصفحة الرئيسية بس
function mount() {
if (!document.body.classList.contains('index') || document.querySelector('[data-hf-cats]')) return;
const anchor = document.querySelector('section[component-id="2014055276"]') || document.querySelector('#main-content > section');
if (!anchor) return;
anchor.insertAdjacentHTML('afterend', markup);
setup(anchor.nextElementSibling);
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', mount, { once: true });
else mount();
})();
/* ---------- 7) آراء العملاء بخريطة السعودية 3D (منقول من موقع سمر بنفس الحركة، بألوان الحسين) ----------
يمين: خريطة المملكة مجسمة بـ three.js (بتتحمّل بس لما الزائر يقرب من السكشن)، والـSVG هو الشكل لو WebGL مش شغال.
شمال: عمودين كروت تقييمات، واحد طالع وواحد نازل. على الجوال: الخريطة فوق وصفّين بيتحركوا بالعرض.
التقييمات من صفحات منتجات زد القديمة (كلها 5 نجوم). */
(function () {
'use strict';
var REVIEWS = [
{ q: 'جودة ممتازة، سعر مناسب، مطابق للوصف، تغليف جيد', n: 'يوسف', p: 'بن لقمتي باشنفر 5 كغ' },
{ q: 'افضل سعر واسرع توصيل، شكرا', n: 'عميل الحسين', p: 'بن هرري باشنفر 10 كغ' },
{ q: 'بحثت عنه طويلا والحمدلله حصلته', n: 'إسماعيل', p: 'أقراص سبيرولينا عضوية' },
{ q: 'أسعار مناسبة', n: 'عمر', p: 'بن هرري باشنفر 10 كغ' },
{ q: 'افضل انواع الكاكاو', n: 'إسماعيل', p: 'كاكاو بودرة خام عضوية' },
{ q: 'جودة ممتازة', n: 'عميل الحسين', p: 'بن لقمتي باشنفر 5 كغ' },
{ q: 'ممتاز', n: 'إسماعيل', p: 'ماء زهر البابونج' }
];
var TITLE = 'آراء عملائنـــا';
var THREE_URL = 'https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.min.js';
var MAP_SVG = '';
var KSA_RINGS = [[[0.3258,-0.2734],[0.3146,-0.2751],[0.3038,-0.2767],[0.2916,-0.2785],[0.2769,-0.2806],[0.2654,-0.2823],[0.2486,-0.2848],[0.2336,-0.287],[0.2194,-0.2891],[0.2053,-0.2912],[0.1933,-0.293],[0.1861,-0.295],[0.1777,-0.2995],[0.1648,-0.3064],[0.1516,-0.3135],[0.1448,-0.3171],[0.1376,-0.3265],[0.134,-0.3312],[0.1274,-0.3398],[0.1225,-0.3463],[0.1166,-0.354],[0.114,-0.3609],[0.11,-0.3715],[0.1066,-0.3742],[0.101,-0.3777],[0.0958,-0.3801],[0.0879,-0.3798],[0.0833,-0.3733],[0.0785,-0.3663],[0.0761,-0.3635],[0.0739,-0.3634],[0.0659,-0.3643],[0.0562,-0.3653],[0.0448,-0.3642],[0.0317,-0.3629],[0.0193,-0.3616],[0.0132,-0.3607],[0.0051,-0.3562],[0.0031,-0.3553],[0.0009,-0.3551],[-0.0087,-0.355],[-0.0182,-0.3549],[-0.0277,-0.3563],[-0.0368,-0.3558],[-0.0463,-0.3566],[-0.0496,-0.3583],[-0.0533,-0.3582],[-0.0556,-0.3598],[-0.0576,-0.3605],[-0.06,-0.3592],[-0.063,-0.3595],[-0.0673,-0.3583],[-0.0702,-0.3554],[-0.0728,-0.3528],[-0.0756,-0.3514],[-0.0787,-0.3505],[-0.0814,-0.3505],[-0.0848,-0.3521],[-0.0869,-0.3536],[-0.0922,-0.3587],[-0.0924,-0.3605],[-0.09,-0.3635],[-0.0907,-0.3649],[-0.0938,-0.3667],[-0.0948,-0.3715],[-0.0952,-0.3741],[-0.0957,-0.3804],[-0.0943,-0.3853],[-0.0925,-0.3872],[-0.0924,-0.3893],[-0.0934,-0.3935],[-0.0963,-0.3949],[-0.0984,-0.3989],[-0.0996,-0.4008],[-0.1019,-0.4029],[-0.1108,-0.4101],[-0.1112,-0.4059],[-0.1141,-0.3998],[-0.1143,-0.3954],[-0.1156,-0.3911],[-0.118,-0.3877],[-0.1225,-0.3842],[-0.1229,-0.3795],[-0.1262,-0.3748],[-0.1306,-0.371],[-0.133,-0.364],[-0.1348,-0.3547],[-0.1463,-0.3425],[-0.1607,-0.3313],[-0.1651,-0.3249],[-0.1722,-0.312],[-0.1758,-0.3017],[-0.1855,-0.29],[-0.1859,-0.2855],[-0.1873,-0.2799],[-0.1895,-0.2738],[-0.1909,-0.269],[-0.2005,-0.2477],[-0.2036,-0.2443],[-0.2063,-0.2396],[-0.207,-0.2359],[-0.2078,-0.2339],[-0.2146,-0.2304],[-0.221,-0.2215],[-0.2401,-0.2073],[-0.2494,-0.2059],[-0.2569,-0.2009],[-0.2623,-0.1942],[-0.2681,-0.1828],[-0.2784,-0.1705],[-0.287,-0.153],[-0.2843,-0.1466],[-0.2845,-0.1421],[-0.2872,-0.1345],[-0.2901,-0.1287],[-0.2921,-0.1232],[-0.2905,-0.1153],[-0.2899,-0.1065],[-0.2882,-0.1018],[-0.2869,-0.0966],[-0.2885,-0.0862],[-0.2914,-0.0807],[-0.2911,-0.077],[-0.2944,-0.0751],[-0.2971,-0.0711],[-0.2943,-0.0711],[-0.2993,-0.0656],[-0.3012,-0.0625],[-0.3031,-0.0549],[-0.3055,-0.0491],[-0.3133,-0.0359],[-0.317,-0.0279],[-0.3253,-0.0176],[-0.3344,-0.0099],[-0.3401,-0.0064],[-0.3429,-0.0033],[-0.3476,-0.0032],[-0.3527,0.0014],[-0.3563,0.0015],[-0.3608,0.0023],[-0.3661,0.011],[-0.3705,0.0191],[-0.378,0.0298],[-0.3761,0.0326],[-0.374,0.0371],[-0.375,0.043],[-0.3762,0.047],[-0.3795,0.0543],[-0.3904,0.0725],[-0.3933,0.0752],[-0.3979,0.0783],[-0.4008,0.0862],[-0.4021,0.0932],[-0.4095,0.0967],[-0.4223,0.1222],[-0.4297,0.1311],[-0.4327,0.1371],[-0.4412,0.1469],[-0.4455,0.1567],[-0.4541,0.1658],[-0.4616,0.1815],[-0.4732,0.1972],[-0.478,0.1999],[-0.4899,0.201],[-0.495,0.2021],[-0.4996,0.1987],[-0.5,0.2031],[-0.4968,0.2091],[-0.4922,0.2218],[-0.4913,0.2328],[-0.4841,0.2658],[-0.474,0.2641],[-0.4656,0.2627],[-0.4534,0.2607],[-0.4408,0.2586],[-0.4334,0.2573],[-0.4309,0.2578],[-0.4207,0.2659],[-0.4115,0.2732],[-0.406,0.2821],[-0.4007,0.2907],[-0.3983,0.2925],[-0.3901,0.2941],[-0.3771,0.2967],[-0.3643,0.2992],[-0.3633,0.3001],[-0.3603,0.307],[-0.3565,0.3158],[-0.3557,0.3167],[-0.3548,0.3176],[-0.3456,0.3225],[-0.34,0.3255],[-0.348,0.3343],[-0.3554,0.3426],[-0.3638,0.3519],[-0.3709,0.3592],[-0.3816,0.37],[-0.3886,0.3771],[-0.3764,0.3805],[-0.3632,0.3841],[-0.3498,0.3878],[-0.3338,0.3922],[-0.3212,0.3957],[-0.3025,0.4008],[-0.2933,0.4033],[-0.2916,0.404],[-0.2846,0.4101],[-0.274,0.4084],[-0.258,0.4058],[-0.2426,0.4033],[-0.2264,0.4004],[-0.2212,0.398],[-0.2055,0.3893],[-0.1953,0.3836],[-0.1834,0.377],[-0.1685,0.3687],[-0.1583,0.363],[-0.1453,0.3557],[-0.1351,0.3474],[-0.1222,0.3368],[-0.108,0.3252],[-0.0963,0.3162],[-0.0803,0.3038],[-0.0644,0.2916],[-0.0489,0.2796],[-0.0365,0.2701],[-0.0208,0.2579],[-0.0196,0.2575],[-0.0037,0.2561],[0.0176,0.2542],[0.0391,0.2524],[0.0584,0.2507],[0.0667,0.2524],[0.0759,0.2513],[0.0882,0.2498],[0.0956,0.2488],[0.1096,0.2469],[0.1138,0.239],[0.1153,0.2334],[0.1167,0.228],[0.1209,0.2231],[0.1305,0.2232],[0.1389,0.2233],[0.1494,0.2235],[0.1576,0.2236],[0.1603,0.2187],[0.1614,0.2138],[0.1664,0.2022],[0.1734,0.1932],[0.175,0.1899],[0.1762,0.185],[0.175,0.1831],[0.1745,0.181],[0.1797,0.176],[0.1883,0.1718],[0.1916,0.1708],[0.1954,0.1689],[0.1925,0.1661],[0.1975,0.1594],[0.2034,0.1527],[0.2097,0.1512],[0.2182,0.141],[0.231,0.1344],[0.2388,0.1257],[0.2381,0.1255],[0.2358,0.1264],[0.233,0.1276],[0.2321,0.1265],[0.2322,0.1229],[0.233,0.1186],[0.237,0.1149],[0.2405,0.1123],[0.2419,0.1073],[0.2391,0.0964],[0.2381,0.0965],[0.2363,0.0974],[0.2343,0.0976],[0.2332,0.097],[0.2356,0.0892],[0.2379,0.0832],[0.2407,0.0785],[0.2431,0.0716],[0.2451,0.0686],[0.2533,0.0613],[0.2559,0.0551],[0.2582,0.0437],[0.2634,0.0373],[0.2662,0.0323],[0.27,0.0282],[0.2724,0.0225],[0.2759,0.0181],[0.2776,0.017],[0.2803,0.0165],[0.2837,0.0165],[0.2877,0.0176],[0.292,0.0187],[0.2954,0.0165],[0.2988,0.0168],[0.2992,0.0147],[0.2969,0.0119],[0.294,0.0048],[0.2981,0.0037],[0.3019,0.0031],[0.3047,0.002],[0.3063,0.002],[0.3063,0.0005],[0.3065,-0.0062],[0.3074,-0.0088],[0.3092,-0.0111],[0.3118,-0.0145],[0.3144,-0.0179],[0.317,-0.0213],[0.3197,-0.0247],[0.3223,-0.0281],[0.3249,-0.0316],[0.3275,-0.035],[0.3301,-0.0384],[0.3327,-0.0418],[0.3354,-0.0452],[0.338,-0.0486],[0.3406,-0.052],[0.3432,-0.0554],[0.3458,-0.0588],[0.3484,-0.0623],[0.3511,-0.0657],[0.3532,-0.0685],[0.3572,-0.069],[0.3585,-0.0692],[0.3621,-0.0697],[0.3677,-0.0704],[0.375,-0.0714],[0.3835,-0.0725],[0.3931,-0.0738],[0.4034,-0.0752],[0.414,-0.0766],[0.4245,-0.078],[0.4348,-0.0794],[0.4444,-0.0807],[0.453,-0.0818],[0.4602,-0.0828],[0.4658,-0.0835],[0.4694,-0.084],[0.4707,-0.0842],[0.4745,-0.0847],[0.4752,-0.0846],[0.4784,-0.0804],[0.4818,-0.0863],[0.4847,-0.0912],[0.4887,-0.0979],[0.4929,-0.105],[0.497,-0.1119],[0.5,-0.117],[0.4984,-0.1222],[0.4967,-0.128],[0.4949,-0.1338],[0.4932,-0.1395],[0.4914,-0.1453],[0.4897,-0.151],[0.488,-0.1568],[0.4862,-0.1626],[0.4845,-0.1683],[0.4827,-0.1741],[0.481,-0.1799],[0.4792,-0.1856],[0.4775,-0.1914],[0.4758,-0.1972],[0.474,-0.2029],[0.4723,-0.2087],[0.4705,-0.2144],[0.4684,-0.2214],[0.4634,-0.2232],[0.4552,-0.2262],[0.447,-0.2292],[0.4388,-0.2322],[0.4307,-0.2352],[0.4225,-0.2382],[0.4143,-0.2411],[0.4061,-0.2441],[0.3979,-0.2471],[0.3897,-0.2501],[0.3816,-0.2531],[0.3734,-0.2561],[0.3652,-0.2591],[0.357,-0.262],[0.3488,-0.265],[0.3406,-0.268],[0.3325,-0.271]],[[-0.1494,-0.3922],[-0.1457,-0.3925],[-0.1472,-0.3908],[-0.1476,-0.39],[-0.146,-0.3876],[-0.1407,-0.3925],[-0.1409,-0.3984],[-0.1413,-0.3997],[-0.1427,-0.3985],[-0.1437,-0.3972],[-0.1439,-0.3959],[-0.1454,-0.3945],[-0.1505,-0.3954],[-0.1537,-0.3938],[-0.1582,-0.3889],[-0.1595,-0.3853],[-0.1576,-0.3846],[-0.1556,-0.3829],[-0.1543,-0.3801],[-0.1554,-0.3772],[-0.1527,-0.3777],[-0.1513,-0.3807],[-0.151,-0.3875],[-0.1506,-0.3889],[-0.1513,-0.3904]]];
var KSA_REGIONS = [[[-0.0217,0.0688],[-0.0186,0.0736],[-0.0214,0.091],[-0.0358,0.1113],[-0.035,0.125],[-0.0137,0.1426],[-0.0157,0.1495],[-0.0238,0.1549]],[[-0.0475,0.0697],[-0.0374,0.0684]],[[-0.0998,0.0226],[-0.0949,0.0276],[-0.0962,0.0372],[-0.0871,0.0478],[-0.067,0.0538],[-0.0542,0.0677],[-0.0475,0.0697]],[[-0.0374,0.0684],[-0.026,0.0692]],[[-0.136,0.028],[-0.1159,0.0227]],[[-0.1442,0.0189],[-0.136,0.028]],[[-0.0319,0.1469],[-0.0422,0.1482],[-0.0588,0.1603]],[[-0.0588,0.1603],[-0.0849,0.1478],[-0.0926,0.1371],[-0.1108,0.1277],[-0.1234,0.1178],[-0.1321,0.1053],[-0.1364,0.1042]],[[-0.0238,0.1549],[-0.0319,0.1469]],[[-0.1376,0.1043],[-0.142,0.0986],[-0.143,0.0879]],[[-0.1498,0.0899],[-0.154,0.0856],[-0.152,0.0762],[-0.1769,0.0671]],[[-0.1801,0.2409],[-0.1621,0.2368]],[[-0.2088,0.2349],[-0.1801,0.2409]],[[-0.15,0.2387],[-0.1303,0.2341],[-0.121,0.2247],[-0.1153,0.2227]],[[-0.1621,0.2368],[-0.15,0.2387]],[[-0.1044,0.2265],[-0.1013,0.2255],[-0.0998,0.2178],[-0.0945,0.2151]],[[-0.1153,0.2227],[-0.1044,0.2265]],[[-0.0672,0.217],[-0.0492,0.187],[-0.0287,0.1821],[-0.0157,0.1704]],[[-0.0787,0.2118],[-0.0672,0.217]],[[-0.0898,0.2156],[-0.0787,0.2118]],[[-0.0238,0.1549],[-0.0232,0.1638],[-0.0157,0.1704]],[[-0.3245,0.3454],[-0.3321,0.3479],[-0.3449,0.3636],[-0.3454,0.3709],[-0.3397,0.3908]],[[-0.3033,0.3474],[-0.3245,0.3454]],[[-0.2887,0.3495],[-0.2502,0.3447],[-0.2356,0.3378],[-0.2096,0.3372]],[[-0.3033,0.3474],[-0.2887,0.3495]],[[-0.2021,0.3376],[-0.1879,0.3286],[-0.1711,0.3255],[-0.164,0.3141],[-0.1533,0.3048],[-0.1605,0.2976],[-0.2065,0.2691],[-0.2101,0.2463],[-0.2181,0.2378]],[[-0.2211,0.2385],[-0.2841,0.2111],[-0.2915,0.2041]],[[0.0068,-0.2599],[0.1244,-0.2456]],[[-0.0291,-0.2465],[-0.0099,-0.2579],[0.0068,-0.2599]],[[-0.0066,0.171],[-0.009,0.1755],[-0.0073,0.1818],[0.004,0.1962],[0.0236,0.2308],[0.032,0.239],[0.0618,0.2514]],[[-0.0066,0.171],[-0.0,0.166],[0.0056,0.1553],[0.0268,0.1461],[0.0373,0.1361],[0.0524,0.1338],[0.0716,0.1228]],[[0.0787,0.124],[0.092,0.1125],[0.1101,0.1039],[0.1126,0.0282],[0.1433,0.0011],[0.1503,-0.0129],[0.1508,-0.0309],[0.1244,-0.2456]],[[0.1094,-0.3725],[0.1244,-0.2456]],[[-0.0291,-0.2465],[-0.0486,-0.2281],[-0.0567,-0.2156],[-0.051,-0.192],[-0.0695,-0.1703]],[[-0.1631,-0.2317],[-0.1563,-0.2119],[-0.1475,-0.2042],[-0.1495,-0.1966],[-0.1473,-0.1886]],[[-0.1543,-0.3085],[-0.152,-0.3099],[-0.1527,-0.3205],[-0.1506,-0.323]],[[-0.1474,-0.3225],[-0.1399,-0.3298],[-0.1288,-0.3313],[-0.1179,-0.343]],[[-0.1066,-0.3253],[-0.085,-0.3522]],[[-0.1179,-0.343],[-0.1127,-0.3301],[-0.1066,-0.3253]],[[-0.0291,-0.2465],[-0.0297,-0.256],[-0.0366,-0.2632],[-0.0362,-0.2809],[-0.0498,-0.2881],[-0.0704,-0.3137],[-0.0709,-0.3545]],[[-0.1442,0.0189],[-0.1498,0.0237],[-0.1548,0.0391],[-0.1655,0.0445],[-0.1657,0.0628],[-0.1769,0.0671]],[[-0.1442,0.0189],[-0.1487,0.0082],[-0.1495,-0.0156]],[[-0.2509,0.1088],[-0.2544,0.1112],[-0.2515,0.1197],[-0.2527,0.1254]],[[-0.2407,0.0554],[-0.2464,0.0611],[-0.2485,0.0872],[-0.2458,0.1062],[-0.2486,0.1093]],[[-0.1769,0.0671],[-0.1943,0.0703]],[[-0.1943,0.0703],[-0.2055,0.069],[-0.2132,0.0614],[-0.2187,0.06]],[[-0.2243,0.0602],[-0.2407,0.0554]],[[-0.1251,-0.069],[-0.132,-0.0649],[-0.1437,-0.0305],[-0.1494,-0.0248],[-0.1495,-0.0156]],[[-0.0953,-0.09],[-0.1016,-0.0856],[-0.1016,-0.0723],[-0.1178,-0.0689]],[[-0.0695,-0.1703],[-0.0827,-0.1492],[-0.081,-0.1275],[-0.0771,-0.1193],[-0.0782,-0.0909],[-0.0875,-0.0882]],[[-0.1713,-0.1914],[-0.1806,-0.1815]],[[-0.1806,-0.1815],[-0.1852,-0.185],[-0.1842,-0.1954],[-0.1898,-0.2074],[-0.2004,-0.2111],[-0.2059,-0.2178],[-0.1987,-0.2236],[-0.1973,-0.2441],[-0.1837,-0.2543]],[[-0.1521,-0.1857],[-0.1713,-0.1914]],[[-0.1837,-0.2543],[-0.1792,-0.2515],[-0.1747,-0.2366],[-0.1706,-0.2326]],[[-0.1597,-0.309],[-0.168,-0.319]],[[-0.159,-0.2307],[-0.1552,-0.2347],[-0.1568,-0.2448],[-0.1541,-0.2533],[-0.1561,-0.2596],[-0.16,-0.2618]],[[-0.1772,-0.2638],[-0.1779,-0.2795],[-0.174,-0.2844]],[[-0.1688,-0.2843],[-0.1614,-0.2877],[-0.1579,-0.2995],[-0.1597,-0.309]],[[-0.085,-0.1776],[-0.0695,-0.1703]],[[-0.1378,-0.2032],[-0.1049,-0.1796],[-0.0907,-0.1761]],[[-0.1473,-0.1886],[-0.1378,-0.2032]],[[-0.1557,-0.0146],[-0.1613,-0.0169],[-0.16,-0.027],[-0.1622,-0.0316],[-0.1828,-0.044],[-0.1753,-0.0543],[-0.1856,-0.0601],[-0.2146,-0.0871]],[[-0.2801,-0.0566],[-0.2962,-0.0416]],[[-0.2962,-0.0416],[-0.3084,-0.0431]],[[-0.2359,-0.0915],[-0.2407,-0.0895],[-0.2415,-0.0788],[-0.2494,-0.0743],[-0.2462,-0.0609],[-0.2501,-0.057]],[[-0.2501,-0.057],[-0.2683,-0.0614]],[[-0.223,-0.0847],[-0.2359,-0.0915]],[[-0.2527,0.1254],[-0.2461,0.14],[-0.2361,0.153],[-0.2472,0.1611],[-0.2529,0.1825],[-0.2568,0.1874],[-0.2708,0.1976],[-0.2915,0.2041]],[[-0.4109,0.2245],[-0.4147,0.2257],[-0.4285,0.2425],[-0.4411,0.2466]],[[-0.4411,0.2466],[-0.464,0.2437],[-0.4713,0.2402]],[[-0.4713,0.2402],[-0.4836,0.2418]],[[-0.3235,0.2072],[-0.3359,0.2087],[-0.3465,0.2142],[-0.3499,0.2214],[-0.3501,0.2385],[-0.3525,0.2405]],[[-0.3525,0.2405],[-0.3677,0.2249]],[[-0.3677,0.2249],[-0.3898,0.2289]],[[-0.3898,0.2289],[-0.4109,0.2245]],[[-0.2961,0.2062],[-0.3064,0.2025]],[[-0.3227,0.1323],[-0.3298,0.145],[-0.3419,0.1482],[-0.351,0.1638]],[[-0.351,0.1638],[-0.3629,0.1585]],[[-0.3629,0.1585],[-0.3749,0.1631]],[[-0.3749,0.1631],[-0.396,0.1553],[-0.3951,0.1522]],[[-0.3911,0.1528],[-0.3866,0.1463],[-0.3865,0.1294],[-0.3741,0.1208],[-0.3787,0.1087],[-0.3737,0.0953]],[[-0.2818,0.1262],[-0.2994,0.1344],[-0.3038,0.1395]],[[-0.3141,0.1373],[-0.3227,0.1323]],[[-0.2573,0.1292],[-0.2818,0.1262]],[[-0.3702,0.0972],[-0.3596,0.0914],[-0.3492,0.078],[-0.3449,0.0653],[-0.338,0.0625],[-0.339,0.0325],[-0.3441,0.0278]],[[-0.3496,0.0284],[-0.3603,0.022]]];
var KSA_CITIES = {"riyadh":[0.0758,0.0229],"jeddah":[-0.2823,-0.1438],"madinah":[-0.2623,0.0114],"dammam":[0.2366,0.1131],"abha":[-0.1248,-0.314]}; // الرياض الأول: الأقواس بتطلع منها
var AVATAR = '';
function esc(s) {
return String(s).replace(/[&<>"]/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"' }[c]; });
}
function card(r) {
return '' +
'
★★★★★
' +
'
«' + esc(r.q) + '»
' +
'' + AVATAR + '' + esc(r.n) + '' + esc(r.p) + '' +
'';
}
// كل عمود فيه القايمة مرتين، فالحركة بمقدار قايمة واحدة بتلف من غير قطع.
function column(list, dir) {
var html = list.map(card).join('');
return '
' + html + '
' + html + '
';
}
function build() {
var up = REVIEWS.filter(function (_, i) { return i % 2 === 0; });
var down = REVIEWS.filter(function (_, i) { return i % 2 === 1; });
var el = document.createElement('section');
el.className = 'hfv';
el.setAttribute('aria-labelledby', 'hfv-title');
el.innerHTML =
'
' +
// نفس عنوان أقسام الثيم بالظبط (الخط والمقاس والزخرفة اللي تحته).
'
' +
'
' + TITLE + '
' +
'' +
'
' +
'
' +
'
' + MAP_SVG + '
' +
'
' + column(up, 'up') + column(down, 'down') + '
' +
'
' +
'
';
return el;
}
/* ---- الخريطة 3D: نفس SaudiMap بتاعة سمر، بكانفاس خاص بيها بدل المسرح المشترك ---- */
var DEPTH = 0.055, TOP = DEPTH + 0.011, BASE_TILT = -0.66, BASE_TURN = 0.1, CAM = 1000;
var GOLD = '#E9C77E', LIGHT = '#FFF3D6';
function toCanvas(x, y, size) { return [(x + 0.5) * size, (0.5 - y) * size]; }
function easeOut(t) { return 1 - Math.pow(1 - t, 3); }
function topTexture(T) {
var size = 1536, c = document.createElement('canvas');
c.width = c.height = size;
var ctx = c.getContext('2d');
var g = ctx.createLinearGradient(0, 0, size, size);
g.addColorStop(0, '#2c6b52');
g.addColorStop(0.5, '#1F4D3A');
g.addColorStop(1, '#153628');
ctx.fillStyle = g;
ctx.fillRect(0, 0, size, size);
var p = toCanvas(0.02, 0.02, size);
var glow = ctx.createRadialGradient(p[0], p[1], 0, p[0], p[1], size * 0.45);
glow.addColorStop(0, 'rgba(255, 243, 214, 0.16)');
glow.addColorStop(1, 'rgba(255, 243, 214, 0)');
ctx.fillStyle = glow;
ctx.fillRect(0, 0, size, size);
ctx.fillStyle = 'rgba(233, 199, 126, 0.2)';
var step = size / 64;
for (var y = step / 2; y < size; y += step) {
for (var x = step / 2; x < size; x += step) {
ctx.beginPath();
ctx.arc(x, y, 1.5, 0, Math.PI * 2);
ctx.fill();
}
}
ctx.strokeStyle = 'rgba(233, 199, 126, 0.45)';
ctx.lineWidth = 2.2;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.setLineDash([10, 7]);
KSA_REGIONS.forEach(function (line) {
ctx.beginPath();
line.forEach(function (pt, i) {
var q = toCanvas(pt[0], pt[1], size);
if (i === 0) ctx.moveTo(q[0], q[1]); else ctx.lineTo(q[0], q[1]);
});
ctx.stroke();
});
var t = new T.CanvasTexture(c);
t.colorSpace = T.SRGBColorSpace;
t.offset.set(0.5, 0.5);
t.anisotropy = 8;
return t;
}
function shadowTexture(T) {
var size = 256, c = document.createElement('canvas');
c.width = c.height = size;
var ctx = c.getContext('2d');
var g = ctx.createRadialGradient(size / 2, size / 2, 0, size / 2, size / 2, size / 2);
g.addColorStop(0, 'rgba(18, 38, 29, 0.5)');
g.addColorStop(0.6, 'rgba(18, 38, 29, 0.16)');
g.addColorStop(1, 'rgba(18, 38, 29, 0)');
ctx.fillStyle = g;
ctx.fillRect(0, 0, size, size);
return new T.CanvasTexture(c);
}
function startMap(T, section) {
var box = section.querySelector('.hfv__map');
var canvas = document.createElement('canvas');
canvas.className = 'hfv__gl';
box.appendChild(canvas);
var renderer = new T.WebGLRenderer({ canvas: canvas, antialias: true, alpha: true, powerPreference: 'high-performance' });
renderer.setPixelRatio(Math.min(window.devicePixelRatio || 1, 2));
renderer.outputColorSpace = T.SRGBColorSpace;
var scene = new T.Scene();
var camera = new T.PerspectiveCamera(50, 1, 10, CAM * 4);
camera.position.z = CAM;
var group = new T.Group(), slab = new T.Group();
var caps = new T.MeshStandardMaterial({ map: topTexture(T), roughness: 0.58, metalness: 0.05 });
var sides = new T.MeshStandardMaterial({ color: '#143426', roughness: 0.75, metalness: 0.08 });
var shapes = KSA_RINGS.map(function (ring) {
return new T.Shape(ring.map(function (p) { return new T.Vector2(p[0], p[1]); }));
});
var geometry = new T.ExtrudeGeometry(shapes, { depth: DEPTH, bevelEnabled: true, bevelThickness: 0.011, bevelSize: 0.006, bevelSegments: 3, curveSegments: 1 });
slab.add(new T.Mesh(geometry, [caps, sides]));
var rimMat = new T.LineBasicMaterial({ color: GOLD, transparent: true, opacity: 0.7 });
KSA_RINGS.forEach(function (ring) {
var pts = ring.map(function (p) { return new T.Vector3(p[0], p[1], TOP + 0.001); });
slab.add(new T.LineLoop(new T.BufferGeometry().setFromPoints(pts), rimMat));
});
group.add(slab);
var shadow = new T.Mesh(new T.PlaneGeometry(1.3, 1.15), new T.MeshBasicMaterial({ map: shadowTexture(T), transparent: true, depthWrite: false }));
shadow.position.set(0.02, -0.05, -0.09);
group.add(shadow);
// منارات المدن: راس منوّر على شعاع، وحلقة بتتنفّس حواليه.
var cities = Object.keys(KSA_CITIES).map(function (k) { return KSA_CITIES[k]; });
var beacons = [], arcs = [];
var headGeo = new T.SphereGeometry(0.009, 16, 12);
var headMat = new T.MeshBasicMaterial({ color: LIGHT });
cities.forEach(function (c, i) {
var hub = i === 0, height = hub ? 0.12 : 0.085;
var beam = new T.Mesh(new T.ConeGeometry(hub ? 0.012 : 0.009, height, 20, 1, true), new T.MeshBasicMaterial({ color: GOLD, transparent: true, opacity: 0.38, depthWrite: false }));
beam.rotation.x = Math.PI / 2;
beam.position.set(c[0], c[1], TOP + height / 2);
group.add(beam);
var head = new T.Mesh(headGeo, headMat);
head.scale.setScalar(hub ? 1.35 : 1);
head.position.set(c[0], c[1], TOP + height);
group.add(head);
var ring = new T.Mesh(new T.RingGeometry(0.012, 0.016, 40), new T.MeshBasicMaterial({ color: GOLD, transparent: true, depthWrite: false }));
ring.position.set(c[0], c[1], TOP + 0.002);
group.add(ring);
beacons.push({ head: head, headScale: hub ? 1.35 : 1, ring: ring, beam: beam, phase: i * 0.29 });
});
// أقواس من الرياض، وعلى كل قوس نقطة نور ماشية.
var from = new T.Vector3(cities[0][0], cities[0][1], TOP + 0.12);
cities.slice(1).forEach(function (c, i) {
var to = new T.Vector3(c[0], c[1], TOP + 0.085);
var mid = from.clone().add(to).multiplyScalar(0.5);
mid.z += from.distanceTo(to) * 0.55;
var curve = new T.QuadraticBezierCurve3(from, mid, to);
var count = 64;
var line = new T.Line(new T.BufferGeometry().setFromPoints(curve.getPoints(count - 1)), new T.LineBasicMaterial({ color: GOLD, transparent: true, opacity: 0.55 }));
line.geometry.setDrawRange(0, 0);
group.add(line);
var spark = new T.Mesh(new T.SphereGeometry(0.007, 12, 10), new T.MeshBasicMaterial({ color: LIGHT, transparent: true, blending: T.AdditiveBlending, depthWrite: false }));
group.add(spark);
arcs.push({ line: line, curve: curve, spark: spark, count: count, phase: i * 0.23, speed: 0.22 + (i % 2) * 0.05 });
});
var hemi = new T.HemisphereLight(LIGHT, '#10241b', 1.25);
var sun = new T.DirectionalLight('#ffffff', 1.75);
sun.position.set(-600, 900, 1200);
scene.add(hemi, sun, group);
group.rotation.set(BASE_TILT, 0, BASE_TURN);
// يميل ناحية الماوس وهو فوق السكشن.
var tilt = { x: 0, y: 0, tx: 0, ty: 0 };
section.addEventListener('pointermove', function (e) {
tilt.tx = (e.clientX / window.innerWidth - 0.5) * 0.5;
tilt.ty = (e.clientY / window.innerHeight - 0.5) * 0.3;
});
section.addEventListener('pointerleave', function () { tilt.tx = 0; tilt.ty = 0; });
var boxW = 0;
function resize() {
var w = canvas.clientWidth, h = canvas.clientHeight;
if (!w || !h) return;
renderer.setSize(w, h, false);
camera.aspect = w / h;
camera.fov = 2 * Math.atan(h / 2 / CAM) * (180 / Math.PI); // وحدة = بكسل عند z=0
camera.updateProjectionMatrix();
boxW = box.clientWidth;
}
resize();
if (window.ResizeObserver) new ResizeObserver(resize).observe(box);
else window.addEventListener('resize', resize);
var reveal = 0, seen = false, last = 0, raf = 0, visible = false;
function frame(now) {
raf = 0;
var time = now / 1000, dt = last ? Math.min(0.1, time - last) : 0.016;
last = time;
var rect = box.getBoundingClientRect(), vh = window.innerHeight;
var offset = (rect.top + rect.height / 2 - vh / 2) / vh;
if (!seen && Math.abs(offset) < 0.45) seen = true;
if (seen && reveal < 1) reveal = Math.min(1, reveal + dt / 2.4);
var rise = easeOut(Math.min(1, reveal / 0.55));
var draw = easeOut(Math.max(0, (reveal - 0.35) / 0.65));
var size = boxW * 0.94;
group.scale.setScalar(size);
slab.scale.z = 0.08 + 0.92 * rise;
var ease = 1 - Math.exp(-dt * 3);
tilt.x += (tilt.tx - tilt.x) * ease;
tilt.y += (tilt.ty - tilt.y) * ease;
group.position.set(0, Math.sin(time * 0.9) * size * 0.012, 0);
group.rotation.x = BASE_TILT + tilt.y + Math.sin(time * 0.6) * 0.02;
group.rotation.y = tilt.x;
group.rotation.z = BASE_TURN - offset * 0.18;
beacons.forEach(function (b) {
b.head.scale.setScalar(b.headScale * rise);
var t = (time * 0.55 + b.phase) % 1;
b.ring.scale.setScalar(1 + t * 2.4);
b.ring.material.opacity = 0.85 * (1 - t) * rise;
b.beam.scale.y = rise;
b.beam.material.opacity = (0.3 + Math.sin(time * 2 + b.phase * 6) * 0.08) * rise;
});
arcs.forEach(function (a) {
a.line.geometry.setDrawRange(0, Math.floor(a.count * draw));
var t = (time * a.speed + a.phase) % 1;
a.spark.position.copy(a.curve.getPoint(t));
a.spark.material.opacity = Math.sin(Math.PI * t) * (draw > 0.98 ? 1 : 0);
});
renderer.render(scene, camera);
if (visible) raf = requestAnimationFrame(frame);
}
// الرسم شغال بس والسكشن ظاهر.
new IntersectionObserver(function (entries) {
visible = entries[0].isIntersecting;
if (visible && !raf) { last = 0; raf = requestAnimationFrame(frame); }
}, { rootMargin: '10% 0px' }).observe(section);
section.classList.add('is-live');
}
function hasWebGL2() {
try { return !!document.createElement('canvas').getContext('webgl2'); } catch (e) { return false; }
}
function init() {
if (!document.body.classList.contains('index') || document.querySelector('.hfv')) return;
var blocks = document.querySelectorAll('section.s-block');
var anchor = blocks[blocks.length - 1];
if (!anchor || !anchor.parentNode) return;
var section = build();
anchor.parentNode.insertBefore(section, anchor.nextSibling);
// الأعمدة بتقف وهي برا الشاشة، وكمان لما الماوس فوقها.
var cols = section.querySelector('.hfv__cols');
new IntersectionObserver(function (entries) {
cols.classList.toggle('is-paused', !entries[0].isIntersecting);
}, { rootMargin: '10% 0px' }).observe(cols);
// three.js بيتحمّل لما الزائر يقرب من السكشن بس.
if (!hasWebGL2()) return;
var io = new IntersectionObserver(function (entries) {
if (!entries[0].isIntersecting) return;
io.disconnect();
new Function('u', 'return import(u)')(THREE_URL).then(function (T) {
try { startMap(T, section); } catch (e) { /* الخريطة الـSVG بتفضل ظاهرة */ }
}, function () {});
}, { rootMargin: '600px 0px' });
io.observe(section);
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init, { once: true });
else init();
})();
/* ---------- 9) الأسئلة الشائعة: كارت «ما لقيت جواب سؤالك؟» بزرار واتساب فوق صورة العنصر ---------- */
(function () {
'use strict';
var WA = 'https://wa.me/966502399222?text=' + encodeURIComponent('السلام عليكم، عندي سؤال');
function init() {
document.querySelectorAll('.s-block--common_questions .saji-common-questions__media').forEach(function (media) {
if (media.querySelector('.hfq-cta')) return;
var cta = document.createElement('div');
cta.className = 'hfq-cta';
cta.innerHTML =
'ما لقيت جواب سؤالك؟' +
'راسلنا على الواتساب ونرد عليك' +
'راسلنا واتساب';
media.appendChild(cta);
});
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init, { once: true });
else init();
})();
/* ---------- 10) بنرات الأقسام المدمجة: ظهور ناعم لما البنر يدخل الشاشة ---------- */
(function () {
'use strict';
if (!('IntersectionObserver' in window)) return;
document.documentElement.classList.add('hf-blend-js');
function init() {
var all = document.querySelectorAll('section.s-block--default-home-slider');
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (!e.isIntersecting) return;
e.target.classList.add('hf-in');
io.unobserve(e.target);
});
}, { rootMargin: '0px 0px -12% 0px' });
for (var i = 1; i < all.length; i++) io.observe(all[i]);
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init, { once: true });
else init();
})();
/* ---------- 11) الهيدر: الثيم بيقلل طول الفراغ مكان الهيدر فجأة فالمحتوى بينط. هنا الفراغ بيفضل بالطول الأصلي، والهيدر بينزل لمكانه بنعومة ---------- */
(function () {
'use strict';
function init() {
var header = document.querySelector('#header[data-saji-scroll-nav]');
if (!header) return;
var root = document.documentElement;
var flowTop = 0;
var wasSticky = header.classList.contains('is-saji-sticky');
function measure() {
if (header.classList.contains('is-saji-sticky')) return;
var menu = header.querySelector('.saji-header-menu--below');
root.style.setProperty('--hf-header-h', header.offsetHeight + 'px');
if (menu) root.style.setProperty('--hf-menu-h', menu.offsetHeight + 'px');
flowTop = header.getBoundingClientRect().top + window.scrollY;
root.classList.add('hf-header-ready');
}
new MutationObserver(function () {
var sticky = header.classList.contains('is-saji-sticky');
if (sticky === wasSticky) return;
wasSticky = sticky;
if (sticky) {
root.style.setProperty('--hf-enter', Math.max(0, flowTop - window.scrollY) + 'px');
header.classList.add('hf-sticky-enter');
} else {
header.classList.remove('hf-sticky-enter');
measure();
}
}).observe(header, { attributes: true, attributeFilter: ['class'] });
header.addEventListener('animationend', function (e) {
if (e.target === header) header.classList.remove('hf-sticky-enter');
});
window.addEventListener('resize', measure, { passive: true });
window.addEventListener('load', measure, { once: true });
measure();
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init, { once: true });
else init();
})();
/* ---------- 12) صفحة المنتج: «مسرح» المنتج (نور وذرات وإمالة 3D)، قصة المنتج من الوصف، شريط شراء ثابت، والصورة بتطير للسلة. المحتوى كله من سلة ---------- */
(function () {
'use strict';
// نصوص ثابتة يقدر صاحب المتجر يغيّرها من هنا
var CONFIG = {
whatsapp: '966502399222',
trust: [
{ icon: 'truck', title: 'توصيل لكل المدن', sub: 'لين باب بيتك' },
{ icon: 'back', title: 'استرجاع سهل', sub: 'خلال 7 أيام من الاستلام' },
{ icon: 'leaf', title: 'خبرة 40 سنة', sub: 'في العطارة والبهارات' },
{ icon: 'chat', title: 'عندك سؤال؟', sub: 'راسلنا واتساب', wa: true }
],
marquee: ['مختار لك بعناية', 'خبرة أكثر من 40 سنة', 'نوصّل لين باب البيت', 'استرجاع خلال 7 أيام'],
storyEyebrow: 'قصة المنتج',
firstPart: 'عن المنتج',
buyNote: 'نجهّز طلبك ونشحنه بأسرع وقت'
};
var ICONS = {
truck: '',
back: '',
leaf: '',
chat: ''
};
var reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var canHover = window.matchMedia && window.matchMedia('(hover: hover) and (pointer: fine)').matches;
function $(s, r) { return (r || document).querySelector(s); }
function $$(s, r) { return Array.prototype.slice.call((r || document).querySelectorAll(s)); }
function trim(s) { return (s || '').replace(/^\s+|\s+$/g, ''); }
function make(tag, cls, text) {
var e = document.createElement(tag);
if (cls) e.className = cls;
if (text) e.textContent = text;
return e;
}
function svg(name) {
return '';
}
function pad(n) { return (n < 10 ? '0' : '') + n; }
function init() {
if (!document.body.classList.contains('product-single')) return;
var form = $('form#single-product-form');
var layout = $('.saji-pdp__layout');
if (!form || !layout) return;
var stage = layout.closest('.saji-pdp > div') || layout.parentNode;
var gallery = $('.saji-pdp__gallery');
var slider = gallery && $('.saji-pdp__slider', gallery);
var titleEl = $('h1.product-title', form);
var title = titleEl ? trim(titleEl.textContent) : '';
var desc = $('#more-content');
stage.classList.add('hp-stage');
if (!reduce) stage.classList.add('hp-anim');
ambient(stage, gallery);
splitTitle(titleEl);
highlights(form, desc);
trust(form, title);
buyNote(form);
galleryExtras(gallery, slider, form);
var after = marquee(stage);
story(after, desc, gallery, title);
hideEmpty();
reveal();
waitButton(form, function (btn) {
stickyBar(btn, form, gallery, title);
flyToCart(btn, gallery);
});
// الدخول: نستنى فريمين عشان الحالة الأولى تتطبق الأول
window.requestAnimationFrame(function () {
window.requestAnimationFrame(function () { stage.classList.add('hp-ready'); });
});
}
/* النور اللي بيمشي مع الماوس، وذرات الزعفران الطايرة */
function ambient(stage, gallery) {
var amb = make('div', 'hp-amb');
amb.setAttribute('aria-hidden', 'true');
var glow = make('div', 'hp-amb__glow');
var canvas = make('canvas', 'hp-amb__dust');
amb.appendChild(glow);
amb.appendChild(canvas);
stage.insertBefore(amb, stage.firstChild);
// النور يبدأ ورا الصورة
function home() {
if (!gallery) return;
var s = stage.getBoundingClientRect();
var g = gallery.getBoundingClientRect();
glow.style.setProperty('--hp-gx', (g.left - s.left + g.width / 2) + 'px');
glow.style.setProperty('--hp-gy', (g.top - s.top + g.height / 2.4) + 'px');
}
home();
if (reduce) return;
if (canHover) {
var px = 0, py = 0, queued = false;
stage.addEventListener('pointermove', function (e) {
var s = stage.getBoundingClientRect();
px = e.clientX - s.left;
py = e.clientY - s.top;
if (queued) return;
queued = true;
window.requestAnimationFrame(function () {
queued = false;
glow.style.setProperty('--hp-gx', px + 'px');
glow.style.setProperty('--hp-gy', py + 'px');
});
}, { passive: true });
stage.addEventListener('pointerleave', home);
}
var ctx = canvas.getContext('2d');
if (!ctx) return;
var dpr = Math.min(window.devicePixelRatio || 1, 1.5);
var W = 0, H = 0, dots = [], raf = 0, visible = false;
function size() {
W = stage.clientWidth;
H = stage.clientHeight;
canvas.width = Math.round(W * dpr);
canvas.height = Math.round(H * dpr);
canvas.style.width = W + 'px';
canvas.style.height = H + 'px';
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
var n = W < 700 ? 22 : 46;
dots = [];
for (var i = 0; i < n; i++) {
dots.push({
x: Math.random() * W,
y: Math.random() * H,
r: 0.6 + Math.random() * 1.9,
vy: 0.12 + Math.random() * 0.38,
vx: (Math.random() - 0.5) * 0.14,
a: 0.18 + Math.random() * 0.5,
t: Math.random() * 6.28
});
}
}
function tick() {
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = '#F0C26B';
for (var i = 0; i < dots.length; i++) {
var p = dots[i];
p.t += 0.012;
p.y -= p.vy;
p.x += p.vx + Math.sin(p.t) * 0.12;
if (p.y < -6) { p.y = H + 6; p.x = Math.random() * W; }
ctx.globalAlpha = p.a * (0.55 + 0.45 * Math.sin(p.t * 2.2));
ctx.beginPath();
ctx.arc(p.x, p.y, p.r, 0, 6.283);
ctx.fill();
}
raf = visible ? window.requestAnimationFrame(tick) : 0;
}
size();
if (window.ResizeObserver) {
var lastW = W;
new ResizeObserver(function () {
if (Math.abs(stage.clientWidth - lastW) < 2 && Math.abs(stage.clientHeight - H) < 40) return;
lastW = stage.clientWidth;
size();
home();
}).observe(stage);
}
// الرسم شغال بس والمسرح ظاهر
new IntersectionObserver(function (entries) {
visible = entries[0].isIntersecting;
if (visible && !raf) raf = window.requestAnimationFrame(tick);
}).observe(stage);
}
/* العنوان كلمة كلمة (نفس الكلام، بس كل كلمة في span) */
function splitTitle(h) {
if (!h) return;
var words = trim(h.textContent).split(/\s+/);
if (!words[0]) return;
h.setAttribute('aria-label', words.join(' '));
h.textContent = '';
words.forEach(function (w, i) {
var outer = make('span', 'hp-w');
var inner = make('span', '', w);
inner.style.setProperty('--i', i);
outer.setAttribute('aria-hidden', 'true');
outer.appendChild(inner);
h.appendChild(outer);
if (i < words.length - 1) h.appendChild(document.createTextNode(' '));
});
}
/* أهم المميزات من قسم «المميزات» في الوصف */
function highlights(form, desc) {
if (!desc) return;
var list = null;
$$('h3', desc).some(function (h) {
if (h.textContent.indexOf('المميزات') === -1) return false;
var n = h.nextElementSibling;
while (n && n.tagName !== 'UL' && n.tagName !== 'H3') n = n.nextElementSibling;
if (n && n.tagName === 'UL') list = n;
return !!list;
});
if (!list) list = $('ul', desc);
if (!list) return;
var items = $$('li', list).slice(0, 4).map(function (li) {
var s = $('strong', li);
var t = s ? trim(s.textContent).replace(/[::]\s*$/, '') : trim(li.textContent).split(/\s+/).slice(0, 4).join(' ');
return t;
}).filter(Boolean);
if (!items.length) return;
var ul = make('ul', 'hp-hls');
items.forEach(function (t) { ul.appendChild(make('li', 'hp-hl', t)); });
var price = $('.saji-pdp__price-display', form);
(price ? price.parentNode : form).insertBefore(ul, price ? price.nextSibling : null);
}
/* مربعات الثقة */
function trust(form, title) {
var box = make('div', 'hp-trust');
CONFIG.trust.forEach(function (t) {
var item;
if (t.wa) {
item = make('a', 'hp-trust-item');
item.href = 'https://wa.me/' + CONFIG.whatsapp + '?text=' + encodeURIComponent('السلام عليكم، عندي سؤال عن: ' + title + ' ' + location.href);
item.target = '_blank';
item.rel = 'noopener';
} else {
item = make('div', 'hp-trust-item');
}
var icon = make('span', 'hp-trust-icon');
icon.innerHTML = svg(t.icon);
var copy = make('span');
copy.appendChild(make('strong', '', t.title));
copy.appendChild(make('small', '', t.sub));
item.appendChild(icon);
item.appendChild(copy);
box.appendChild(item);
});
var col = $('.saji-pdp__buybox-col', form);
form.insertBefore(box, col ? col.nextSibling : null);
}
function buyNote(form) {
var box = $('.saji-pdp__buybox', form);
if (box && !$('.hp-buy-note', box)) box.appendChild(make('p', 'hp-buy-note', CONFIG.buyNote));
}
/* الصورة: إمالة 3D ولمعة، بادج الخصم، وعداد الصور */
function galleryExtras(gallery, slider, form) {
if (!gallery || !slider) return;
// نسبة الخصم جنب السعر
var stock = $('.saji-pdp__stock small', form);
var saleRow = $('.saji-pdp__price-display .price_is_on_sale', form);
if (stock && saleRow) saleRow.appendChild(stock);
// بادج الخصم: سلة بتكتب النسبة متأخر، فبنحسبها من السعرين
var badge = make('span', 'hp-gallery-badge');
badge.hidden = true;
slider.appendChild(badge);
var priceBox = $('.saji-pdp__price-display', form);
function num(e) { return e ? parseFloat(e.textContent.replace(/[^\d.]/g, '')) : 0; }
function updateBadge() {
var sale = priceBox && $('.price_is_on_sale', priceBox);
var now = sale && num($('.total-price', sale));
var before = sale && num($('.before-price', sale));
var pct = sale && sale.offsetParent && before > now && now > 0 ? Math.round((before - now) / before * 100) : 0;
badge.hidden = !pct;
if (pct) badge.textContent = '-' + pct + '%';
}
updateBadge();
window.setTimeout(updateBadge, 1500);
if (priceBox) new MutationObserver(updateBadge).observe(priceBox, { childList: true, subtree: true, characterData: true });
// عداد الصور (الصور الأساسية بس)
var slides = $$('.saji-pdp__slide', gallery);
if (slides.length > 1) {
var count = make('span', 'hp-gallery-count');
slider.appendChild(count);
var refresh = function () {
var idx = 0;
for (var k = 0; k < slides.length; k++) if (slides[k].classList.contains('swiper-slide-active')) { idx = k; break; }
var txt = (idx + 1) + ' / ' + slides.length;
if (count.textContent !== txt) count.textContent = txt;
};
refresh();
// بنراقب الشرايح بس (العداد برّاها، فمفيش لفة ما بتخلصش)
var wrap = $('.swiper-wrapper', slider);
if (wrap) new MutationObserver(refresh).observe(wrap, { subtree: true, attributes: true, attributeFilter: ['class'] });
}
// الإمالة واللمعة (لابتوب بس)
var glare = make('span', 'hp-glare');
glare.setAttribute('aria-hidden', 'true');
slider.appendChild(glare);
if (reduce || !canHover) return;
var rect = null, mx = 0, my = 0, queued = false;
slider.addEventListener('pointerenter', function () {
rect = slider.getBoundingClientRect();
slider.classList.add('is-tilt');
});
slider.addEventListener('pointermove', function (e) {
if (!rect) rect = slider.getBoundingClientRect();
mx = (e.clientX - rect.left) / rect.width - 0.5;
my = (e.clientY - rect.top) / rect.height - 0.5;
if (queued) return;
queued = true;
window.requestAnimationFrame(function () {
queued = false;
slider.style.transform = 'perspective(1400px) rotateX(' + (-my * 7).toFixed(2) + 'deg) rotateY(' + (mx * 9).toFixed(2) + 'deg)';
glare.style.setProperty('--hp-lx', (mx * 45).toFixed(1) + '%');
glare.style.setProperty('--hp-ly', (my * 45).toFixed(1) + '%');
});
}, { passive: true });
slider.addEventListener('pointerleave', function () {
rect = null;
slider.classList.remove('is-tilt');
slider.style.transform = '';
});
}
/* الشريط الدهبي المتحرك */
function marquee(stage) {
var bar = make('div', 'hp-marquee');
bar.setAttribute('aria-hidden', 'true');
var track = make('div', 'hp-marquee__track');
// القايمة متكررة 4 مرات عشان تملا الشاشات الكبيرة، والحركة بنص الطول بالظبط
for (var r = 0; r < 4; r++) {
CONFIG.marquee.forEach(function (t) { track.appendChild(make('span', 'hp-marquee__item', t)); });
}
bar.appendChild(track);
stage.parentNode.insertBefore(bar, stage.nextSibling);
// بيقف وهو برّه الشاشة
new IntersectionObserver(function (e) { bar.classList.toggle('is-paused', !e[0].isIntersecting); }).observe(bar);
return bar;
}
/* قصة المنتج: الوصف بيتقسم حسب عناوينه، والصورة ثابتة جنبه */
function story(after, desc, gallery, title) {
if (!desc) return;
var groups = [];
var cur = { title: CONFIG.firstPart, nodes: [] };
function hasText(nodes) { return nodes.some(function (n) { return trim(n.textContent); }); }
Array.prototype.forEach.call(desc.childNodes, function (n) {
if (n.nodeType === 1 && n.tagName === 'H3') {
if (hasText(cur.nodes)) groups.push(cur);
cur = { title: trim(n.textContent), nodes: [] };
} else if (n.nodeType === 1 && n.tagName === 'BR') {
return;
} else if (n.nodeType === 3 && !trim(n.textContent)) {
return;
} else {
cur.nodes.push(n);
}
});
if (hasText(cur.nodes)) groups.push(cur);
if (!groups.length) return;
var sec = make('section', 'hp-story');
var inner = make('div', 'hp-story__inner');
var head = make('div', 'hp-story__head');
head.setAttribute('data-hp-reveal', '');
head.appendChild(make('span', 'hp-eyebrow', CONFIG.storyEyebrow));
head.appendChild(make('h2', 'hp-story__title', title));
inner.appendChild(head);
// صور المنتج نفسها
var srcs = [];
$$('.saji-pdp__slide img', gallery).forEach(function (img) {
var s = img.getAttribute('data-src') || img.currentSrc || img.src;
if (s && srcs.indexOf(s) === -1) srcs.push(s);
});
var media = make('aside', 'hp-story__media');
var frame = make('div', 'hp-story__frame');
var pics = srcs.map(function (s, i) {
var im = make('img');
im.src = s;
im.alt = title;
im.loading = 'lazy';
if (!i) im.className = 'is-on';
frame.appendChild(im);
return im;
});
var metaRow = make('div', 'hp-story__meta');
var bigNum = make('span', 'hp-story__num', '01');
var bar = make('span', 'hp-story__bar');
bar.appendChild(document.createElement('i'));
metaRow.appendChild(bigNum);
metaRow.appendChild(bar);
media.appendChild(frame);
media.appendChild(metaRow);
if (pics.length) inner.appendChild(media);
var steps = make('div', 'hp-story__steps');
var stepEls = groups.map(function (g, i) {
var step = make('article', 'hp-step' + (i ? '' : ' is-active'));
step.appendChild(make('span', 'hp-step__num', pad(i + 1) + ' / ' + pad(groups.length)));
step.appendChild(make('h3', '', g.title));
var body = make('div', 'hp-step__body');
g.nodes.forEach(function (n) { body.appendChild(n.cloneNode(true)); });
step.appendChild(body);
steps.appendChild(step);
return step;
});
inner.appendChild(steps);
sec.appendChild(inner);
after.parentNode.insertBefore(sec, after.nextSibling);
document.body.classList.add('hp-has-story');
var active = 0;
function setActive(i) {
if (i === active) return;
stepEls[active].classList.remove('is-active');
stepEls[i].classList.add('is-active');
active = i;
bigNum.textContent = pad(i + 1);
bar.firstChild.style.setProperty('--hp-p', ((i + 1) / groups.length).toFixed(3));
if (pics.length > 1) {
pics.forEach(function (p, k) { p.classList.toggle('is-on', k === i % pics.length); });
} else if (pics[0]) {
pics[0].style.setProperty('--hp-zoom', (1 + (i % 2) * 0.07).toFixed(2));
}
}
bar.firstChild.style.setProperty('--hp-p', (1 / groups.length).toFixed(3));
// القسم اللي في نص الشاشة هو اللي بينوّر
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (e.isIntersecting) setActive(stepEls.indexOf(e.target));
});
}, { rootMargin: '-45% 0px -45% 0px' });
stepEls.forEach(function (s) { io.observe(s); });
}
/* السكاشن الفاضية بتستخبى، وترجع لو اتملت */
function hideEmpty() {
var reviews = $('.saji-reviews-theme');
var rBox = reviews && reviews.closest('.container');
if (rBox) {
var checkReviews = function () {
var has = $('.s-comments-item, [class*="comment-item"]', reviews);
rBox.style.display = !has && reviews.textContent.replace(/\s+/g, '').length < 12 ? 'none' : '';
};
checkReviews();
new MutationObserver(checkReviews).observe(reviews, { childList: true, subtree: true });
}
var similar = $('.container.similar-products-slider');
if (similar) {
var checkSimilar = function () {
// سلة بتحط شريحة فاضية حتى لو مفيش منتجات، فبندوّر على كارت منتج حقيقي
similar.style.display = $('custom-salla-product-card, salla-product-card, .s-product-card-entry, .product-entry', similar) ? '' : 'none';
};
window.setTimeout(checkSimilar, 3000);
new MutationObserver(checkSimilar).observe(similar, { childList: true, subtree: true });
}
}
/* ظهور ناعم للسكاشن اللي تحت */
function reveal() {
$$('.s-block--bundle-similar-products, .container.similar-products-slider, .saji-reviews-theme').forEach(function (e) {
e.setAttribute('data-hp-reveal', '');
});
var els = $$('[data-hp-reveal]');
if (reduce || !window.IntersectionObserver) {
els.forEach(function (e) { e.classList.add('hp-in'); });
return;
}
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (!e.isIntersecting) return;
e.target.classList.add('hp-in');
io.unobserve(e.target);
});
}, { rootMargin: '0px 0px -10% 0px' });
els.forEach(function (e) { io.observe(e); });
}
/* زرار سلة بيتبني بعد تحميل الصفحة، فبنستناه */
function waitButton(form, done) {
var tries = 0;
(function look() {
var btn = $('salla-add-product-button .s-add-product-button-main button[type="submit"]', form);
if (btn) done(btn);
else if (++tries < 40) window.setTimeout(look, 250);
})();
}
/* شريط الشراء الثابت على اللابتوب */
function stickyBar(btn, form, gallery, title) {
var price = $('.saji-pdp__price-display strong.total-price', form);
var img = gallery && $('.saji-pdp__slide img', gallery);
var bar = make('div', 'hp-bar');
var thumb = make('img');
thumb.alt = '';
if (img) thumb.src = img.currentSrc || img.src;
var copy = make('div', 'hp-bar-copy');
copy.appendChild(make('div', 'hp-bar-title', title));
var pr = make('div', 'hp-bar-price');
copy.appendChild(pr);
var go = make('button', '', 'أضف للسلة');
go.type = 'button';
bar.appendChild(thumb);
bar.appendChild(copy);
bar.appendChild(go);
document.body.appendChild(bar);
go.addEventListener('click', function () { btn.click(); });
function syncPrice() { if (price) pr.innerHTML = price.innerHTML; }
syncPrice();
if (price) new MutationObserver(syncPrice).observe(price.parentNode, { childList: true, subtree: true, characterData: true });
var btnSeen = true, footSeen = false;
function update() { bar.classList.toggle('hp-bar-visible', !btnSeen && !footSeen && window.innerWidth >= 1024); }
new IntersectionObserver(function (e) { btnSeen = e[0].isIntersecting; update(); }).observe(btn);
var foot = $('footer.hf') || $('footer');
if (foot) new IntersectionObserver(function (e) { footSeen = e[0].isIntersecting; update(); }).observe(foot);
window.addEventListener('resize', update, { passive: true });
}
/* الصورة بتطير لأيقونة السلة بعد ما الإضافة تنجح */
function flyToCart(btn, gallery) {
if (reduce || !Element.prototype.animate) return;
var last = 0;
function mark() { last = Date.now(); }
btn.addEventListener('click', mark, true);
document.addEventListener('click', function (e) {
if (e.target.closest && e.target.closest('.hp-bar button')) mark();
}, true);
function fly() {
if (Date.now() - last > 8000) return; // الإضافة جاية من زرار تاني في الصفحة
last = 0;
var cart = $('#header .s-cart-summary-wrapper') || $('#header salla-cart-summary');
var img = gallery && ($('.saji-pdp__slide.swiper-slide-active img', gallery) || $('.saji-pdp__slide img', gallery));
if (!cart || !img) return;
var a = img.getBoundingClientRect();
// لو الصورة برّه الشاشة، بتطير من الزرار
if (a.bottom < 0 || a.top > window.innerHeight || !a.width) {
var b0 = (btn.offsetParent ? btn : $('.hp-bar button') || btn).getBoundingClientRect();
a = { left: b0.left + b0.width / 2 - 40, top: b0.top - 20, width: 80, height: 80 };
}
var c = cart.getBoundingClientRect();
var ghost = make('img', 'hp-ghost');
ghost.src = img.currentSrc || img.src;
ghost.alt = '';
ghost.style.left = a.left + 'px';
ghost.style.top = a.top + 'px';
ghost.style.width = a.width + 'px';
ghost.style.height = a.height + 'px';
document.body.appendChild(ghost);
var dx = c.left + c.width / 2 - (a.left + a.width / 2);
var dy = c.top + c.height / 2 - (a.top + a.height / 2);
var s = 44 / Math.max(a.width, 44);
var anim = ghost.animate([
{ transform: 'translate(0, 0) scale(1)', opacity: 1 },
{ transform: 'translate(' + dx * 0.5 + 'px, ' + (dy * 0.5 - 110) + 'px) scale(' + (s * 3.2) + ')', opacity: 1, offset: 0.55 },
{ transform: 'translate(' + dx + 'px, ' + dy + 'px) scale(' + s * 0.5 + ')', opacity: 0.2 }
], { duration: 950, easing: 'cubic-bezier(0.55, 0, 0.3, 1)' });
anim.onfinish = function () {
ghost.remove();
cart.animate([
{ transform: 'scale(1)' },
{ transform: 'scale(1.35) rotate(-8deg)' },
{ transform: 'scale(1)' }
], { duration: 520, easing: 'cubic-bezier(0.3, 1.6, 0.5, 1)' });
};
}
// نستنى نجاح الإضافة من سلة نفسها
try {
if (window.salla && salla.cart && salla.cart.event && salla.cart.event.onItemAdded) {
salla.cart.event.onItemAdded(fly);
return;
}
} catch (err) { /* لو سلة غيّرت الـAPI نكمل بالضغطة */ }
btn.addEventListener('click', function () { window.setTimeout(fly, 150); });
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init, { once: true });
else init();
})();
/* ---------- 13) الرئيسية: مسرح المنتج المميز (نور وذرات)، شريط دهبي، وطيران صورة المنتج للسلة من أي كارت ---------- */
(function () {
'use strict';
var MARQUEE = ['مختار لك بعناية', 'خبرة أكثر من 40 سنة', 'نوصّل لين باب البيت', 'استرجاع خلال 7 أيام'];
var reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var canHover = window.matchMedia && window.matchMedia('(hover: hover) and (pointer: fine)').matches;
function make(tag, cls, text) {
var e = document.createElement(tag);
if (cls) e.className = cls;
if (text) e.textContent = text;
return e;
}
/* مسرح المنتج المميز */
function stage() {
var sec = document.querySelector('.single-product-section-home');
if (!sec || sec.classList.contains('hp-home-stage')) return;
sec.classList.add('hp-home-stage');
['tr', 'tl', 'br', 'bl'].forEach(function (k) { sec.appendChild(make('span', 'hp-corner hp-corner--' + k)); });
var amb = make('div', 'hp-amb');
amb.setAttribute('aria-hidden', 'true');
var glow = make('div', 'hp-amb__glow');
var canvas = make('canvas', 'hp-amb__dust');
amb.appendChild(glow);
amb.appendChild(canvas);
sec.insertBefore(amb, sec.firstChild);
// الشريط الدهبي تحت المسرح، وبيقف وهو برّه الشاشة
var bar = make('div', 'hp-marquee');
bar.setAttribute('aria-hidden', 'true');
var track = make('div', 'hp-marquee__track');
for (var r = 0; r < 4; r++) MARQUEE.forEach(function (t) { track.appendChild(make('span', 'hp-marquee__item', t)); });
bar.appendChild(track);
sec.parentNode.insertBefore(bar, sec.nextSibling);
new IntersectionObserver(function (e) { bar.classList.toggle('is-paused', !e[0].isIntersecting); }).observe(bar);
if (reduce) return;
// النور بيمشي مع الماوس
if (canHover) {
var px = 0, py = 0, queued = false;
sec.addEventListener('pointermove', function (e) {
var s = sec.getBoundingClientRect();
px = e.clientX - s.left;
py = e.clientY - s.top;
if (queued) return;
queued = true;
window.requestAnimationFrame(function () {
queued = false;
glow.style.setProperty('--hp-gx', px + 'px');
glow.style.setProperty('--hp-gy', py + 'px');
});
}, { passive: true });
}
// ذرات الزعفران (شغالة بس والمسرح ظاهر)
var ctx = canvas.getContext('2d');
if (!ctx) return;
var dpr = Math.min(window.devicePixelRatio || 1, 1.5);
var W = 0, H = 0, dots = [], raf = 0, visible = false;
function size() {
W = sec.clientWidth;
H = sec.clientHeight;
canvas.width = Math.round(W * dpr);
canvas.height = Math.round(H * dpr);
canvas.style.width = W + 'px';
canvas.style.height = H + 'px';
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
var n = W < 700 ? 20 : 42;
dots = [];
for (var i = 0; i < n; i++) {
dots.push({ x: Math.random() * W, y: Math.random() * H, r: 0.6 + Math.random() * 1.9, vy: 0.12 + Math.random() * 0.38, vx: (Math.random() - 0.5) * 0.14, a: 0.18 + Math.random() * 0.5, t: Math.random() * 6.28 });
}
}
function tick() {
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = '#F0C26B';
for (var i = 0; i < dots.length; i++) {
var p = dots[i];
p.t += 0.012;
p.y -= p.vy;
p.x += p.vx + Math.sin(p.t) * 0.12;
if (p.y < -6) { p.y = H + 6; p.x = Math.random() * W; }
ctx.globalAlpha = p.a * (0.55 + 0.45 * Math.sin(p.t * 2.2));
ctx.beginPath();
ctx.arc(p.x, p.y, p.r, 0, 6.283);
ctx.fill();
}
raf = visible ? window.requestAnimationFrame(tick) : 0;
}
size();
if (window.ResizeObserver) {
var lastW = W;
new ResizeObserver(function () {
if (Math.abs(sec.clientWidth - lastW) < 2 && Math.abs(sec.clientHeight - H) < 40) return;
lastW = sec.clientWidth;
size();
}).observe(sec);
}
new IntersectionObserver(function (e) {
visible = e[0].isIntersecting;
if (visible && !raf) raf = window.requestAnimationFrame(tick);
}).observe(sec);
}
/* صورة المنتج بتطير للسلة بعد ما الإضافة تنجح (صفحة المنتج ليها نسخة خاصة في قسم 12) */
function flyToCart() {
if (reduce || !Element.prototype.animate) return;
var src = null, from = null, at = 0;
document.addEventListener('click', function (e) {
var btn = e.target.closest && e.target.closest('button');
if (!btn) return;
var card = btn.closest('custom-salla-product-card, salla-product-card, .single-product-section-home');
if (!card) return;
var img = card.querySelector('img.card-slide-first, .card-slide-images img, img');
var bg = card.querySelector('.lazy__bg[data-bg]');
var box = img || bg;
if (!box) return;
src = img ? (img.currentSrc || img.src) : bg.getAttribute('data-bg');
from = box;
at = Date.now();
}, true);
function fly() {
if (!from || Date.now() - at > 8000) return;
var cart = document.querySelector('#header .s-cart-summary-wrapper') || document.querySelector('#header salla-cart-summary');
if (!cart) return;
var a = from.getBoundingClientRect();
var c = cart.getBoundingClientRect();
from = null;
if (!a.width || a.bottom < 0 || a.top > window.innerHeight) return;
var w = Math.min(a.width, 240), h = Math.min(a.height, 240);
var x = a.left + (a.width - w) / 2, y = a.top + (a.height - h) / 2;
var ghost = make('img', 'hp-ghost');
ghost.src = src;
ghost.alt = '';
ghost.style.cssText = 'left:' + x + 'px;top:' + y + 'px;width:' + w + 'px;height:' + h + 'px';
document.body.appendChild(ghost);
var dx = c.left + c.width / 2 - (x + w / 2);
var dy = c.top + c.height / 2 - (y + h / 2);
var s = 44 / Math.max(w, 44);
var anim = ghost.animate([
{ transform: 'translate(0, 0) scale(1)', opacity: 1 },
{ transform: 'translate(' + dx * 0.5 + 'px, ' + (dy * 0.5 - 110) + 'px) scale(' + Math.min(1, s * 3.2) + ')', opacity: 1, offset: 0.55 },
{ transform: 'translate(' + dx + 'px, ' + dy + 'px) scale(' + s * 0.5 + ')', opacity: 0.2 }
], { duration: 950, easing: 'cubic-bezier(0.55, 0, 0.3, 1)' });
anim.onfinish = function () {
ghost.remove();
cart.animate([{ transform: 'scale(1)' }, { transform: 'scale(1.35) rotate(-8deg)' }, { transform: 'scale(1)' }], { duration: 520, easing: 'cubic-bezier(0.3, 1.6, 0.5, 1)' });
};
}
try {
if (window.salla && salla.cart && salla.cart.event && salla.cart.event.onItemAdded) salla.cart.event.onItemAdded(fly);
} catch (err) { /* سلة غيّرت الـAPI */ }
}
function init() {
if (document.body.classList.contains('product-single')) return;
if (document.body.classList.contains('index')) stage();
flyToCart();
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init, { once: true });
else init();
})();