קווים מפוסלים ומעטפת זכוכית בגוון חם משתלבים כדי להעניק זוהר רך וזהוב, אידיאלי לשולחנות עבודה, לשידות לילה או למשטחי קונסולה. מסגרת העץ המקושתת באלגנטיות נמנעת מקישוטיות כבדה, ומאפשרת לפריט להשתלב בקלות בחללי פנים עכשוויים, ניטרליים ובגווני אדמה.

עיצוב ובנייה
בסיס עץ מקושת בגוון אגוז מעגן את גוף התאורה ומציג טכניקות נגרות אורגניות. מפזר הזכוכית הנלווה מעוצב ידנית בכבשן, ולכן כיסי אוויר מיקרוסקופיים ושינויים עדינים במרקם פני השטח הם מאפייני ייצור טבעיים ואינם נחשבים לפגמי ייצור.
- צללית עץ זורמת בגימור עשיר בגוון אגוז
- כיפת זכוכית כהה המסננת את האור לגוון צהוב עמוק
- מערך חשמלי מוכן לשימוש הכולל כבל באורך 59.1 אינץ' ומתג הפעלה מוחשי
תאורה ומידות
מערכת התאורה הפנימית צורכת כ-12 ואט באמצעות דיודות מוליכים למחצה מובנות, שתוכננו להפעלה יומיומית ממושכת. סדרות רגילות מסופקות עם טמפרטורת צבע נעימה של 3000 קלווין; לקוחות המעוניינים באפשרות מאוזנת של 4000K או באפשרות חדה של 6000K חייבים לתאם זאת ישירות עם התמיכה לפני התשלום. שתי אפשרויות גובה מבטיחות התאמה למגוון סידורי חדר. לשתי הגרסאות מידה זהה של 8.7 אינץ' בחתך, והן משתמשות בדיוק באותו כיסוי זכוכית. הגרסה הנמוכה מתנשאת לגובה 9.8 אינץ', ואילו הגרסה הגבוהה מגיעה ל-12.6 אינץ'.

{
resetProtectionAfterCheckoutReturn();
});
(async function ShipCheckCartExtension() {
const CONFIG = {
EXTENSION_DISABLED: false,
EXTENSION_LAYOUT: "user_consent",
TIMESTAMP: "1790184857",
SHOP_PERMANENT_DOMAIN: "rpejan-3j.myshopify.com",
PRODUCT_HANDLE: "shipping-protection-1",
PRODUCT_ID: 15652463411573,
AUTO_ACCEPT: true,
AUTO_TRANSLATE: true,
DISABLE_FOR_DIGITAL_PRODUCTS: false,
EXCLUDE_DIGITAL_PRODUCTS: false,
IMAGE_GRAYSCALE: false,
CHECKOUT_SELECTOR: "button[name=\"checkout\"]",
CART_TOTAL_SELECTOR: ".totals__total-value",
EXTENSION_TARGET_SELECTOR: "",
CURRENT_COUNTRY: "DE",
};
const CHECKOUT_BUTTONS = [
CONFIG.CHECKOUT_SELECTOR,
'button[name="checkout"],.rebuy-cart__checkout-button,#mu-checkout-button,.cd-checkout-section-button,.ocu-checkout-button,.slide-cart-checkout-btn,.boost-sd__btn-checkout,input[name="checkout"]:not([type="hidden"]),a[id="cart__checkout_btn"],button[data-href="/checkout"],a[href="/checkout"]:not(#checkout-xx-aa),a[href="/en/checkout"],.xb_slide_cart_button_checkout,.scd__checkout,.AOV-CartDrawer-Checkout,button[upnova-action="checkout"],#cart-sidebar-checkout,a[data-instant-action-type="redirect-to-checkout"],.amp-cart__footer-checkout-button,button[name="icartCheckout"],.unicorn_checkout_button,#corner-cowi-cart-summary-card-cta-button,button[name="waio_addToCart"],.checkout-button,.upcart-checkout-button,button[data-essential-cart-element="cart-drawer-checkout-button"],#AOV-CDMinimal__ViewCartButton,.easc-checkoutBtn,.pp-checkout-button,button[href^="https://www.shop.carcover.com/cart/"],.kaching-cart__checkout-button,.qsc2-checkout-button',
].filter((s) => String(s || '').trim()).join(',');
const CUSTOMER_TAGS = null;
const LOCALES_JSON = {"en":{"cartTickerTitle":"Secure Checkout","cartTickerSubtitleOn":"Your order is protected from loss or damage","cartTickerSubtitleOff":"Your order isn't protected from loss or damage ","cartTickerPolicy":"Terms and Conditions","cartBtnLayoutLabel":"Protected Checkout","cartBtnLayoutTitle":"Secure Checkout","cartBtnLayoutSubtitle":"Your order is protected from loss or damage","cartBtnLayoutPolicy":"Terms","checkoutTitle":"Shipping Protection","checkoutSubtitleOn":"Order is protected from loss or damage","checkoutSubtitleOff":"Order is not protected from loss or damage","checkoutPolicy":"Terms and Conditions","thankYouTitle":"Shipping Protection","thankYouSubtitle":"Protect your order from loss or damage","thankYouPolicy":"Terms and Conditions","thankYouBuyBtn":"Add to order","thankYouBuyBtnError":"Retry","thankYouPaymentLink":"Pay now"},"ar":{"cartTickerTitle":"الدفع الآمن","cartTickerSubtitleOn":"طلبك محمي من الفقدان أو التلف","cartTickerSubtitleOff":"طلبك غير محمي من الفقدان أو التلف","cartBtnLayoutLabel":"دفع محمي","cartBtnLayoutTitle":"الدفع الآمن","cartBtnLayoutSubtitle":"طلبك محمي من الضياع أو التلف"},"cs":{"cartTickerTitle":"Bezpečná pokladna","cartTickerSubtitleOn":"Vaše objednávka je chráněna proti ztrátě nebo poškození","cartTickerSubtitleOff":"Vaše objednávka není chráněna proti ztrátě nebo poškození","cartBtnLayoutLabel":"Chráněná pokladna","cartBtnLayoutTitle":"Bezpečný pokladní výstup","cartBtnLayoutSubtitle":"Vaše objednávka je chráněna před ztrátou nebo pošk"},"da":{"cartTickerTitle":"Sikker betaling","cartTickerSubtitleOn":"Din ordre er beskyttet mod tab eller skade","cartTickerSubtitleOff":"Din ordre er ikke beskyttet mod tab eller skade","cartBtnLayoutLabel":"Beskyttet betaling","cartBtnLayoutTitle":"Sikker checkout","cartBtnLayoutSubtitle":"Din ordre er beskyttet mod tab eller beskadigelse"},"de":{"cartTickerTitle":"Sicherer Checkout","cartTickerSubtitleOn":"Ihre Bestellung ist gegen Verlust oder Beschädigung geschützt","cartTickerSubtitleOff":"Ihre Bestellung ist nicht gegen Verlust oder Beschädigung geschützt","cartBtnLayoutLabel":"Geschützter Checkout","cartBtnLayoutTitle":"Sicherer Checkout","cartBtnLayoutSubtitle":"Ihre Bestellung ist vor Verlust oder Beschädigung "},"es":{"cartTickerTitle":"Pago seguro","cartTickerSubtitleOn":"Su pedido está protegido contra pérdida o daño","cartTickerSubtitleOff":"Su pedido no está protegido contra pérdida o daño","cartBtnLayoutLabel":"Pago Protegido","cartBtnLayoutTitle":"Proceso de pago seguro","cartBtnLayoutSubtitle":"Su pedido está protegido contra pérdidas o daños"},"fi":{"cartTickerTitle":"Turvallinen kassa","cartTickerSubtitleOn":"Tilauksesi on suojattu katoamista tai vahinkoa vastaan","cartTickerSubtitleOff":"Tilauksesi ei ole suojattu katoamista tai vahinkoa vastaan","cartBtnLayoutLabel":"Suojattu kassa","cartBtnLayoutTitle":"Turvallinen maksu","cartBtnLayoutSubtitle":"Tilauksesi on suojattu katoamiselta tai vahingoitt"},"fr":{"cartTickerTitle":"Paiement sécurisé","cartTickerSubtitleOn":"Votre commande est protégée contre la perte ou les dommages","cartTickerSubtitleOff":"Votre commande n'est pas protégée contre la perte ou les dommages","cartBtnLayoutLabel":"Paiement sécurisé","cartBtnLayoutTitle":"Validation sécurisée","cartBtnLayoutSubtitle":"Votre commande est protégée contre la perte ou les"},"he":{"cartTickerTitle":"צ'קאאוט מאובטח","cartTickerSubtitleOn":"ההזמנה שלך מוגנת מפני אובדן או נזק","cartTickerSubtitleOff":"ההזמנה שלך אינה מוגנת מפני אובדן או נזק","cartBtnLayoutLabel":"קופה מוגנת","cartBtnLayoutTitle":"תשלום מאובטח","cartBtnLayoutSubtitle":"ההזמנה שלך מוגנת מפני אובדן או נזק"},"hu":{"cartTickerTitle":"Biztonságos fizetés","cartTickerSubtitleOn":"A rendelése védett elvesztés vagy sérülés ellen","cartTickerSubtitleOff":"A rendelése nincs védve elvesztés vagy sérülés ellen","cartBtnLayoutLabel":"Védett pénztár","cartBtnLayoutTitle":"Biztonságos pénztár","cartBtnLayoutSubtitle":"A rendelése védve van az elvesztéstől vagy sérülés"},"it":{"cartTickerTitle":"Checkout sicuro","cartTickerSubtitleOn":"Il tuo ordine è protetto da smarrimento o danni","cartTickerSubtitleOff":"Il tuo ordine non è protetto da smarrimento o danni","cartBtnLayoutLabel":"Pagamento protetto","cartBtnLayoutTitle":"Checkout sicuro","cartBtnLayoutSubtitle":"Il tuo ordine è protetto da smarrimento o danneggi"},"ja":{"cartTickerTitle":"安全なチェックアウト","cartTickerSubtitleOn":"ご注文は紛失や損傷から保護されています","cartTickerSubtitleOff":"ご注文は紛失や損傷から保護されていません","cartBtnLayoutLabel":"保護されたチェックアウト","cartBtnLayoutTitle":"安全なチェックアウト","cartBtnLayoutSubtitle":"ご注文は紛失や破損から保護されます"},"nb":{"cartTickerTitle":"Sikker betaling","cartTickerSubtitleOn":"Bestillingen din er beskyttet mot tap eller skade","cartTickerSubtitleOff":"Bestillingen din er ikke beskyttet mot tap eller skade","cartBtnLayoutLabel":"Beskyttet betaling","cartBtnLayoutTitle":"Sikker utsjekk","cartBtnLayoutSubtitle":"Bestillingen din er beskyttet mot tap eller skade"},"nl":{"cartTickerTitle":"Veilige checkout","cartTickerSubtitleOn":"Je bestelling is beschermd tegen verlies of schade","cartTickerSubtitleOff":"Je bestelling is niet beschermd tegen verlies of schade","cartBtnLayoutLabel":"Beveiligde betaling","cartBtnLayoutTitle":"Veilig afrekenen","cartBtnLayoutSubtitle":"Uw bestelling is beschermd tegen verlies of bescha"},"pl":{"cartTickerTitle":"Bezpieczna płatność","cartTickerSubtitleOn":"Twoje zamówienie jest chronione przed zagubieniem lub uszkodzeniem","cartTickerSubtitleOff":"Twoje zamówienie nie jest chronione przed zagubieniem lub uszkodzeniem","cartBtnLayoutLabel":" Zabezpieczona płatność","cartBtnLayoutTitle":"Bezpieczne finalizowanie zamówienia","cartBtnLayoutSubtitle":"Twoje zamówienie jest chronione przed zgubieniem l"},"pt-PT":{"cartTickerTitle":"Checkout seguro","cartTickerSubtitleOn":"A sua encomenda está protegida contra perda ou danos","cartTickerSubtitleOff":"A sua encomenda não está protegida contra perda ou danos","cartBtnLayoutLabel":"Checkout Protegido","cartBtnLayoutTitle":"Checkout seguro","cartBtnLayoutSubtitle":"O seu pedido está protegido contra perdas ou danos"},"ro":{"cartTickerTitle":"Finalizare comandă sigură","cartTickerSubtitleOn":"Comanda dvs. este protejată împotriva pierderii sau deteriorării","cartTickerSubtitleOff":"Comanda dvs. nu este protejată împotriva pierderii sau deteriorării","cartBtnLayoutLabel":"Finalizare comandă protejată","cartBtnLayoutTitle":"Plată securizată","cartBtnLayoutSubtitle":"Comanda dvs. este protejată împotriva pierderii sa"},"sv":{"cartTickerTitle":"Säker utcheckning","cartTickerSubtitleOn":"Din beställning är skyddad mot förlust eller skada","cartTickerSubtitleOff":"Din beställning är inte skyddad mot förlust eller skada","cartBtnLayoutLabel":"Skyddad utcheckning","cartBtnLayoutTitle":"Säker utcheckning","cartBtnLayoutSubtitle":"Din beställning är skyddad mot förlust eller skada"},"zh-CN":{"cartTickerSubtitleOn":"您的订单受到丢失或损坏的保护","cartTickerSubtitleOff":"您的订单未受到丢失或损坏的保护","cartBtnLayoutLabel":"安全结账","cartBtnLayoutTitle":"安全结账"}};
const TS = CONFIG.TIMESTAMP;
const CLASSES = {
ICON: `asc-widget-image-${TS}`,
ROOT: `asc-root-${TS}`,
SUBTITLE: 'asc-shipping-protection-subtitle-text',
SWITCH: 'asc-widget-switch',
PRICE: 'asc-shipping-protection-price',
};
const DEBOUNCE_MS = 500;
const CART_UPDATE_DEBOUNCE_MS = 150;
// Avoid /\/cart\// — some theme minifiers treat the trailing // as a comment.
const CART_REQUEST_URL_RE = new RegExp('/cart/');
const STOREFRONT_CART_EVENTS = [
'shopify:cart:lines-update',
'shopify:cart:note-update',
'shopify:cart:discount-update',
];
const SPINNER_HTML =
'';
const INJECT_INDEX = {
'resource-electrical.myshopify.com': 0,
'trimove-fi.myshopify.com': 1,
'mvmf3z-uc.myshopify.com': 2,
'mycubecraft.myshopify.com': 3,
'barrett-fragrances-6447.myshopify.com': 3,
};
function each(selector, fn) {
document.querySelectorAll(selector).forEach(fn);
}
function debounce(fn, ms) {
let timer = null;
return (...args) => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
fn(...args);
}, ms);
};
}
const EMBEDDED_PLANS = [{"id":57592685789557,"title":"0T50","price":199},{"id":57592685822325,"title":"50T100","price":299},{"id":57592684740981,"title":"100T200","price":449},{"id":56499832258933,"title":"200TN","price":699}];
function currencyRate() {
const rate = Number(Shopify?.currency?.rate);
return Number.isFinite(rate) && rate > 0 ? rate : 1;
}
function normalizePlanVariant(variant, { fromShopMajorUnits = false } = {}) {
const id = variant.id;
const title = variant.title || variant.name || '';
let price = Number(variant.price);
if (!Number.isFinite(price)) price = 0;
if (fromShopMajorUnits) {
price = Math.round(price * 100 * currencyRate());
}
return { id, title, price };
}
async function loadProtectionPlans() {
if (EMBEDDED_PLANS?.length) {
return EMBEDDED_PLANS.map((v) => normalizePlanVariant(v));
}
if (!CONFIG.PRODUCT_HANDLE) {
console.warn('ShipCheck: protection product handle is missing');
return null;
}
const root = String(window.Shopify?.routes?.root || '/').replace(/\/?$/, '/');
const productBase = `${root}products/${encodeURIComponent(CONFIG.PRODUCT_HANDLE)}`;
try {
const response = await fetch(`${productBase}.js`);
if (response.ok) {
const product = await response.json();
if (product?.id && CONFIG.PRODUCT_ID == null) CONFIG.PRODUCT_ID = product.id;
const variants = product?.variants;
if (variants?.length) {
return variants.map((v) => normalizePlanVariant(v));
}
return null;
}
if (response.status === 404) {
console.warn(
'Shipcheck protection product not found or not active',
CONFIG.PRODUCT_HANDLE,
);
return null;
}
} catch {}
try {
const response = await fetch(`${productBase}.json`);
if (!response.ok) return null;
const product = (await response.json())?.product;
if (product?.id && CONFIG.PRODUCT_ID == null) CONFIG.PRODUCT_ID = product.id;
const variants = product?.variants;
if (!variants?.length) return null;
return variants.map((v) => normalizePlanVariant(v, { fromShopMajorUnits: true }));
} catch {
return null;
}
}
const plans = await loadProtectionPlans();
if (!plans) return;
const TLD_LOCALE_SHOPS = new Set([
'rg9hrw-4v.myshopify.com',
'acproductsnl.myshopify.com',
'ffepey-pg.myshopify.com',
]);
const baseLocale = "en";
const shopLocale = TLD_LOCALE_SHOPS.has(CONFIG.SHOP_PERMANENT_DOMAIN)
? window.location.hostname.split('.').pop()
: "he".split('-')[0];
const ctx = {
shopLocale,
shopLangLocale: CONFIG.AUTO_TRANSLATE ? shopLocale : baseLocale,
baseLocale,
plans,
moneyWithCurrencyFormat: "€{{amount_with_comma_separator}} EUR",
moneyFormat: "€{{amount_with_comma_separator}}",
};
const PROTECTION_VARIANT_IDS = new Set(plans.map((p) => String(p.id)));
const translation = {
userConsent: { titles: {}, subtitles: { on: {}, off: {} }, policy: {} },
checkoutButton: { buttonLabel: {}, title: {}, subtitle: {}, policy: {} },
};
(function hydrateTranslation() {
if (!LOCALES_JSON || typeof LOCALES_JSON !== 'object') return;
const set = (target, locale, value) => {
if (typeof value === 'string') target[locale] = value;
};
for (const [locale, strings] of Object.entries(LOCALES_JSON)) {
if (!strings || typeof strings !== 'object') continue;
set(translation.userConsent.titles, locale, strings.cartTickerTitle);
set(translation.userConsent.subtitles.on, locale, strings.cartTickerSubtitleOn);
set(translation.userConsent.subtitles.off, locale, strings.cartTickerSubtitleOff);
set(translation.userConsent.policy, locale, strings.cartTickerPolicy);
set(translation.checkoutButton.buttonLabel, locale, strings.cartBtnLayoutLabel);
set(translation.checkoutButton.title, locale, strings.cartBtnLayoutTitle);
set(translation.checkoutButton.subtitle, locale, strings.cartBtnLayoutSubtitle);
set(translation.checkoutButton.policy, locale, strings.cartBtnLayoutPolicy);
}
})();
function t(map) {
if (!map || typeof map !== 'object') return '';
const value = map[ctx.shopLangLocale] ?? map[ctx.baseLocale] ?? map.en;
return typeof value === 'string' ? value : '';
}
function formatAmount(amount, template = '') {
let locale = ctx.shopLocale;
if (CONFIG.SHOP_PERMANENT_DOMAIN === 'avatechwear.myshopify.com' && Shopify.currency.active === 'EUR') {
locale = 'de-DE';
} else if (CONFIG.SHOP_PERMANENT_DOMAIN === 'u0x8b1-xu.myshopify.com') {
locale = 'en-US';
}
const digits = template.includes('amount_no_decimals') ? 0 : 2;
return new Intl.NumberFormat(locale, {
minimumFractionDigits: digits,
maximumFractionDigits: digits,
}).format(amount);
}
function money(amount, template) {
const formatted = formatAmount(amount, template);
return template.replace(/\{\{(.*?)\}\}/g, () => formatted);
}
const state = {
cart: {"note":null,"attributes":{},"original_total_price":0,"total_price":0,"total_discount":0,"total_weight":0.0,"item_count":0,"items":[],"requires_shipping":false,"currency":"EUR","items_subtotal_price":0,"cart_level_discount_applications":[],"checkout_charge_amount":0},
consent: CONFIG.EXTENSION_DISABLED ? false : CONFIG.AUTO_ACCEPT,
};
let selectedPlan = null;
let hasProtectionInCart = false;
let checkoutBusy = false;
let interceptBusy = false;
let interceptorBound = false;
let addInProgress = false;
let desiredVariantId = null;
let addStartedAt = 0;
let usingStorefrontEvents = false;
let mounting = false;
let mountRetryTimer = null;
const extensionRoots = new Set();
const detachedRoots = [];
const isEnabled = () => !CONFIG.EXTENSION_DISABLED;
const isCheckoutLayout = () => CONFIG.EXTENSION_LAYOUT === 'checkout_button';
const cartItems = () => state.cart?.items || [];
const EXCLUDED_PRODUCT_IDS = [7648135217198];
function numericId(value) {
if (value == null || value === '') return null;
if (typeof value === 'number' && Number.isFinite(value)) return value;
const match = String(value).match(/(\d+)\s*$/);
return match ? Number(match[1]) : null;
}
function isProtectionItem(item) {
if (!item) return false;
const productId = numericId(item.product_id);
if (CONFIG.PRODUCT_ID != null && productId === Number(CONFIG.PRODUCT_ID)) return true;
const variantId = numericId(item.variant_id) ?? numericId(item.id);
if (variantId != null && PROTECTION_VARIANT_IDS.has(String(variantId))) return true;
if (desiredVariantId && variantId != null && String(variantId) === desiredVariantId) return true;
if (item.handle && item.handle === CONFIG.PRODUCT_HANDLE) return true;
const props = item.properties;
return Boolean(props && (props._shipcheck || props['_shipcheck']));
}
function isExcludedProduct(item) {
const productId = numericId(item?.product_id);
return productId != null && EXCLUDED_PRODUCT_IDS.includes(productId);
}
function findProtectionLine() {
return cartItems().find(isProtectionItem) || null;
}
function syncProtectionFlag() {
hasProtectionInCart = cartItems().some(isProtectionItem);
}
function merchandiseTotals() {
let physical = 0;
let merchandise = 0;
for (const item of cartItems()) {
if (isProtectionItem(item) || isExcludedProduct(item)) continue;
const line = Number(item.final_line_price) / 100;
if (!Number.isFinite(line)) continue;
merchandise += line;
if (item.requires_shipping) physical += line;
}
return { merchandise, physical };
}
function planByVariantId(variantId) {
const id = String(numericId(variantId) ?? '');
if (!id) return null;
return ctx.plans.find((plan) => String(plan.id) === id) || null;
}
function selectPlan() {
if (addInProgress && selectedPlan) return;
const line = findProtectionLine();
if (line) {
const locked = planByVariantId(line.variant_id ?? line.id);
if (locked) {
selectedPlan = locked;
return;
}
if (selectedPlan) return;
}
const { merchandise, physical } = merchandiseTotals();
const total = (CONFIG.EXCLUDE_DIGITAL_PRODUCTS ? physical : merchandise) / currencyRate();
selectedPlan = null;
let fallback = null;
for (const variant of ctx.plans) {
const range = String(variant.title || '').split(' ').pop() || '';
const parts = range.split('T');
if (parts.length !== 2) continue;
const min = parseFloat(parts[0]);
const max = parts[1] === 'N' ? Infinity : parseFloat(parts[1]);
if (!Number.isFinite(min)) continue;
if (parts[1] === 'N') fallback = variant;
if (total >= min && total <= max) {
selectedPlan = variant;
break;
}
}
if (!selectedPlan) selectedPlan = fallback;
}
function protectionPrice() {
if (!selectedPlan) return 0;
const cents = Number(selectedPlan.price);
if (!Number.isFinite(cents)) return 0;
return cents / 100;
}
function protectionDisplayAmount() {
const raw = money(protectionPrice(), ctx.moneyFormat);
const tmp = document.createElement('span');
tmp.innerHTML = raw;
return (tmp.textContent || raw).trim();
}
const DISPLAY_RULES = [
{
type: 'country_restriction',
shop: 'pet-tags-com-au.myshopify.com',
evaluate: () => ['NZ'].includes(CONFIG.CURRENT_COUNTRY),
},
{
type: 'customer_tag_restriction',
shop: 'threeworlds.myshopify.com',
evaluate: () => {
const excluded = ['wholesale', 'jasonure'];
return Array.isArray(CUSTOMER_TAGS) && excluded.some((tag) => CUSTOMER_TAGS.includes(tag));
},
},
{
type: 'product_exclusion',
global: true,
evaluate: () => {
const merchandise = cartItems().filter((item) => !isProtectionItem(item));
return merchandise.length > 0 && merchandise.every(isExcludedProduct);
},
},
{
type: 'product_inclusion',
shop: 'art-fever.myshopify.com',
evaluate: () => {
const allowed = ['Photo Roller Blinds', 'Google Blinds', 'Shopping 2025 Best Sellers'];
return !cartItems().some((item) => allowed.includes(item.product_type));
},
},
{
type: 'config_flag',
global: true,
evaluate: () => CONFIG.DISABLE_FOR_DIGITAL_PRODUCTS && !state.cart.requires_shipping,
},
];
function shouldHideExtension() {
return DISPLAY_RULES.some((rule) => {
if (!rule.global && rule.shop && rule.shop !== CONFIG.SHOP_PERMANENT_DOMAIN) return false;
return rule.evaluate();
});
}
function canAddProtection() {
return (
isEnabled() &&
!hasProtectionInCart &&
!shouldHideExtension() &&
cartItems().length > 0 &&
selectedPlan
);
}
function shouldInflateCartTotal() {
return state.consent && !hasProtectionInCart && !addInProgress;
}
function cartTotalText() {
if (!selectedPlan) return null;
const protection = protectionPrice();
const inflate = shouldInflateCartTotal();
if (window.SLIDECART_STATE) {
const base = SLIDECART_STATE().cart.total_price / 100;
return money(
inflate ? base + protection : base,
window.SLIDECART_FORMAT || ctx.moneyFormat,
);
}
if (inflate) {
return money(merchandiseTotals().merchandise + protection, ctx.moneyWithCurrencyFormat);
}
return money((state.cart?.total_price || 0) / 100, ctx.moneyWithCurrencyFormat);
}
function writeCartTotal() {
if (!CONFIG.CART_TOTAL_SELECTOR || isCheckoutLayout()) return;
if (hasProtectionInCart) return;
const text = cartTotalText();
if (!text) return;
each(`${CONFIG.CART_TOTAL_SELECTOR}, .cart__total-value`, (target) => {
const match = target.innerText.match(/^(.*?)\s*•\s*.+$/);
const next = match ? `${match[1]} • ${text}` : text;
if (target.innerHTML !== next) target.innerHTML = next;
});
}
function moneyToCents(value) {
if (value == null) return 0;
if (typeof value === 'number') return Math.round(value * 100);
const amount = typeof value === 'object' ? value.amount : value;
return Math.round(parseFloat(amount || 0) * 100);
}
function normalizeCart(cart) {
if (!cart) return null;
if (Array.isArray(cart.items)) return cart;
const rawLines = Array.isArray(cart.lines) ? cart.lines : cart.lines?.nodes;
if (!Array.isArray(rawLines)) return null;
const items = rawLines.map((line) => {
const merchandise = line.merchandise || {};
const product = merchandise.product || {};
const variantId = numericId(merchandise.id ?? line.merchandiseId);
return {
id: numericId(line.id) ?? variantId,
variant_id: variantId,
key: line.id != null ? String(line.id) : undefined,
quantity: line.quantity ?? 0,
final_line_price: moneyToCents(line.cost?.totalAmount ?? line.cost?.amount),
requires_shipping:
merchandise.requiresShipping ??
product.requiresShipping ??
line.requiresShipping ??
true,
product_type: product.productType || product.type || line.productType || '',
handle: product.handle || line.handle || '',
product_id: numericId(product.id),
};
});
return {
items,
item_count: cart.totalQuantity ?? items.reduce((n, i) => n + i.quantity, 0),
total_price: moneyToCents(cart.cost?.totalAmount ?? cart.cost?.amount),
requires_shipping: items.some((item) => item.requires_shipping),
};
}
async function mutateCart(action, variantId) {
try {
const isAdd = action === 'add';
const response = await fetch(
isAdd ? '/cart/add.js?shipcheck' : '/cart/change.js?shipcheck',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(
isAdd
? {
items: [{
id: String(variantId),
quantity: 1,
properties: {
_shipcheck: 'true',
_attributed_extension: 'cart',
},
}],
}
: { id: String(variantId), quantity: 0 },
),
},
);
return response.ok;
} catch {
return false;
}
}
async function fetchAjaxCart() {
try {
return await (await fetch('/cart.js?shipcheck')).json();
} catch {
return null;
}
}
function sync(cart) {
if (cart) {
const normalized = normalizeCart(cart);
if (!normalized) return;
state.cart = normalized;
}
syncProtectionFlag();
selectPlan();
ensureMounted();
paint();
}
let cartRefreshInFlight = false;
let cartRefreshQueued = false;
async function refreshCart() {
if (cartRefreshInFlight) {
cartRefreshQueued = true;
return;
}
cartRefreshInFlight = true;
try {
do {
cartRefreshQueued = false;
const cart = await fetchAjaxCart();
if (cart) {
sync(cart);
if (addInProgress) await reconcileProtectionLine();
}
} while (cartRefreshQueued);
} finally {
cartRefreshInFlight = false;
}
}
const scheduleCartRefresh = debounce(refreshCart, CART_UPDATE_DEBOUNCE_MS);
async function reconcileProtectionLine() {
const line = findProtectionLine();
if (line) {
const lineId = String(line.variant_id || line.id || '');
if (desiredVariantId && lineId !== desiredVariantId) {
await mutateCart('remove', lineId);
await mutateCart('add', desiredVariantId);
cartRefreshQueued = true;
}
return;
}
if (Date.now() - addStartedAt > 2000) endAddWindow();
}
function beginAddWindow(variantId) {
addInProgress = true;
desiredVariantId = String(variantId);
addStartedAt = Date.now();
localStorage.setItem(STORAGE_KEY_PROTECTION_ID, String(variantId));
localStorage.removeItem(STORAGE_KEY_PROTECTION_ID_LEGACY);
}
function endAddWindow() {
addInProgress = false;
desiredVariantId = null;
}
function onStorefrontCartEvent(event) {
usingStorefrontEvents = true;
stopCartRequestObserver();
const run = event.promise
? event.promise.then(() => refreshCart()).catch(() => scheduleCartRefresh())
: refreshCart();
Promise.resolve(run).catch(() => scheduleCartRefresh());
}
function subscribeStorefrontCartEvents() {
for (const name of STOREFRONT_CART_EVENTS) {
document.addEventListener(name, onStorefrontCartEvent);
}
}
let cartRequestObserver = null;
function startCartRequestObserver() {
if (cartRequestObserver || usingStorefrontEvents) return;
if (typeof PerformanceObserver === 'undefined') return;
cartRequestObserver = new PerformanceObserver((list) => {
if (usingStorefrontEvents) return;
for (const entry of list.getEntries()) {
if (!['xmlhttprequest', 'fetch'].includes(entry.initiatorType)) continue;
if (entry.duration <= 0) continue;
if (!CART_REQUEST_URL_RE.test(entry.name)) continue;
if (entry.name.includes('shipcheck')) continue;
scheduleCartRefresh();
}
});
cartRequestObserver.observe({ entryTypes: ['resource'] });
}
function stopCartRequestObserver() {
if (!cartRequestObserver) return;
cartRequestObserver.disconnect();
cartRequestObserver = null;
}
function paintPrice() {
const amount = protectionDisplayAmount();
each(`.${CLASSES.PRICE}`, (el) => {
el.setAttribute('translate', 'no');
el.textContent = amount;
});
}
function paintConsent() {
const html = (state.consent
? t(translation.userConsent.subtitles.on)
: t(translation.userConsent.subtitles.off)
).trim();
each(`.${CLASSES.SUBTITLE}`, (node) => { node.innerHTML = html; });
each(`.${CLASSES.SWITCH}`, (el) => {
el.setAttribute('aria-checked', state.consent ? 'true' : 'false');
});
if (CONFIG.IMAGE_GRAYSCALE) {
const value = state.consent ? '0' : '1';
each(`.${CLASSES.ICON}`, (icon) => { icon.style.filter = `grayscale(${value})`; });
}
}
function paint() {
paintPrice();
const hide = shouldHideExtension();
for (const root of extensionRoots) {
root.style.display = hide ? 'none' : '';
}
if (state.consent && (!isEnabled() || (hide && !CONFIG.AUTO_ACCEPT))) {
setConsent(false);
return;
}
writeCartTotal();
}
function setConsent(consent) {
const next = isEnabled() ? Boolean(consent) : false;
if (state.consent === next) return;
state.consent = next;
paintConsent();
if (isCheckoutLayout()) return;
writeCartTotal();
requestAnimationFrame(writeCartTotal);
}
function onConsentSwitchClick(event) {
event?.preventDefault?.();
event?.stopPropagation?.();
if (!isEnabled()) return;
setConsent(!state.consent);
}
function checkoutButtonMarkup() {
return ``;
}
function userConsentMarkup() {
const subtitle = (state.consent
? t(translation.userConsent.subtitles.on)
: t(translation.userConsent.subtitles.off)
).trim();
return ``;
}
function extensionMarkup() {
return isCheckoutLayout() ? checkoutButtonMarkup() : userConsentMarkup();
}
const ROOT_SELECTOR = `shipcheck-cart-widget[data-shipcheck-extension="true"], .${CLASSES.ROOT}[data-shipcheck-extension="true"]`;
const MOUNT_SELECTOR =
CHECKOUT_BUTTONS
;
const MOUNT_RETRY_MS = 200;
const BOOT_RETRY_MS = [100, 400, 1200];
function isRootIntact(root) {
return Boolean(
root?.querySelector?.(`.${CLASSES.SWITCH}, .${CLASSES.PRICE}, .asc-checkout-button-${TS}`),
);
}
function pruneRoots() {
for (const root of [...extensionRoots]) {
if (document.documentElement.contains(root)) {
if (isRootIntact(root)) continue;
extensionRoots.delete(root);
root.remove();
continue;
}
extensionRoots.delete(root);
if (isRootIntact(root) && !detachedRoots.includes(root)) detachedRoots.push(root);
}
while (detachedRoots.length > 4) detachedRoots.shift();
}
function stashRoot(root) {
if (!root) return;
if (document.documentElement.contains(root)) {
extensionRoots.add(root);
return;
}
extensionRoots.delete(root);
if (isRootIntact(root) && !detachedRoots.includes(root)) detachedRoots.push(root);
while (detachedRoots.length > 4) detachedRoots.shift();
}
function takeStashedRoot() {
while (detachedRoots.length) {
const root = detachedRoots.pop();
if (root && !document.documentElement.contains(root) && isRootIntact(root)) {
root.querySelectorAll(`.${CLASSES.PRICE}`).forEach((el) => {
el.textContent = '';
});
return root;
}
}
return null;
}
function findRootIn(container) {
if (!container) return null;
for (const root of extensionRoots) {
if (!container.contains(root)) continue;
if (isRootIntact(root)) return root;
extensionRoots.delete(root);
root.remove();
}
const found = container.querySelector?.(ROOT_SELECTOR);
if (!found) return null;
if (!isRootIntact(found)) {
found.remove();
return null;
}
extensionRoots.add(found);
const idx = detachedRoots.indexOf(found);
if (idx >= 0) detachedRoots.splice(idx, 1);
return found;
}
function createRoot(hide) {
const root = document.createElement('shipcheck-cart-widget');
root.className = CLASSES.ROOT;
root.setAttribute('data-shipcheck-extension', 'true');
root.innerHTML = extensionMarkup();
root.style.display = hide ? 'none' : '';
extensionRoots.add(root);
return root;
}
function insertAt(parent, node, index) {
const ref = parent.children[index];
if (ref) parent.insertBefore(node, ref);
else parent.appendChild(node);
}
function mountRoot(parent, beforeNode, index) {
const hide = shouldHideExtension();
const existing = findRootIn(parent);
if (existing) {
existing.style.display = hide ? 'none' : '';
return false;
}
const reused = takeStashedRoot();
const root = reused || createRoot(hide);
if (reused) {
root.style.display = hide ? 'none' : '';
extensionRoots.add(root);
}
if (index !== undefined) insertAt(parent, root, index);
else if (beforeNode && beforeNode.parentNode === parent) parent.insertBefore(root, beforeNode);
else parent.prepend(root);
return true;
}
function injectExtension() {
pruneRoots();
const shop = CONFIG.SHOP_PERMANENT_DOMAIN;
const index = INJECT_INDEX[shop];
let changed = false;
const seenParents = new Set();
for (const button of document.querySelectorAll(CHECKOUT_BUTTONS)) {
const parent = button.parentNode;
const grandparent = parent?.parentNode;
if (!parent || !grandparent || seenParents.has(grandparent)) continue;
seenParents.add(grandparent);
const did = index !== undefined
? mountRoot(grandparent, null, index)
: mountRoot(grandparent, parent);
if (did) changed = true;
}
return changed;
}
function needsMount() {
pruneRoots();
for (const root of extensionRoots) {
if (!document.documentElement.contains(root) || !isRootIntact(root)) return true;
}
const seenParents = new Set();
for (const button of document.querySelectorAll(CHECKOUT_BUTTONS)) {
const parent = button.parentNode;
const grandparent = parent?.parentNode;
if (!parent || !grandparent || seenParents.has(grandparent)) continue;
seenParents.add(grandparent);
if (!findRootIn(grandparent)) return true;
}
return false;
}
function ensureMounted() {
if (mounting) return false;
mounting = true;
let changed = false;
try {
changed = injectExtension();
attachCheckoutInterceptor();
if (changed) paintConsent();
} finally {
mounting = false;
}
return changed;
}
function remountAndPaint() {
ensureMounted();
paint();
if (needsMount()) scheduleMountRetry();
}
function scheduleMountRetry() {
if (mountRetryTimer) return;
mountRetryTimer = setTimeout(() => {
mountRetryTimer = null;
if (!needsMount()) return;
remountAndPaint();
}, MOUNT_RETRY_MS);
}
function captureElementState(el) {
const tag = el.tagName.toLowerCase();
const rect = el.getBoundingClientRect();
return {
tag,
content: tag === 'input' ? el.value : el.innerHTML,
disabled: el.disabled,
height: rect.height,
width: rect.width,
};
}
function setButtonLoading(el, loading, original) {
if (loading) {
if (el.hasAttribute('data-asc-loading')) return;
el.setAttribute('data-asc-loading', JSON.stringify({
content: original.tag === 'input' ? el.value : el.innerHTML,
styles: {
position: el.style.position,
height: el.style.height,
width: el.style.width,
minHeight: el.style.minHeight,
minWidth: el.style.minWidth,
pointerEvents: el.style.pointerEvents,
color: el.style.color,
},
}));
const computed = window.getComputedStyle(el).position;
el.style.position = computed === 'static' || !computed ? 'relative' : computed;
el.style.height = `${original.height}px`;
el.style.width = `${original.width}px`;
el.disabled = true;
if (original.tag === 'input') {
el.value = '';
el.style.color = 'transparent';
el.insertAdjacentHTML(
'afterend',
`${SPINNER_HTML}`,
);
} else {
el.style.pointerEvents = 'none';
el.innerHTML = `${SPINNER_HTML}`;
}
return;
}
const raw = el.getAttribute('data-asc-loading');
if (!raw) return;
const saved = JSON.parse(raw);
if (original.tag === 'input') {
el.value = saved.content;
const spinner = el.nextElementSibling;
if (spinner?.classList.contains('asc-spinner-wrapper')) spinner.remove();
} else {
el.innerHTML = saved.content;
}
el.disabled = original.disabled;
Object.assign(el.style, saved.styles);
el.removeAttribute('data-asc-loading');
}
function checkoutUrl(el) {
if (el?.tagName === 'A' && el.href) return el.href;
const dataHref = el?.getAttribute?.('data-href');
if (dataHref) {
try { return new URL(dataHref, location.origin).href; } catch { return dataHref; }
}
const root = window.Shopify?.routes?.root || '/';
return root.endsWith('/') ? `${root}checkout` : `${root}/checkout`;
}
async function addProtectionIfNeeded() {
if (!canAddProtection()) return false;
beginAddWindow(selectedPlan.id);
try {
let ok = await mutateCart('add', selectedPlan.id);
if (!ok) ok = await mutateCart('add', selectedPlan.id);
if (ok) hasProtectionInCart = true;
return ok;
} catch {
endAddWindow();
return false;
}
}
async function onCheckoutExtensionClick(event) {
if (!isEnabled() || checkoutBusy) return;
event.preventDefault();
const button = event.target?.closest?.('button, a, input') || event.target;
if (!button) return;
const original = captureElementState(button);
button.disabled = true;
checkoutBusy = true;
setButtonLoading(button, true, original);
try {
if (isCheckoutLayout()) await addProtectionIfNeeded();
} finally {
setButtonLoading(button, false, original);
checkoutBusy = false;
setTimeout(endAddWindow, DEBOUNCE_MS);
window.location.href = checkoutUrl(button);
}
}
function attachCheckoutInterceptor() {
if (!isEnabled() || interceptorBound) return;
interceptorBound = true;
let resumeClick = false;
document.addEventListener('click', async (event) => {
if (resumeClick) return;
if (interceptBusy) return;
if (!state.consent || !canAddProtection() || isCheckoutLayout()) return;
let control;
try {
control = event.target?.closest?.(CHECKOUT_BUTTONS);
} catch {
return;
}
if (!control) return;
if (control.closest(`.asc-checkout-button-${TS}`)) return;
event.preventDefault();
event.stopImmediatePropagation();
interceptBusy = true;
beginAddWindow(selectedPlan.id);
const original = captureElementState(control);
setButtonLoading(control, true, original);
let ok = await mutateCart('add', selectedPlan.id);
if (!ok) ok = await mutateCart('add', selectedPlan.id);
if (ok) hasProtectionInCart = true;
setButtonLoading(control, false, original);
interceptBusy = false;
setTimeout(endAddWindow, DEBOUNCE_MS);
const anchorHref = control.tagName === 'A' ? control.href : '';
resumeClick = true;
try {
control.click();
if (anchorHref) window.location.href = anchorHref;
} finally {
resumeClick = false;
}
}, true);
}
function mutationRemovedExtension(mutation) {
for (const node of mutation.removedNodes) {
if (node.nodeType !== 1) continue;
try {
if (node.matches?.(ROOT_SELECTOR)) {
stashRoot(node);
continue;
}
const nested = node.querySelector?.(ROOT_SELECTOR);
if (nested) stashRoot(nested);
} catch { }
for (const root of [...extensionRoots]) {
if (node === root || node.contains?.(root)) stashRoot(root);
}
}
}
function mutationAddedMountTarget(mutation) {
if (!MOUNT_SELECTOR) return false;
for (const node of mutation.addedNodes) {
if (node.nodeType !== 1) continue;
try {
if (node.matches?.(MOUNT_SELECTOR) || node.querySelector?.(MOUNT_SELECTOR)) return true;
} catch { }
}
return false;
}
function onThemeCartUpdate() {
queueMicrotask(() => {
if (needsMount()) remountAndPaint();
else paint();
scheduleCartRefresh();
});
}
const mutationObserver = new MutationObserver((mutations) => {
if (mounting) return;
let addedTarget = false;
for (const mutation of mutations) {
if (mutation.type !== 'childList') continue;
mutationRemovedExtension(mutation);
let insideOurs = false;
for (const root of extensionRoots) {
if (root === mutation.target || root.contains?.(mutation.target)) {
insideOurs = true;
break;
}
}
if (insideOurs) continue;
if (mutationAddedMountTarget(mutation)) addedTarget = true;
}
if (!needsMount()) {
if (addedTarget) attachCheckoutInterceptor();
return;
}
remountAndPaint();
});
window.shipcheck = {
...window.shipcheck,
update_consent_1790184857: onConsentSwitchClick,
on_checkout_click_1790184857: onCheckoutExtensionClick,
reset_protection_fn: resetProtectionAfterCheckoutReturn,
};
syncProtectionFlag();
selectPlan();
ensureMounted();
paintConsent();
paint();
mutationObserver.observe(document.body, { childList: true, subtree: true });
BOOT_RETRY_MS.forEach((ms) => {
setTimeout(() => {
if (needsMount()) remountAndPaint();
}, ms);
});
document.addEventListener('cart:update', onThemeCartUpdate);
subscribeStorefrontCartEvents();
startCartRequestObserver();
})();
})();