/* Add custom JS code below */ /* ============================================================ ROUGE NOIR — NARS-Inspired Theme JavaScript for Salla ------------------------------------------------------------ HOW TO USE (Salla): 1. Store Dashboard → المظهر (Store Design/Theme) → الإعدادات المتقدمة (Advanced Settings) → Custom JS 2. Paste this entire file. 3. Save & publish. It is safe & silent — every feature checks for the element before acting, so it never breaks your store. ============================================================ */ (function () { "use strict"; /* ---------- THEME TOKENS ---------- */ var THEME = { rouge: "#e4002b", rougeDark: "#b8001f", rougeSoft: "#fbe6ea", ink: "#0a0a0a", paper: "#ffffff", cream: "#f6f4f0", stone: "#7d746c", radius: "0px", fontDisplay: "'Oswald','Cairo',sans-serif", fontBody: "'Inter','Cairo',sans-serif" }; /* Apply tokens to as CSS custom properties */ function applyTheme(t) { var r = document.documentElement; var map = { "--rn-rouge": t.rouge, "--rn-rouge-dark": t.rougeDark, "--rn-rouge-soft": t.rougeSoft, "--rn-ink": t.ink, "--rn-night": t.ink, "--rn-paper": t.paper, "--rn-cream": t.cream, "--rn-stone": t.stone, "--rn-radius": t.radius, "--rn-font-display": t.fontDisplay, "--rn-font-body": t.fontBody, "--color-primary": t.rouge, "--color-secondary": t.ink, "--salla-primary-color": t.rouge, "--salla-secondary-color": t.ink }; for (var k in map) r.style.setProperty(k, map[k]); } applyTheme(THEME); /* ---------- 1. INJECT GOOGLE FONTS ---------- */ function loadFonts() { if (document.getElementById("rn-fonts")) return; var pre1 = document.createElement("link"); pre1.rel = "preconnect"; pre1.href = "https://fonts.googleapis.com"; var pre2 = document.createElement("link"); pre2.rel = "preconnect"; pre2.href = "https://fonts.gstatic.com"; pre2.crossOrigin = ""; var css = document.createElement("link"); css.id = "rn-fonts"; css.rel = "stylesheet"; css.href = "https://fonts.googleapis.com/css2?family=Oswald:wght@300;400;500;600;700" + "&family=Inter:wght@300;400;500;600;700;800;900" + "&family=Cairo:wght@400;500;600;700;800;900&display=swap"; document.head.appendChild(pre1); document.head.appendChild(pre2); document.head.appendChild(css); } /* ---------- 2. SCROLL-REVEAL ANIMATIONS ---------- */ function initReveal() { var els = document.querySelectorAll(".rn-reveal"); if (!els.length) return; if (!("IntersectionObserver" in window)) { els.forEach(function (e) { e.classList.add("is-visible"); }); return; } var obs = new IntersectionObserver(function (entries) { entries.forEach(function (e) { if (e.isIntersecting) { e.target.classList.add("is-visible"); obs.unobserve(e.target); } }); }, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" }); els.forEach(function (e) { obs.observe(e); }); } /* ---------- 3. STICKY HEADER ON SCROLL ---------- */ function initStickyHeader() { var header = document.querySelector(".site-header") || document.querySelector(".s-header") || document.querySelector("header"); if (!header) return; var scrolled = false; function onScroll() { var s = window.scrollY > 40; if (s === scrolled) return; scrolled = s; header.classList.toggle("rn-scrolled", s); header.style.boxShadow = s ? "0 1px 0 rgba(0,0,0,.08)" : "none"; header.style.background = "var(--rn-paper)"; } window.addEventListener("scroll", onScroll, { passive: true }); onScroll(); } /* ---------- 4. BACK-TO-TOP BUTTON ---------- */ function initBackToTop() { if (document.getElementById("rn-backtop")) return; var btn = document.createElement("button"); btn.id = "rn-backtop"; btn.innerHTML = "↑"; btn.setAttribute("aria-label", "Back to top"); btn.style.cssText = "position:fixed;bottom:20px;inset-inline-end:20px;z-index:60;width:46px;height:46px;" + "border:0;border-radius:50%;background:var(--rn-ink,#0a0a0a);color:#fff;font-size:18px;" + "cursor:pointer;box-shadow:0 10px 30px rgba(0,0,0,.3);opacity:0;transform:translateY(12px);" + "pointer-events:none;transition:all .35s ease;"; btn.addEventListener("mouseenter", function () { btn.style.background = "var(--rn-rouge,#e4002b)"; }); btn.addEventListener("mouseleave", function () { btn.style.background = "var(--rn-ink,#0a0a0a)"; }); btn.addEventListener("click", function () { window.scrollTo({ top: 0, behavior: "smooth" }); }); document.body.appendChild(btn); window.addEventListener("scroll", function () { var show = window.scrollY > 600; btn.style.opacity = show ? "1" : "0"; btn.style.transform = show ? "translateY(0)" : "translateY(12px)"; btn.style.pointerEvents = show ? "auto" : "none"; }, { passive: true }); } /* ---------- 5. ANNOUNCEMENT BAR ROTATOR ---------- */ function initAnnouncement() { var bars = document.querySelectorAll(".rn-announce"); bars.forEach(function (bar) { var items = bar.querySelectorAll(".rn-announce__item"); if (items.length < 2) return; var i = 0; setInterval(function () { items[i].style.opacity = "0"; items[i].style.transform = "translateY(-100%)"; i = (i + 1) % items.length; items[i].style.transform = "translateY(100%)"; // force reflow void items[i].offsetWidth; items[i].style.opacity = "1"; items[i].style.transform = "translateY(0)"; }, 4000); }); } /* ---------- 6. MARQUEE DUPLICATOR ---------- */ function initMarquee() { document.querySelectorAll(".rn-marquee").forEach(function (m) { if (m.dataset.rnReady) return; m.dataset.rnReady = "1"; m.innerHTML = m.innerHTML + m.innerHTML; /* duplicate for seamless loop */ }); } /* ---------- INIT ---------- */ function init() { loadFonts(); applyTheme(THEME); initReveal(); initStickyHeader(); initBackToTop(); initAnnouncement(); initMarquee(); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", init); } else { init(); } /* ---------- PUBLIC API: change the theme live ---------- Open the browser console and run, e.g.: sallaTheme.set({ rouge: "#0f7a5a", radius: "8px" }) sallaTheme.dark(true) sallaTheme.reset() ---------------------------------------------------------- */ window.sallaTheme = { set: function (patch) { for (var k in patch) THEME[k] = patch[k]; applyTheme(THEME); return THEME; }, dark: function (on) { if (on) { applyTheme(Object.assign({}, THEME, { ink: "#f3f0ea", paper: "#0c0c0c", cream: "#161616", stone: "#a99f95" })); } else { applyTheme(THEME); } }, reset: function () { THEME = { rouge: "#e4002b", rougeDark: "#b8001f", rougeSoft: "#fbe6ea", ink: "#0a0a0a", paper: "#ffffff", cream: "#f6f4f0", stone: "#7d746c", radius: "0px", fontDisplay: "'Oswald','Cairo',sans-serif", fontBody: "'Inter','Cairo',sans-serif" }; applyTheme(THEME); } }; })();