1<!doctype html> 2<html lang="es"> 3<head > 4 <meta charset="utf-8"/> 5<meta name="title" content="Bonito del Norte en conserva | Sabor y calidad"/> 6<meta name="description" content="Compra bonito en conserva de la mejor calidad. Sabor auténtico en cada lata, ideal para cualquier receta. ¡Haz tu pedido online!"/> 7<meta name="robots" content="INDEX, FOLLOW"/> 8<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/> 9<meta name="p:domain_verify" content="4b65f872394cb7cad307a07d303b76b4"/> 10<meta property="og:image" content="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/images/logo.png"/> 11<meta property="og:image:width" content="158"/> 12<meta property="og:image:height" content="70"/> 13<meta property="og:image:type" content="image/png"/> 14<title>Bonito del Norte en conserva | Sabor y calidad</title> 15<link rel="stylesheet" type="text/css" media="all" href="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/Netreviews_Avisverifies/css/netreviews.css" /> 16<link rel="stylesheet" type="text/css" media="all" href="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/Netreviews_Avisverifies/css/netreviews_category.css" /> 17<link rel="stylesheet" type="text/css" media="all" href="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/css/styles.css" /> 18<link rel="icon" type="image/x-icon" href="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/Magento_Theme/favicon.ico" /> 19<link rel="shortcut icon" type="image/x-icon" href="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/Magento_Theme/favicon.ico" /> 20<link rel="canonical" href="https://www.serrats.com/es_es/comprar-bonito-del-norte" /> 21<link rel="alternate" hreflang="es" href="https://www.serrats.com/es_es/comprar-bonito-del-norte" /> 22<link rel="alternate" hreflang="eu" href="https://www.serrats.com/es_eu/ipar-ekialdeko-hegaluzea-erosi" /> 23<link rel="alternate" hreflang="en" href="https://www.serrats.com/int_en/buy-white-tuna-albacore" /> 24<link rel="alternate" hreflang="fr" href="https://www.serrats.com/int_fr/acheter-thon-blanc" /> 25<link rel="alternate" hreflang="x-default" href="https://www.serrats.com/es_es/comprar-bonito-del-norte" /> 26
26<script type="text/javascript"> 27 function cookieBlocker() { 28 return { 29 isCookieNameMatch: function (cookieName, regexp) { 30 let regExpCookieName = regexp; 31 32 if (regExpCookieName instanceof RegExp) { 33 regExpCookieName = regexp.toString(); 34 regExpCookieName = regExpCookieName.slice(1, regExpCookieName.lastIndexOf('/')); 35 36 if (regExpCookieName.startsWith('^')) { 37 regExpCookieName = regExpCookieName.slice(1); 38 } 39 40 if (regExpCookieName.endsWith('$')) { 41 regExpCookieName = regExpCookieName.slice(0, -1); 42 } 43 } 44 45 let regExp = new RegExp(regExpCookieName, 'g'); 46 47 return regExp.test(cookieName); 48 }, 49 isDomainAllowed: function (domain) { 50 if (this.checkAcceptAll()) { 51 return true; 52 } 53 54 let whitelist = window.domains_whitelist || []; 55 if (whitelist.length) { 56 for (let allowedDomain of whitelist) { 57 if (domain.includes(allowedDomain)) { 58 return true; 59 } 60 } 61 } 62 63 return false; 64 }, 65 getCookieDescriptor: function (referenceWindow = null) { 66 let referenceObject = referenceWindow ? referenceWindow.Object : Object; 67 let cookieDescriptor = referenceObject.getOwnPropertyDescriptor(document, 'cookie') || 68 referenceObject.getOwnPropertyDescriptor(HTMLDocument.prototype, 'cookie'); 69 70 if (!cookieDescriptor) { 71 cookieDescriptor = {}; 72 cookieDescriptor.get = HTMLDocument.prototype.__lookupGetter__('cookie'); 73 cookieDescriptor.set = HTMLDocument.prototype.__lookupSetter__('cookie'); 74 } 75 76 return cookieDescriptor; 77 }, 78 shouldBypass: function () { 79 const bypassGetParameters = {"1":"_storyblok","2":"preview_token"}, 80 bypassUserAgents = {"1":"rocket-cypress"}; 81 82 const urlParams = new URLSearchParams(window.location.search); 83 for (const parameter in bypassGetParameters) { 84 if (urlParams.has(bypassGetParameters[parameter])) { 85 return true; 86 } 87 } 88 89 const currentUserAgent = window.navigator.userAgent; 90 for (const userAgent in bypassUserAgents) { 91 if (currentUserAgent == bypassUserAgents[userAgent]) { 92 return true; 93 } 94 } 95 96 return this.checkAcceptAll(); 97 }, 98 checkAcceptAll() { 99 let result = false;
100 try { 101 let cookieValue = document.cookie.match('(^|;) ?' + 'cookie-consent' + '=([^;]*)(;|$)'); 102 cookieValue = cookieValue ? cookieValue[2] : null; 103 cookieValue = cookieValue ? JSON.parse(decodeURIComponent(cookieValue)) : false; 104 result = (cookieValue && Object.values(cookieValue.consents).every(item => item)) ? true : false; 105 } catch (error) { 106 console.log(error); 107 result = false; 108 } 109 110 return result; 111 }, 112 init: function (referenceWindow = null) { 113 window.bypass_cookie_consent = this.shouldBypass(); 114 115 if (window.bypass_cookie_consent) { 116 return; 117 } 118 119 const self = this; 120 let cookieDescriptor = self.getCookieDescriptor(referenceWindow); 121 let referenceObject = referenceWindow ? referenceWindow.Object : Object; 122 let cookies_whitelist = [{"regexp":"cookie-consent","path":"\/","domain":null},{"regexp":"frontend","path":"\/","domain":null},{"regexp":"cookienotice","path":"\/","domain":null},{"regexp":"form_key","path":"\/","domain":null},{"regexp":"\/mage-.+\/","path":"\/","domain":null},{"regexp":"product_data_storage","path":"\/","domain":null},{"regexp":"\/recently_.+\/","path":"\/","domain":null},{"regexp":"PHPSESSID","path":"\/","domain":null},{"regexp":"add_to_cart","path":"\/","domain":null},{"regexp":"guest-view","path":"\/","domain":null},{"regexp":"login_redirect","path":"\/","domain":null},{"regexp":"remove_from_cart","path":"\/","domain":null},{"regexp":"stf","path":"\/","domain":null},{"regexp":"X-Magento-Vary","path":"\/","domain":null},{"regexp":"private_content_version","path":"\/","domain":null},{"regexp":"section_data_ids","path":"\/","domain":null},{"regexp":"store","path":"\/","domain":null},{"regexp":"user_allowed_save_cookie","path":"\/","domain":null},{"regexp":"\/_ga|_gid|_gat|_gac.+|AMP_TOKEN|__utm.+\/","path":"\/","domain":null},{"regexp":"OGPC","path":"\/","domain":null},{"regexp":"CGIC","path":"\/","domain":null},{"regexp":"DV","path":"\/","domain":null},{"regexp":"SIDCC","path":"\/","domain":null},{"regexp":"rocket_social_login_initial_link","path":"\/","domain":null},{"regexp":"outdated_browser_popup","path":"\/","domain":null},{"regexp":"geoip_store","path":"\/","domain":null},{"regexp":"country_code","path":"\/","domain":null},{"regexp":"datalayer-cache-customer","path":"\/","domain":null},{"regexp":"cookie-consent","path":"\/","domain":null},{"regexp":"PHPSESSID","path":"\/","domain":null},{"regexp":"frontend","path":"\/","domain":null},{"regexp":"cookienotice","path":"\/","domain":null},{"regexp":"form_key","path":"\/","domain":null},{"regexp":"\/mage-.+\/","path":"\/","domain":null},{"regexp":"\/recently_.+\/","path":"\/","domain":null},{"regexp":"product_data_storage","path":"\/","domain":null},{"regexp":"add_to_cart","path":"\/","domain":null},{"regexp":"remove_from_cart","path":"\/","domain":null},{"regexp":"guest-view","path":"\/","domain":null},{"regexp":"login_redirect","path":"\/","domain":null},{"regexp":"stf","path":"\/","domain":null},{"regexp":"X-Magento-Vary","path":"\/","domain":null},{"regexp":"private_content_version","path":"\/","domain":null},{"regexp":"section_data_ids","path":"\/","domain":null},{"regexp":"store","path":"\/","domain":null},{"regexp":"user_allowed_save_cookie","path":"\/","domain":null},{"regexp":"OGPC","path":"\/","domain":null},{"regexp":"CGIC","path":"\/","domain":null},{"regexp":"SIDCC","path":"\/","domain":null},{"regexp":"DV","path":"\/","domain":null},{"regexp":"rocket_social_login_initial_link","path":"\/","domain":null},{"regexp":"geoip_store","path":"\/","domain":null},{"regexp":"ampromo-popup","path":"\/","domain":null},{"regexp":"outdated_browser_popup","path":"\/","domain":null}] 123 referenceObject.defineProperty(document, 'cookie', { 124 configurable: true, 125 get: function () { 126 return cookieDescriptor.get.apply(document); 127 }, 128 set: function () { 129 let whitelist = window.cookies_whitelist || cookies_whitelist; 130 let cookieSetArguments = arguments; 131 132 if (whitelist.length) { 133 let cookieName = arguments[0].split('=')[0]; 134 Array.prototype.forEach.call(whitelist, function (whitelistItem) { 135 if (self.isCookieNameMatch(cookieName, whitelistItem.regexp)) { 136 cookieDescriptor.set.apply(document, cookieSetArguments); 137 } 138 }); 139 } 140 } 141 }); 142 143 let originalAppendChild = Element.prototype.appendChild; 144 Element.prototype.appendChild = function() { 145 return processInjectingTag.call(this, originalAppendChild, ...arguments); 146 }; 147 148 let originalInsertBefore = Element.prototype.insertBefore; 149 Element.prototype.insertBefore = function () { 150 return processInjectingTag.call(this, originalInsertBefore, ...arguments); 151 }; 152 153 function processInjectingTag(method, ...args) { 154 const injectingTag = args[0]; 155 156 if (!injectingTag) { 157 return; 158 } 159 160 const {nodeName, src} = injectingTag; 161 const isScript = nodeName === 'SCRIPT'; 162 163 if (!src || !isScript || (isScript && self.isDomainAllowed(src))) { 164 return method.apply(this, args); 165 } 166 167 handleRejectedScript(src); 168 } 169 170 function handleRejectedScript(src) { 171 console.log('Script is not allowed: ' + src); 172 window.scripts_rejected = window.scripts_rejected || []; 173 174 if (!window.scripts_rejected.includes(src)) { 175 window.scripts_rejected.push(src); 176 } 177 } 178 } 179 } 180 } 181 182 cookieBlocker().init();//catches cookies set before DOM loaded 183 document.addEventListener('DOMContentLoaded', function () {//catches cookies set after DOM loaded 184 cookieBlocker().init(window); 185 }, false); 186</script>
186 187
188<script type="text/javascript"> 189 const privateContentIsLoaded = new Promise((resolve) => { 190 window.addEventListener('private-content-loaded', event => { 191 const dataObject = event.detail.data['rocket_datalayer'] || {}; 192 let customerData = {}; 193 194 if (dataObject['customer'] && Object.keys(dataObject['customer']).length) { 195 customerData = dataObject['customer']; 196 } 197 198 return resolve(customerData); 199 }); 200 }); 201 202 const datalayerIsReady = new Promise((resolve) => { 203 window.addEventListener('datalayer-ready', () => { 204 const pageData = {"event":"gtm.datalayer","page_type":"category","page_cat1":"comprar-bonito-del-norte"}; 205 206 return resolve(pageData); 207 }); 208 }); 209 210 const allPromises = [privateContentIsLoaded, datalayerIsReady]; 211 212 try { 213 Promise.all(allPromises).then(sendDataGTM) 214 } catch (e) { 215 //Promise.all is not supported browser 216 PromiseAllPolyfill(allPromises).then(sendDataGTM); 217 } 218 219 function sendDataGTM(result) { 220 const customerEvent = result.shift(); 221 const pageData = result.shift(); 222 223 if (!customerEvent || !pageData) { 224 return; 225 } 226 227 const dataGTM = Object.assign(pageData); 228 const userDataGTM = Object.assign(customerEvent) 229 230 window.dispatchEvent( 231 new CustomEvent('datalayer-event', 232 { 233 detail: userDataGTM 234 } 235 ) 236 ); 237 238 window.dispatchEvent( 239 new CustomEvent('datalayer-event', 240 { 241 detail: dataGTM 242 } 243 ) 244 ); 245 } 246 247 function PromiseAllPolyfill(promises) { 248 const results = []; 249 let completed = 0; 250 251 return new Promise((resolve, reject) => { 252 promises.forEach((value, index) => { 253 Promise.resolve(value) 254 .then((res) => { 255 results[index] = res; 256 completed++; 257 if (completed === promises.length) { 258 resolve(results); 259 } 260 }).catch((err) => reject(err)); 261 }); 262 }); 263 } 264</script>
vendor: 1 bytes, line 264
264
265<script> 266(function () { 267 'use strict'; 268 269 var STORAGE_KEY = 'atmos_attribution'; 270 var UTM_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term']; 271 var CLICK_IDS = ['fbclid', 'ttclid', 'gclid', 'msclkid']; 272 var ALL_PARAMS = UTM_PARAMS.concat(CLICK_IDS); 273 274 (function captureAttribution() { 275 try { 276 var searchParams = new URLSearchParams(window.location.search); 277 var newAttribution = {}; 278 var hasNewParams = false; 279 280 ALL_PARAMS.forEach(function (param) { 281 if (searchParams.has(param)) { 282 newAttribution[param] = searchParams.get(param); 283 hasNewParams = true; 284 } 285 }); 286 287 if (!hasNewParams) { 288 return; 289 } 290 291 newAttribution.landing_url = window.location.href; 292 newAttribution.captured_at = Date.now(); 293 294 sessionStorage.setItem(STORAGE_KEY, JSON.stringify(newAttribution)); 295 } catch (e) { console.warn('[UtmAttribution] capture failed', e); } 296 }()); 297 298 // Wrap sendEvent as early as possible so no events are missed before load 299 window.addEventListener('datalayer-ready', function onDatalayerReady() { 300 try { 301 var _orig = window.sendEvent; 302 if (typeof _orig === 'function') { 303 window.sendEvent = function (event) { 304 try { 305 if (event && event.event) { 306 var raw = sessionStorage.getItem(STORAGE_KEY); 307 if (raw) { 308 var attribution = JSON.parse(raw); 309 Object.keys(attribution).forEach(function (key) { 310 if (!(key in event)) { 311 event[key] = attribution[key]; 312 } 313 }); 314 } 315 } 316 } catch (e) { console.warn('[UtmAttribution] sendEvent enrichment failed', e); } 317 return _orig(event); 318 }; 319 } 320 } catch (e) { console.warn('[UtmAttribution] sendEvent wrap failed', e); } 321 }, { once: true }); 322}()); 323</script>
vendor: 1 bytes, line 323
323
324<script type="text/javascript"> 325 window.dataLayer = window.dataLayer || []; 326 window.addEventListener("load", () => { 327 (function (w, d, s, l, i) { 328 w[l] = w[l] || []; 329 w[l].push({'gtm.start': new Date().getTime(), event: 'gtm.js'}); 330 var f = d.getElementsByTagName(s)[0], 331 j = d.createElement(s), 332 dl = l != 'dataLayer' ? '&l=' + l : ''; 333 j.async = true; 334 j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; 335 336 // GTM container has been downloaded from Googleâs servers 337 // It will dispatch new browser event named "datalayer-ready" 338 j.addEventListener('load', function () { 339 window.dispatchEvent( 340 new CustomEvent("datalayer-ready", {}) 341 ); 342 }); 343 344 f.parentNode.insertBefore(j, f); 345 })(window, document, 'script', 'dataLayer', 'GTM-M58G7NBG'); 346 }); 347</script>
vendor: 1 bytes, line 347
347
348<script type="text/javascript"> 349 if (typeof window.queueMicrotask !== 'function') { 350 window.queueMicrotask = function(callback) { 351 Promise.resolve() 352 .then(callback) 353 .catch(e => setTimeout(() => { 354 throw e; 355 })); 356 }; 357 } 358</script>
vendor: 1 bytes, line 358
358
359<script type="text/javascript"> 360 if (!Array.prototype.flatMap) { 361 Object.defineProperty(Array.prototype, 'flatMap', { 362 configurable: true, 363 value: function flatMap (callback) { 364 return Array.prototype.map.apply(this, arguments).flat(); 365 }, 366 writable: true 367 }); 368 } 369</script>
vendor: 1 bytes, line 369
369
vendor: 725 bytes, lines 370-390
370<script type="text/javascript"> 371 if (!Array.prototype.flat) { 372 Object.defineProperty(Array.prototype, 'flat', { 373 configurable: true, 374 value: function flat () { 375 var depth = isNaN(arguments[0]) ? 1 : Number(arguments[0]); 376 377 return depth ? Array.prototype.reduce.call(this, function (acc, cur) { 378 if (Array.isArray(cur)) { 379 acc.push.apply(acc, flat.call(cur, depth - 1)); 380 } else { 381 acc.push(cur); 382 } 383 384 return acc; 385 }, []) : Array.prototype.slice.call(this); 386 }, 387 writable: true 388 }); 389 } 390</script>
vendor: 1 bytes, line 390
390
391<script> 392 var BASE_URL = 'https://www.serrats.com/es_es/'; 393 var THEME_PATH = 'https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES'; 394 var COOKIE_CONFIG = { 395 "expires": null, 396 "path": "\u002F", 397 "domain": ".www.serrats.com", 398 "secure": true, 399 "lifetime": "604800", 400 "cookie_restriction_enabled": true }; 401 var CURRENT_STORE_CODE = 'es_es'; 402 var CURRENT_WEBSITE_ID = '1'; 403 404 window.hyva = window.hyva || {} 405 406 window.cookie_consent_groups = window.cookie_consent_groups || {} 407 window.cookie_consent_groups['necessary'] = true; 408 409 window.cookie_consent_config = window.cookie_consent_config || {}; 410 window.cookie_consent_config['necessary'] = [].concat( 411 window.cookie_consent_config['necessary'] || [], 412 [ 413 'user_allowed_save_cookie', 414 'form_key', 415 'mage-messages', 416 'private_content_version', 417 'mage-cache-sessid', 418 'last_visited_store', 419 'section_data_ids' 420 ] 421 ); 422</script>
vendor: 1 bytes, line 422
422
423<script> 424 'use strict'; 425 (function( hyva, undefined ) { 426 427 function lifetimeToExpires(options, defaults) { 428 429 const lifetime = options.lifetime || defaults.lifetime; 430 431 if (lifetime) { 432 const date = new Date; 433 date.setTime(date.getTime() + lifetime * 1000); 434 return date; 435 } 436 437 return null; 438 } 439 440 function generateRandomString() { 441 442 const allowedCharacters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 443 length = 16; 444 445 let formKey = '', 446 charactersLength = allowedCharacters.length; 447 448 for (let i = 0; i < length; i++) { 449 formKey += allowedCharacters[Math.round(Math.random() * (charactersLength - 1))] 450 } 451 452 return formKey; 453 } 454 455 const sessionCookieMarker = {noLifetime: true} 456 457 const cookieTempStorage = {}; 458 459 const internalCookie = { 460 get(name) { 461 const v = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)'); 462 return v ? v[2] : null; 463 }, 464 set(name, value, days, skipSetDomain) { 465 let expires, 466 path, 467 domain, 468 secure, 469 samesite; 470 471 const defaultCookieConfig = { 472 expires: null, 473 path: '/', 474 domain: null, 475 secure: false, 476 lifetime: null, 477 samesite: 'lax' 478 }; 479 480 const cookieConfig = window.COOKIE_CONFIG || {}; 481 482 expires = days && days !== sessionCookieMarker 483 ? lifetimeToExpires({lifetime: 24 * 60 * 60 * days, expires: null}, defaultCookieConfig) 484 : lifetimeToExpires(window.COOKIE_CONFIG, defaultCookieConfig) || defaultCookieConfig.expires; 485 486 path = cookieConfig.path || defaultCookieConfig.path; 487 domain = !skipSetDomain && (cookieConfig.domain || defaultCookieConfig.domain); 488 secure = cookieConfig.secure || defaultCookieConfig.secure; 489 samesite = cookieConfig.samesite || defaultCookieConfig.samesite; 490 491 document.cookie = name + "=" + encodeURIComponent(value) + 492 (expires && days !== sessionCookieMarker ? '; expires=' + expires.toGMTString() : '') + 493 (path ? '; path=' + path : '') + 494 (domain ? '; domain=' + domain : '') + 495 (secure ? '; secure' : '') + 496 (samesite ? '; samesite=' + samesite : 'lax'); 497 }, 498 isWebsiteAllowedToSaveCookie() { 499 const allowedCookies = this.get('user_allowed_save_cookie'); 500 if (allowedCookies) { 501 const allowedWebsites = JSON.parse(unescape(allowedCookies)); 502 503 return allowedWebsites[CURRENT_WEBSITE_ID] === 1; 504 } 505 return false; 506 }, 507 getGroupByCookieName(name) { 508 const cookieConsentConfig = window.cookie_consent_config || {}; 509 let group = null; 510 for (let prop in cookieConsentConfig) { 511 if (!cookieConsentConfig.hasOwnProperty(prop)) continue; 512 if (cookieConsentConfig[prop].includes(name)) { 513 group = prop; 514 break; 515 } 516 } 517 return group; 518 }, 519 isCookieAllowed(name) { 520 const cookieGroup = this.getGroupByCookieName(name); 521 return cookieGroup 522 ? window.cookie_consent_groups[cookieGroup] 523 : this.isWebsiteAllowedToSaveCookie(); 524 }, 525 saveTempStorageCookies() { 526 for (const [name, data] of Object.entries(cookieTempStorage)) { 527 if (this.isCookieAllowed(name)) { 528 this.set(name, data['value'], data['days'], data['skipSetDomain']); 529 delete cookieTempStorage[name]; 530 } 531 } 532 } 533 }; 534 535 hyva.getCookie = (name) => { 536 const cookieConfig = window.COOKIE_CONFIG || {}; 537 538 if (cookieConfig.cookie_restriction_enabled && ! internalCookie.isCookieAllowed(name)) { 539 return cookieTempStorage[name] ? cookieTempStorage[name]['value'] : null; 540 } 541 542 return internalCookie.get(name); 543 } 544 545 hyva.setCookie = (name, value, days, skipSetDomain) => { 546 const cookieConfig = window.COOKIE_CONFIG || {}; 547 548 if (cookieConfig.cookie_restriction_enabled && ! internalCookie.isCookieAllowed(name)) { 549 cookieTempStorage[name] = {value, days, skipSetDomain}; 550 return; 551 } 552 return internalCookie.set(name, value, days, skipSetDomain); 553 } 554 555 556 hyva.setSessionCookie = (name, value, skipSetDomain) => { 557 return hyva.setCookie(name, value, sessionCookieMarker, skipSetDomain) 558 } 559 560 hyva.getBrowserStorage = () => { 561 const browserStorage = window.localStorage || window.sessionStorage; 562 if (!browserStorage) { 563 console.warn('Browser Storage is unavailable'); 564 return false;
565 } 566 try { 567 browserStorage.setItem('storage_test', '1'); 568 browserStorage.removeItem('storage_test'); 569 } catch (error) { 570 console.warn('Browser Storage is not accessible', error); 571 return false; 572 } 573 return browserStorage; 574 } 575 576 hyva.postForm = (postParams) => { 577 const form = document.createElement("form"); 578 579 let data = postParams.data; 580 581 if (! postParams.skipUenc && ! data.uenc) { 582 data.uenc = btoa(window.location.href); 583 } 584 form.method = "POST"; 585 form.action = postParams.action; 586 587 Object.keys(postParams.data).map(key => { 588 const field = document.createElement("input"); 589 field.type = 'hidden' 590 field.value = postParams.data[key]; 591 field.name = key; 592 form.appendChild(field); 593 }); 594 595 const form_key = document.createElement("input"); 596 form_key.type = 'hidden'; 597 form_key.value = hyva.getFormKey(); 598 form_key.name="form_key"; 599 form.appendChild(form_key); 600 601 document.body.appendChild(form); 602 603 form.submit(); 604 } 605 606 hyva.getFormKey = function () { 607 let formKey = hyva.getCookie('form_key'); 608 609 if (!formKey) { 610 formKey = generateRandomString(); 611 hyva.setCookie('form_key', formKey); 612 } 613 614 return formKey; 615 } 616 617 hyva.formatPrice = (value, showSign, options = {}) => { 618 const groupSeparator = options.groupSeparator; 619 const decimalSeparator = options.decimalSeparator 620 delete options.groupSeparator; 621 delete options.decimalSeparator; 622 const formatter = new Intl.NumberFormat( 623 'es\u002DES', 624 Object.assign({ 625 style: 'currency', 626 currency: 'EUR', 627 signDisplay: showSign ? 'always' : 'auto' 628 }, options) 629 ); 630 return (typeof Intl.NumberFormat.prototype.formatToParts === 'function') ? 631 formatter.formatToParts(value).map(({type, value}) => { 632 switch (type) { 633 case 'currency': 634 return '\u20AC' || value; 635 case 'minusSign': 636 return '- '; 637 case 'plusSign': 638 return '+ '; 639 case 'group': 640 return groupSeparator !== undefined ? groupSeparator : value; 641 case 'decimal': 642 return decimalSeparator !== undefined ? decimalSeparator : value; 643 default : 644 return value; 645 } 646 }).reduce((string, part) => string + part) : 647 formatter.format(value); 648 } 649 650 const formatStr = function (str, nStart) { 651 const args = Array.from(arguments).slice(2); 652 653 return str.replace(/(%+)([0-9]+)/g, (m, p, n) => { 654 const idx = parseInt(n) - nStart; 655 656 if (args[idx] === null || args[idx] === void 0) { 657 return m; 658 } 659 return p.length % 2 660 ? p.slice(0, -1).replace('%%', '%') + args[idx] 661 : p.replace('%%', '%') + n; 662 }) 663 } 664 665 hyva.str = function (string) { 666 const args = Array.from(arguments); 667 args.splice(1, 0, 1); 668 669 return formatStr.apply(undefined, args); 670 } 671 672 hyva.strf = function () { 673 const args = Array.from(arguments); 674 args.splice(1, 0, 0); 675 676 return formatStr.apply(undefined, args); 677 } 678 679 /** 680 * Take a html string as `content` parameter and 681 * extract an element from the DOM to replace in 682 * the current page under the same selector, 683 * defined by `targetSelector` 684 */ 685 hyva.replaceDomElement = (targetSelector, content) => { 686 // Parse the content and extract the DOM node using the `targetSelector` 687 const parser = new DOMParser(); 688 const doc = parser.parseFromString(content, 'text/html');
689 const contentNode = doc.querySelector(targetSelector); 690 691 // Bail if content or target can't be found 692 if (!contentNode || !document.querySelector(targetSelector)) { 693 return; 694 } 695 696 hyva.activateScripts(contentNode); 697 698 // Replace the old DOM node with the new content 699 document.querySelector(targetSelector).replaceWith(contentNode); 700 701 // Reload customerSectionData and display cookie-messages if present 702 window.dispatchEvent(new CustomEvent("reload-customer-section-data")); 703 hyva.initMessages(); 704 } 705 706 hyva.removeScripts = (contentNode) => { 707 const scripts = contentNode.getElementsByTagName('script'); 708 for (let i = 0; i < scripts.length; i++) { 709 scripts[i].parentNode.removeChild(scripts[i]); 710 } 711 const templates = contentNode.getElementsByTagName('template'); 712 for (let i = 0; i < templates.length; i++) { 713 const container = document.createElement('div'); 714 container.innerHTML = templates[i].innerHTML; 715 hyva.removeScripts(container); 716 templates[i].innerHTML = container.innerHTML; 717 } 718 } 719 720 hyva.activateScripts = (contentNode) => { 721 // Create new array from HTMLCollection to avoid mutation of collection while manipulating the DOM. 722 const scripts = Array.from(contentNode.getElementsByTagName('script')); 723 724 // Iterate over all script tags to duplicate+inject each into the head 725 for (const original of scripts) { 726 const script = document.createElement('script'); 727 original.type && (script.type = original.type); 728 script.innerHTML = original.innerHTML; 729 730 // Remove the original (non-executing) script from the contentNode 731 original.parentNode.removeChild(original) 732 733 // Add script to head 734 document.head.appendChild(script); 735 } 736 737 return contentNode; 738 } 739 740 const replace = {['+']: '-', ['/']: '_', ['=']: ','}; 741 hyva.getUenc = () => btoa(window.location.href).replace(/[+/=]/g, match => replace[match]); 742 743 let currentTrap; 744 745 const focusableElements = (rootElement) => { 746 const selector = 'button, [href], input, select, textarea, details, [tabindex]:not([tabindex="-1"]'; 747 return Array.from(rootElement.querySelectorAll(selector)) 748 .filter(el => { 749 return el.style.display !== 'none' 750 && !el.disabled 751 && el.tabIndex !== -1 752 && (el.offsetWidth || el.offsetHeight || el.getClientRects().length) 753 }) 754 } 755 756 const focusTrap = (e) => { 757 const isTabPressed = e.key === 'Tab' || e.keyCode === 9; 758 if (!isTabPressed) return; 759 760 const focusable = focusableElements(currentTrap) 761 const firstFocusableElement = focusable[0] 762 const lastFocusableElement = focusable[focusable.length - 1] 763 764 e.shiftKey 765 ? document.activeElement === firstFocusableElement && (lastFocusableElement.focus(), e.preventDefault()) 766 : document.activeElement === lastFocusableElement && (firstFocusableElement.focus(), e.preventDefault()) 767 }; 768 769 hyva.releaseFocus = (rootElement) => { 770 if (currentTrap && (!rootElement || rootElement === currentTrap)) { 771 currentTrap.removeEventListener('keydown', focusTrap) 772 currentTrap = null 773 } 774 } 775 hyva.trapFocus = (rootElement) => { 776 if (!rootElement) return; 777 hyva.releaseFocus() 778 currentTrap = rootElement 779 rootElement.addEventListener('keydown', focusTrap) 780 const firstElement = focusableElements(rootElement)[0] 781 firstElement && firstElement.focus() 782 } 783 784 hyva.safeParseNumber = (rawValue) => { 785 const number = rawValue ? parseFloat(rawValue) : null; 786 787 return Array.isArray(number) || isNaN(number) ? rawValue : number; 788 } 789 790 const toCamelCase = s => s.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(''); 791 hyva.createBooleanObject = (name, value = false, additionalMethods = {}) => { 792 793 const camelCase = toCamelCase(name);
794 const key = '__hyva_bool_' + name 795 796 return new Proxy(Object.assign( 797 additionalMethods, 798 { 799 [key]: !!value, 800 [name]() {return !!this[key]}, 801 ['!' + name]() {return !this[key]}, // @deprecated This does not work with non-CSP Alpine 802 ['not' + camelCase]() {return !this[key]}, 803 ['toggle' + camelCase]() {this[key] = !this[key]}, 804 [`set${camelCase}True`]() {this[key] = true}, 805 [`set${camelCase}False`]() {this[key] = false}, 806 } 807 ), { 808 set(target, prop, value) { 809 return prop === name 810 ? (target[key] = !!value) 811 : Reflect.set(...arguments); 812 } 813 }) 814 } 815 816 hyva.alpineInitialized = (fn) => window.addEventListener('alpine:initialized', fn, {once: true}) 817 window.addEventListener('alpine:init', () => Alpine.data('{}', () => ({})), {once: true}); 818 window.addEventListener('user-allowed-save-cookie', () => internalCookie.saveTempStorageCookies()) 819 820 }( window.hyva = window.hyva || {} )); 821</script>
vendor: 1 bytes, line 821
821
822<script> 823 if (!window.IntersectionObserver) { 824 window.IntersectionObserver = function (callback) { 825 this.observe = el => el && callback(this.takeRecords()); 826 this.takeRecords = () => [{isIntersecting: true, intersectionRatio: 1}]; 827 this.disconnect = () => {}; 828 this.unobserve = () => {}; 829 } 830 } 831</script>
831 832<style data-jit-css data-liveview-style-type="cms_block" data-liveview-style-id="39">.cmsb39-mx-auto { 833margin-left: auto; 834margin-right: auto 835} 836.cmsb39-flex { 837display: flex 838} 839.cmsb39-h-\[38px\] { 840height: 38px 841} 842.cmsb39-max-w-7xl { 843max-width: 80rem 844} 845.cmsb39-items-center { 846align-items: center 847} 848.cmsb39-justify-center { 849justify-content: center 850} 851.cmsb39-overflow-hidden { 852overflow: hidden 853} 854.cmsb39-border-b { 855border-bottom-width: 1px 856} 857.cmsb39-border-white\/10 { 858border-color: rgb(255 255 255 / 0.1) 859} 860.cmsb39-bg-\[\#1A1919\] { 861--tw-bg-opacity: 1; 862background-color: rgb(26 25 25 / var(--tw-bg-opacity)) 863} 864.cmsb39-px-4 { 865padding-left: 1rem; 866padding-right: 1rem 867} 868.cmsb39-pb-0 { 869padding-bottom: 0px 870} 871.cmsb39-text-center { 872text-align: center 873} 874.cmsb39-font-sans { 875font-family: "Moderat", ui-sans-serif, sans-serif 876} 877.cmsb39-text-\[11px\] { 878font-size: 11px 879} 880.cmsb39-font-bold { 881font-weight: 700 882} 883.cmsb39-font-normal { 884font-weight: 400 885} 886.cmsb39-leading-tight { 887line-height: 1.25 888} 889.cmsb39-tracking-wide { 890letter-spacing: 0.025em 891} 892.cmsb39-text-white { 893--tw-text-opacity: 1; 894color: rgb(255 255 255 / var(--tw-text-opacity)) 895} 896@media (min-width: 640px) { 897.cmsb39-sm\:px-6 { 898padding-left: 1.5rem; 899padding-right: 1.5rem 900} 901.cmsb39-sm\:text-xs { 902font-size: 0.75rem; 903line-height: 1.255 904} 905} 906@media (min-width: 768px) { 907.cmsb39-md\:text-sm { 908font-size: 0.875rem; 909line-height: 1.255 910} 911} 912@media (min-width: 1024px) { 913.cmsb39-lg\:px-8 { 914padding-left: 2rem; 915padding-right: 2rem 916} 917}</style><style data-jit-css data-liveview-style-type="cms_block" data-liveview-style-id="17">.cmsb17-mx-auto { 918margin-left: auto; 919margin-right: auto 920} 921.cmsb17-mb-12 { 922margin-bottom: 3rem 923} 924.cmsb17-mt-6 { 925margin-top: 1.5rem 926} 927.cmsb17-flex { 928display: flex 929} 930.cmsb17-table { 931display: table 932} 933.cmsb17-w-full { 934width: 100% 935} 936.cmsb17-max-w-2xl { 937max-width: 42rem 938} 939.cmsb17-max-w-7xl { 940max-width: 80rem 941} 942.cmsb17-flex-shrink-0 { 943flex-shrink: 0 944} 945.cmsb17-origin-top { 946transform-origin: top 947} 948.cmsb17-rotate-180 { 949--tw-rotate: 180deg; 950transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) 951} 952.cmsb17-scale-y-100 { 953--tw-scale-y: 1; 954transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) 955} 956.cmsb17-scale-y-95 { 957--tw-scale-y: .cmsb17-95; 958transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) 959} 960.cmsb17-transform { 961transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) 962} 963.cmsb17-items-center { 964align-items: center 965} 966.cmsb17-justify-between { 967justify-content: space-between 968} 969.cmsb17-space-y-4 > :not([hidden]) ~ :not([hidden]) { 970--tw-space-y-reverse: 0; 971margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); 972margin-bottom: calc(1rem * var(--tw-space-y-reverse)) 973} 974.cmsb17-divide-y > :not([hidden]) ~ :not([hidden]) { 975--tw-divide-y-reverse: 0; 976border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); 977border-bottom-width: calc(1px * var(--tw-divide-y-reverse)) 978} 979.cmsb17-divide-gray-200 > :not([hidden]) ~ :not([hidden]) { 980--tw-divide-opacity: 1; 981border-color: rgb(229 231 235 / var(--tw-divide-opacity)) 982} 983.cmsb17-border-b { 984border-bottom-width: 1px 985} 986.cmsb17-border-t { 987border-top-width: 1px 988} 989.cmsb17-border-gray-200 { 990--tw-border-opacity: 1; 991border-color: rgb(229 231 235 / var(--tw-border-opacity)) 992} 993.cmsb17-bg-white { 994--tw-bg-opacity: 1; 995background-color: rgb(255 255 255 / var(--tw-bg-opacity)) 996} 997.cmsb17-px-4 { 998padding-left: 1rem; 999padding-right: 1rem 1000} 1001.cmsb17-py-12 { 1002padding-top: 3rem; 1003padding-bottom: 3rem 1004} 1005.cmsb17-py-4 { 1006padding-top: 1rem; 1007padding-bottom: 1rem 1008} 1009.cmsb17-pr-4 { 1010padding-right: 1rem 1011} 1012.cmsb17-text-left { 1013text-align: left 1014} 1015.cmsb17-text-center { 1016text-align: center 1017} 1018.cmsb17-text-4xl { 1019font-size: 1.625rem; 1020line-height: 1.255 1021} 1022.cmsb17-text-md { 1023font-size: 1rem; 1024line-height: 1.286 1025} 1026.cmsb17-text-sm { 1027font-size: 0.875rem; 1028line-height: 1.255 1029} 1030.cmsb17-font-bold {
1031font-weight: 700 1032} 1033.cmsb17-font-extralight { 1034font-weight: 200 1035} 1036.cmsb17-font-medium { 1037font-weight: 500 1038} 1039.cmsb17-uppercase { 1040text-transform: uppercase 1041} 1042.cmsb17-italic { 1043font-style: italic 1044} 1045.cmsb17-leading-tight { 1046line-height: 1.25 1047} 1048.cmsb17-tracking-wide { 1049letter-spacing: 0.025em 1050} 1051.cmsb17-opacity-0 { 1052opacity: 0 1053} 1054.cmsb17-opacity-100 { 1055opacity: 1 1056} 1057.cmsb17-transition { 1058transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter; 1059transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 1060transition-duration: 150ms 1061} 1062.cmsb17-transition-transform { 1063transition-property: transform; 1064transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 1065transition-duration: 150ms 1066} 1067.cmsb17-duration-300 { 1068transition-duration: 300ms 1069} 1070.cmsb17-ease-out { 1071transition-timing-function: cubic-bezier(0, 0, 0.2, 1) 1072} 1073.cmsb17-focus\:outline-none:focus { 1074outline: 2px solid transparent; 1075outline-offset: 2px 1076} 1077@media (min-width: 768px) { 1078.cmsb17-md\:text-8xl { 1079font-size: 2.125rem; 1080line-height: 1.255 1081} 1082} 1083@media (min-width: 1024px) { 1084.cmsb17-lg\:mb-20 { 1085margin-bottom: 5rem 1086} 1087.cmsb17-lg\:py-20 { 1088padding-top: 5rem; 1089padding-bottom: 5rem 1090} 1091}</style><style data-jit-css data-liveview-style-type="cms_block" data-liveview-style-id="34">.cmsb34-relative { 1092position: relative 1093} 1094.cmsb34-mx-auto { 1095margin-left: auto; 1096margin-right: auto 1097} 1098.cmsb34-mb-1 { 1099margin-bottom: 0.25rem 1100} 1101.cmsb34-mb-4 { 1102margin-bottom: 1rem 1103} 1104.cmsb34-mb-5 { 1105margin-bottom: 1.25rem 1106} 1107.cmsb34-mb-8 { 1108margin-bottom: 2rem 1109} 1110.cmsb34-mt-12 { 1111margin-top: 3rem 1112} 1113.cmsb34-mt-6 { 1114margin-top: 1.5rem 1115} 1116.cmsb34-mt-8 { 1117margin-top: 2rem 1118} 1119.cmsb34-block { 1120display: block 1121} 1122.cmsb34-flex { 1123display: flex 1124} 1125.cmsb34-grid { 1126display: grid 1127} 1128.cmsb34-hidden { 1129display: none 1130} 1131.cmsb34-h-full { 1132height: 100% 1133} 1134.cmsb34-w-full { 1135width: 100% 1136} 1137.cmsb34-max-w-7xl { 1138max-width: 80rem 1139} 1140.cmsb34-max-w-\[150px\] { 1141max-width: 150px 1142} 1143.cmsb34-max-w-md { 1144max-width: 28rem 1145} 1146.cmsb34-flex-shrink-0 { 1147flex-shrink: 0 1148} 1149.cmsb34-rotate-180 { 1150--tw-rotate: 180deg; 1151transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) 1152} 1153.cmsb34-grid-cols-2 { 1154grid-template-columns: repeat(2, minmax(0, 1fr)) 1155} 1156.cmsb34-flex-col { 1157flex-direction: column 1158} 1159.cmsb34-flex-wrap { 1160flex-wrap: wrap 1161} 1162.cmsb34-flex-nowrap { 1163flex-wrap: nowrap 1164} 1165.cmsb34-items-end { 1166align-items: flex-end 1167} 1168.cmsb34-items-center { 1169align-items: center 1170} 1171.cmsb34-justify-start { 1172justify-content: flex-start 1173} 1174.cmsb34-justify-center { 1175justify-content: center 1176} 1177.cmsb34-justify-between { 1178justify-content: space-between 1179} 1180.cmsb34-gap-2 { 1181gap: 0.5rem 1182} 1183.cmsb34-gap-4 { 1184gap: 1rem 1185} 1186.cmsb34-space-y-2 > :not([hidden]) ~ :not([hidden]) { 1187--tw-space-y-reverse: 0; 1188margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); 1189margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)) 1190} 1191.cmsb34-rounded { 1192border-radius: 0.25rem 1193} 1194.cmsb34-rounded-xl { 1195border-radius: 0.75rem 1196} 1197.cmsb34-border { 1198border-width: 1px 1199} 1200.cmsb34-border-b { 1201border-bottom-width: 1px 1202} 1203.cmsb34-border-r { 1204border-right-width: 1px 1205} 1206.cmsb34-border-\[\#BCBFBA\] { 1207--tw-border-opacity: 1; 1208border-color: rgb(188 191 186 / var(--tw-border-opacity)) 1209} 1210.cmsb34-border-gray-200 { 1211--tw-border-opacity: 1; 1212border-color: rgb(229 231 235 / var(--tw-border-opacity)) 1213} 1214.cmsb34-border-white\/10 { 1215border-color: rgb(255 255 255 / 0.1) 1216} 1217.cmsb34-bg-\[\#D9DDD7\] { 1218--tw-bg-opacity: 1; 1219background-color: rgb(217 221 215 / var(--tw-bg-opacity)) 1220} 1221.cmsb34-bg-black { 1222--tw-bg-opacity: 1; 1223background-color: rgb(22 23 26 / var(--tw-bg-opacity)) 1224} 1225.cmsb34-bg-white { 1226--tw-bg-opacity: 1; 1227background-color: rgb(255 255 255 / var(--tw-bg-opacity)) 1228} 1229.cmsb34-p-4 { 1230padding: 1rem 1231} 1232.cmsb34-p-8 { 1233padding: 2rem 1234} 1235.cmsb34-px-4 { 1236padding-left: 1rem; 1237padding-right: 1rem 1238} 1239.cmsb34-px-8 { 1240padding-left: 2rem; 1241padding-right: 2rem 1242} 1243.cmsb34-py-10 { 1244padding-top: 2.5rem; 1245padding-bottom: 2.5rem 1246} 1247.cmsb34-py-4 { 1248padding-top: 1rem; 1249padding-bottom: 1rem 1250} 1251.cmsb34-pb-10 { 1252padding-bottom: 2.5rem 1253}
1254.cmsb34-pb-5 { 1255padding-bottom: 1.25rem 1256} 1257.cmsb34-pt-20 { 1258padding-top: 5rem 1259} 1260.cmsb34-pt-5 { 1261padding-top: 1.25rem 1262} 1263.cmsb34-pt-6 { 1264padding-top: 1.5rem 1265} 1266.cmsb34-pt-8 { 1267padding-top: 2rem 1268} 1269.cmsb34-text-left { 1270text-align: left 1271} 1272.cmsb34-text-center { 1273text-align: center 1274} 1275.cmsb34-text-4xl { 1276font-size: 1.625rem; 1277line-height: 1.255 1278} 1279.cmsb34-text-\[16px\] { 1280font-size: 16px 1281} 1282.cmsb34-text-\[18px\] { 1283font-size: 18px 1284} 1285.cmsb34-text-base { 1286font-size: 1rem; 1287line-height: 1.5rem 1288} 1289.cmsb34-text-lg { 1290font-size: 1.125rem; 1291line-height: 1.255 1292} 1293.cmsb34-font-bold { 1294font-weight: 700 1295} 1296.cmsb34-font-light { 1297font-weight: 300 1298} 1299.cmsb34-font-normal { 1300font-weight: 400 1301} 1302.cmsb34-uppercase { 1303text-transform: uppercase 1304} 1305.cmsb34-leading-relaxed { 1306line-height: 1.625 1307} 1308.cmsb34-text-black { 1309--tw-text-opacity: 1; 1310color: rgb(22 23 26 / var(--tw-text-opacity)) 1311} 1312.cmsb34-text-gray-600 { 1313--tw-text-opacity: 1; 1314color: rgb(75 85 99 / var(--tw-text-opacity)) 1315} 1316.cmsb34-text-white { 1317--tw-text-opacity: 1; 1318color: rgb(255 255 255 / var(--tw-text-opacity)) 1319} 1320.cmsb34-text-white\/50 { 1321color: rgb(255 255 255 / 0.5) 1322} 1323.cmsb34-text-white\/70 { 1324color: rgb(255 255 255 / 0.7) 1325} 1326.cmsb34-text-white\/80 { 1327color: rgb(255 255 255 / 0.8) 1328} 1329.cmsb34-shadow-md { 1330--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
1331--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); 1332box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow) 1333} 1334.cmsb34-shadow-sm { 1335--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05); 1336--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color); 1337box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow) 1338} 1339.cmsb34-transition-all { 1340transition-property: all; 1341transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 1342transition-duration: 150ms 1343} 1344.cmsb34-transition-opacity { 1345transition-property: opacity; 1346transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 1347transition-duration: 150ms 1348} 1349.cmsb34-transition-transform { 1350transition-property: transform; 1351transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 1352transition-duration: 150ms 1353} 1354.cmsb34-duration-200 { 1355transition-duration: 200ms 1356} 1357.cmsb34-hover\:bg-gray-800:hover { 1358--tw-bg-opacity: 1; 1359background-color: rgb(31 41 55 / var(--tw-bg-opacity)) 1360} 1361.cmsb34-hover\:underline:hover { 1362text-decoration-line: underline 1363} 1364.cmsb34-hover\:opacity-80:hover { 1365opacity: 0.8 1366} 1367@media (min-width: 768px) { 1368.cmsb34-md\:flex-row { 1369flex-direction: row 1370} 1371.cmsb34-md\:items-start { 1372align-items: flex-start 1373} 1374.cmsb34-md\:justify-start { 1375justify-content: flex-start 1376} 1377.cmsb34-md\:space-x-4 > :not([hidden]) ~ :not([hidden]) { 1378--tw-space-x-reverse: 0; 1379margin-right: calc(1rem * var(--tw-space-x-reverse)); 1380margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))) 1381} 1382.cmsb34-md\:space-y-0 > :not([hidden]) ~ :not([hidden]) { 1383--tw-space-y-reverse: 0; 1384margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse))); 1385margin-bottom: calc(0px * var(--tw-space-y-reverse)) 1386} 1387.cmsb34-md\:p-12 { 1388padding: 3rem 1389} 1390.cmsb34-md\:pb-16 { 1391padding-bottom: 4rem 1392} 1393.cmsb34-md\:pt-32 { 1394padding-top: 8rem 1395} 1396.cmsb34-md\:text-left { 1397text-align: left 1398} 1399.cmsb34-md\:text-5xl { 1400font-size: 1.75rem; 1401line-height: 1.255 1402} 1403} 1404@media (min-width: 1024px) { 1405.cmsb34-lg\:pointer-events-none { 1406pointer-events: none 1407} 1408.cmsb34-lg\:mx-0 { 1409margin-left: 0px; 1410margin-right: 0px 1411} 1412.cmsb34-lg\:block { 1413display: block 1414} 1415.cmsb34-lg\:hidden { 1416display: none 1417} 1418.cmsb34-lg\:grid-cols-4 { 1419grid-template-columns: repeat(4, minmax(0, 1fr)) 1420} 1421.cmsb34-lg\:justify-start { 1422justify-content: flex-start 1423} 1424.cmsb34-lg\:border-b-0 { 1425border-bottom-width: 0px 1426} 1427.cmsb34-lg\:border-l { 1428border-left-width: 1px 1429} 1430.cmsb34-lg\:border-r { 1431border-right-width: 1px 1432} 1433.cmsb34-lg\:p-5 { 1434padding: 1.25rem 1435} 1436.cmsb34-lg\:px-0 { 1437padding-left: 0px; 1438padding-right: 0px 1439} 1440.cmsb34-lg\:px-8 { 1441padding-left: 2rem; 1442padding-right: 2rem 1443} 1444.cmsb34-lg\:py-4 { 1445padding-top: 1rem; 1446padding-bottom: 1rem 1447} 1448.cmsb34-lg\:pb-12 { 1449padding-bottom: 3rem 1450} 1451.cmsb34-lg\:pb-8 { 1452padding-bottom: 2rem 1453} 1454.cmsb34-lg\:pl-10 { 1455padding-left: 2.5rem 1456} 1457.cmsb34-lg\:pr-10 { 1458padding-right: 2.5rem 1459} 1460.cmsb34-lg\:pt-12 {
1461padding-top: 3rem 1462} 1463.cmsb34-lg\:pt-8 { 1464padding-top: 2rem 1465} 1466.cmsb34-lg\:text-left { 1467text-align: left 1468} 1469}</style></head> 1470<body class="catalog-category-view catalog-category-view-type-layered catalog-category-view-displaymode-products catalog-category-view-id-6 hyva-default hyva-catalog-category-view hyva-catalog-category-view-type-layered hyva-catalog-category-view-displaymode-products hyva-catalog-category-view-id-6 customer-logged-out page-with-filter page-products categorypath-comprar-bonito-del-norte category-comprar-bonito-del-norte page-layout-2columns-left"> 1471<div id="cookie-consent" x-data="initCookiesConfig()"> 1472 <div x-show="visibleNotice" 1473 :class="{'fixed top-0 right-0 bottom-0 left-0 z-40' : !isAllowNavigation}" 1474 aria-label="Región de aviso de cookies" 1475 role="dialog" 1476 x-ref="dialog" 1477 aria-modal="true" 1478 x-cloak> 1479 <div> 1480 <div x-show="!isAllowNavigation" 1481 x-transition:enter="ease-out duration-300" 1482 x-transition:enter-start="opacity-0" 1483 x-transition:enter-end="opacity-100" 1484 x-transition:leave="ease-in duration-200" 1485 x-transition:leave-start="opacity-100" 1486 x-transition:leave-end="opacity-0" 1487 class="backdrop" 1488 aria-hidden="true"></div> 1489 1490 <div x-transition:enter="ease-out duration-300" 1491 x-transition:enter-start="opacity-0 translate-y-4 md:translate-y-0 md:scale-95" 1492 x-transition:enter-end="opacity-100 translate-y-0 md:scale-100" 1493 x-transition:leave="ease-in duration-200" 1494 x-transition:leave-start="opacity-100 translate-y-0 md:scale-100" 1495 x-transition:leave-end="opacity-0 translate-y-4 md:translate-y-0 md:scale-95" 1496 :class="{'z-50' : isAllowNavigation}" 1497 class="fixed bg-gray-light bottom-0 left-0 right-0 p-4 lg:py-10 lg:pb-7 lg:px-7"> 1498 <button x-show="isAllowNavigation" @click="visibleNotice = false" aria-label="Cerrar" 1499 class="absolute top-0 right-0 p-2.5 opacity-75 transition duration-150 ease-in-out"> 1500 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-6 h-6" width="24" height="24" role="img"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/><title>x</title></svg> 1501 </button> 1502 <div class=""> 1503 <div class="py-1 lg:pt-3.5 lg:pb-4"> 1504 <p class="text-2xl font-bold text-black"> 1505 <span>Cookies</span> 1506 </p> 1507 </div> 1508 <div class="flex flex-col flex-no-wrap py-2.5 gap-6 md:gap-4 md:justify-between md:flex-row"> 1509 <p class="text-md md:text-lg font-light text-black"> 1510 <span class="hidden md:block">Utilizamos cookies propias y de terceros para mejorar nuestros servicios y mostrarle publicidad relacionada con sus preferencias mediante el análisis de sus hábitos de navegación. Para gestionar o deshabilitar estas cookies, haga clic en Configuración de cookies. En caso de rechazarlas, se aceptarán las necesarias para una navegación alternativa.</span> 1511 <span class="md:hidden">Utilizamos cookies propias y de terceros para mejorar nuestros servicios. Para gestionarlas haga clic en Configuración de cookies. En caso de rechazarlas, se aceptarán las necesarias para una navegación alternativa.</span> 1512 </p> 1513 <div class="flex flex-col flex-no-wrap gap-2 md:w-1/2 md:mt-0 md:flex-row"> 1514 <button class="btn btn-dark-stroke btn-md w-full md:w-1/2 order-2 md:order-1" mcclane-data="cookies-configure" @click="visibleConfig = true; visibleNotice = false">
1514Configurar cookies</button> 1515 <button class="btn btn-dark-stroke btn-md w-full md:w-1/2 order-3 md:order-2" @click="clickAcceptRequired" aria-label="Rechazar">Rechazar</button> 1516 <button class="btn btn-dark-stroke btn-md w-full md:w-1/2 order-1 md:order-3" mcclane-data="cookies-accept" @click="clickAcceptAll" title="Enable or disable all services">Aceptar todas</button> 1517 </div> 1518 </div> 1519 </div> 1520 </div> 1521 </div> 1522 </div> 1523 1524 <div x-show="visibleConfig" class="overflow-y-auto fixed inset-0 z-50" 1525 x-on:toggle-cookiesconsent-config.window="visibleConfig = true" 1526 aria-labelledby="modal-title" 1527 x-ref="dialog" 1528 aria-modal="true" 1529 x-cloak> 1530 <div class="flex justify-center items-center min-h-screen"> 1531 <div x-show="visibleConfig" 1532 x-transition:enter="ease-out duration-300" 1533 x-transition:enter-start="opacity-0" 1534 x-transition:enter-end="opacity-100" 1535 x-transition:leave="ease-in duration-200" 1536 x-transition:leave-start="opacity-100" 1537 x-transition:leave-end="opacity-0" 1538 class="backdrop backdrop-close" 1539 @click="visibleConfig = false; visibleNotice = true" 1540 aria-hidden="true"></div> 1541 1542 <span class="hidden md:inline-block md:align-middle md:h-screen" aria-hidden="true">​</span> 1543 1544 <div x-show="visibleConfig" 1545 x-transition:enter="ease-out duration-300" 1546 x-transition:enter-start="opacity-0 translate-y-4 md:translate-y-0 md:scale-95" 1547 x-transition:enter-end="opacity-100 translate-y-0 md:scale-100" 1548 x-transition:leave="ease-in duration-200" 1549 x-transition:leave-start="opacity-100 translate-y-0 md:scale-100" 1550 x-transition:leave-end="opacity-0 translate-y-4 md:translate-y-0 md:scale-95" 1551 class="flex overflow-hidden flex-col justify-start px-4 pt-10 pb-4 m-4 w-full h-auto bg-white transition-all transform gap-4 md:justify-center md:p-8 md:my-8 md:max-w-2xl" mcclane="cookies-configure-modal"> 1552 <button @click="visibleConfig = false; visibleNotice = true" aria-label="Cerrar" 1553 class="absolute top-0 right-0 p-4 opacity-75 transition duration-150 ease-in-out"> 1554 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-6 h-6" width="24" height="24" role="img"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/><title>x</title></svg> 1555 </button> 1556 <div class="relative"> 1557 <p class="text-lg font-bold mb-2 configuratorTitle">Configuración de cookies</p> 1558 <p class="text-sm font-light text-black"> 1559 <span class="hidden md:inline-block configuratorDescription">Utilizamos cookies propias y de terceros para mejorar nuestros servicios y mostrarle publicidad relacionada con sus preferencias mediante el análisis de sus hábitos de navegación. Para saber más, lea nuestros <a href="cookies" target="_blank" class="underline">cookies</a>.</span> 1560 <span class="md:hidden configuratorDescription">Utilizamos cookies propias y de terceros para mejorar nuestros servicios mediante el análisis de sus hábitos de navegación. Para saber más, lea nuestros <a href="cookies" target="_blank" class="underline">cookies</a>.</span> 1561 </p> 1562 </div> 1563 <div class="overflow-y-auto flex flex-col gap-4"> 1564 <template x-for="[id, category] in Object.entries(categories)" hidden> 1565 <div class="flex flex-row gap-3 pl-1"> 1566 <button class="shrink-0 group relative rounded-full inline-flex items-center justify-center h-5 w-10 cursor-pointer 
1566focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" 1567 type="button" 1568 role="switch" 1569 aria-checked="false" 1570 :aria-checked="groups[id].toString()" 1571 :class="{'opacity-30': category.required}" 1572 :disabled="category.required" 1573 mcclane-data="cookies-configure-btn" 1574 @click="groups[id] = !groups[id]"> 1575 <span aria-hidden="true" class="pointer-events-none absolute bg-white w-full h-full rounded-md"></span> 1576 <span aria-hidden="true" class="pointer-events-none absolute h-4 w-9 mx-auto rounded-full transition-colors ease-in-out duration-200 bg-gray-200" x-state:on="Enabled" x-state:off="Not Enabled" :class="{ 'bg-primary': groups[id], 'bg-gray-light': !(groups[id]) }"></span> 1577 <span aria-hidden="true" class="pointer-events-none absolute left-0 inline-block h-5 w-5 border border-gray-200 rounded-full bg-white shadow transform ring-0 transition-transform ease-in-out duration-200 translate-x-0" x-state:on="Enabled" x-state:off="Not Enabled" :class="{ 'translate-x-5': groups[id], 'translate-x-0': !(groups[id]) }"></span> 1578 </button> 1579 <div class="flex flex-col gap-0.5"> 1580 <p class="text-md font-bold" x-text="category.title"></p> 1581 <p class="text-sm font-light" x-text="category.description"></p> 1582 <span class="cursor-pointer text-sm underline" 1583 @click="visibleConfig = false; visibleNotice = true; openLink(atob(category.link), '_self');"> 1584 Ver cookies </span> 1585 </div> 1586 </div> 1587 </template> 1588 </div> 1589 <div class="flex flex-row flex-no-wrap gap-2"> 1590 <button class="btn btn-dark-stroke btn-sm w-full md:w-auto" @click="clickAcceptSelected" mcclane-data="cookies-modal-accept">Aceptar seleccionadas</button> 1591 <button class="btn btn-dark-stroke btn-sm w-full md:w-auto" @click="clickAcceptAll" title="Enable or disable all services">Aceptar todas</button> 1592 </div> 1593 </div> 1594 </div> 1595 </div> 1596</div> 1597
1598<script> 1599 window.domains_whitelist = ["googletagmanager.com"] || []; 1600 function initCookiesConfig() { 1601 return { 1602 cookieName: 'cookie\u002Dconsent', 1603 definitionVersion: '0.0.1', 1604 isAllowNavigation: false, 1605 cookiesPolicyUrl: 'cookies', 1606 logMode: false, 1607 categories: {"required":{"name":"required","title":"Cookies obligatorias","description":"Estas cookies son estrictamente necesarias para el funcionamiento de la tienda y nos permiten ofrecer funcionalidades b\u00e1sicas (seguridad, registro de usuarios, idioma, carrito de la compra...).","link":"aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvY29va2llcw==","required":true,"purposes":["required"],"accept":true,"iscustom":false,"default":true,"domains":["googletagmanager.com"],"cookies":[["cookie-consent","\/","Almacena la configuraci\u00f3n real del consentimiento de las cookies del cliente","","",""],["frontend","\/","Cookie interna para equilibrar el servidor","","",""],["cookienotice","\/","Magento utiliza para saber si se muestra el aviso de cookies","","",""],["form_key","\/","Clave de formulario de Magento","","",""],["\/mage-.+\/","\/","Cookies relacionadas con Magento","","",""],["product_data_storage","\/","Precio personalizado del producto Magento por cliente","","",""],["\/recently_.+\/","\/","Magento relacionado con las secciones vistas recientemente","","",""],["PHPSESSID","\/","Cookie interna de PHP para almacenar sesiones","","",""],["add_to_cart","\/","Utilizado por Google Tag Manager. Captura el SKU del producto, el nombre, el precio y la cantidad eliminados del carrito, y hace que la informaci\u00f3n est\u00e9 disponible para una futura integraci\u00f3n mediante secuencias de comandos de terceros.","","",""],["guest-view","\/","Stores the Order ID that guest shoppers use to retrieve their order status. Guest orders view. Used in \u201cOrders and Returns\u201d widgets.","","",""],["login_redirect","\/","Conserva la p\u00e1gina de destino que se estaba cargando antes de que se indicara al cliente que iniciara sesi\u00f3n. Se utiliza una redirecci\u00f3n de inicio de sesi\u00f3n con el minicarro para los clientes que inician sesi\u00f3n si la opci\u00f3n de configuraci\u00f3n Mostrar minicarro est\u00e1 establecida en S\u00ed","","",""],["remove_from_cart","\/","Utilizado por Google Tag Manager. Captura el SKU del producto, el nombre, el precio y la cantidad agregada al carrito, y hace que la informaci\u00f3n est\u00e9 disponible para una futura integraci\u00f3n mediante secuencias de comandos de terceros.","","",""],["stf","\/","Registra la hora en que el m\u00f3dulo SendFriend (Enviar correo electr\u00f3nico a un amigo) env\u00eda los mensajes.","","",""],["X-Magento-Vary","\/","Ajuste de configuraci\u00f3n que mejora el rendimiento cuando se utiliza el almacenamiento en cach\u00e9 de contenido est\u00e1tico de Varnish.","","",""],["private_content_version","\/","Agrega un n\u00famero y una hora aleatorios y \u00fanicos a las p\u00e1ginas con contenido del cliente para evitar que se almacenen en cach\u00e9 en el servidor","","",""],["section_data_ids","\/","Almacena informaci\u00f3n espec\u00edfica del cliente relacionada con acciones iniciadas por el comprador, como mostrar la lista de deseos, informaci\u00f3n de pago, etc.","","",""],["store","\/","Realiza un seguimiento de la vista \/ configuraci\u00f3n regional espec\u00edfica de la tienda seleccionada por el comprador","","",""],["user_allowed_save_cookie","\/","Usado para el modo de restricci\u00f3n de cookies","","",""],["\/_ga|_gid|_gat|_gac.+|AMP_TOKEN|__utm.+\/","\/","Cookies relacionadas con Google Analytics para el seguimiento de visitas","google-analitycs.com","",""],["OGPC","\/","Esta cookie habilita la funcionalidad de Google Maps.",".google.com","",""],["CGIC","\/","Mejora la entrega de resultados de b\u00fasqueda al completar autom\u00e1ticamente las consultas de b\u00fasqueda seg\u00fan la entrada inicial del usuario. Esta cookie tiene una duraci\u00f3n de 6 meses",".google.com","",""],["DV","\/","Google ReCaptcha almacena una co
1607okie para ayudar a detectar si el usuario es un robot o no (garantizar la seguridad)","www.google.com","",""],["SIDCC","\/","Google los utiliza para almacenar las preferencias del usuario y la informaci\u00f3n mientras visualiza p\u00e1ginas con mapas de Google","google.com","",""],["rocket_social_login_initial_link","\/","Permite una correcta redirecci\u00f3n despu\u00e9s de identificarse o registrarse con redes sociales.","","",""],["outdated_browser_popup","\/","Used for display only once the outdated browser pop up","","",""],["geoip_store","\/","Used for display only once the store selector pop up","","",""],["country_code","\/","This cookie is used to store the user's country code, typically detected via IP address or browser settings. Its main purpose is to tailor the user experience by displaying relevant content, currency, language, or services based on the user's geographic l","serrats.com","",""],["datalayer-cache-customer","\/","This cookie is used to store cached customer-related data for the dataLayer. It helps optimize performance by reducing the need to repeatedly fetch customer data for tracking or personalization purposes.","serrats.com","",""],["cookie-consent","","Almacena la configuraci\u00f3n real del consentimiento de las cookies del cliente","","12 months","Sin transferencia de datos a terceros pa\u00edses"],["PHPSESSID","","Cookie interna de PHP para almacenar sesiones","","Sesi\u00f3n","Sin transferencia de datos a terceros pa\u00edses"],["frontend","","Cookie interna para equilibrar el servidor","","Sesi\u00f3n","Sin transferencia de datos a terceros pa\u00edses"],["cookienotice","","Magento utiliza para saber si se muestra el aviso de cookies","","12 months","Sin transferencia de datos a terceros pa\u00edses"],["form_key","","Magento form key","","Sesi\u00f3n","Sin transferencia de datos a terceros pa\u00edses"],["\/mage-.+\/","","Cookies relacionadas con Magento","","Sesi\u00f3n","Sin transferencia de datos a terceros pa\u00edses"],["\/recently_.+\/","","Magento relacionado con las secciones vistas recientemente","","Sesi\u00f3n","Sin transferencia de datos a terceros pa\u00edses"],["product_data_storage","","Precio personalizado del producto Magento por cliente","","Sesi\u00f3n","Sin transferencia de datos a terceros pa\u00edses"],["add_to_cart","","Utilizado por Google Tag Manager. Captura el SKU del producto, el nombre, el precio y la cantidad eliminados del carrito, y hace que la informaci\u00f3n est\u00e9 disponible para una futura integraci\u00f3n mediante secuencias de comandos de terceros.","","Sesi\u00f3n","S\u00ed, a EE.UU. y otros pa\u00edses"],["remove_from_cart","","Utilizado por Google Tag Manager. Captura el SKU del producto, el nombre, el precio y la cantidad agregada al carrito, y hace que la informaci\u00f3n est\u00e9 disponible para una futura integraci\u00f3n mediante secuencias de comandos de terceros.","","Sesi\u00f3n","S\u00ed, a EE.UU. y otros pa\u00edses"],["guest-view","","Stores the Order ID that guest shoppers use to retrieve their order status. Guest orders view. Used in \u201cOrders and Returns\u201d widgets.","","Sesi\u00f3n","Sin transferencia de datos a terceros pa\u00edses"],["login_redirect","","Conserva la p\u00e1gina de destino que se estaba cargando antes de que se indicara al cliente que iniciara sesi\u00f3n. Se utiliza una redirecci\u00f3n de inicio de sesi\u00f3n con el minicarro para los clientes que inician sesi\u00f3n si la opci\u00f3n de configuraci\u00f3n Mostrar minicarro est\u00e1 establecida en S\u00ed","","Sesi\u00f3n","Sin transferencia de datos a terceros pa\u00edses"],["stf","","Registra la hora en que el m\u00f3dulo SendFriend (Enviar correo electr\u00f3nico a un amigo) env\u00eda los mensajes.","","Sesi\u00f3n","Sin transferencia de datos a terceros pa\u00edses"],["X-Magento-Vary","","Ajuste de configuraci\u00f3n que mejora el rendimiento cuando se utiliza el almacenamiento en cach\u00e9 de contenido est\u00e1tico de Varnish.","","Sesi\u00f3n","Sin transferencia de datos a terceros pa\u00edses"],["private_content_version","","Agrega un n\u00famero y una hora aleatorios y \u00fanicos a las p\u00e1ginas con contenido del cliente para evitar que se almacenen en cach\u00e9 en el servidor","","Sesi\u00f3n","Sin transferencia de datos a terceros pa\u00edses"],["section_data_ids","","Almacena informaci\u00f3n espec\u00edfica del cliente relacionada con acciones iniciadas por el comprador, como mostrar la lista de deseos, informaci\u00f3n de pago, etc.","","Sesi\u00f3n","Sin transferencia de datos a terceros pa\u00edses"],["store","","Realiza un seguimiento de la vista \/ configuraci\u00f3n regional espec\u00edfica de la tienda seleccionad
1607a por el comprador","","Sesi\u00f3n","Sin transferencia de datos a terceros pa\u00edses"],["user_allowed_save_cookie","","Usado para el modo de restricci\u00f3n de cookies","","12 months","Sin transferencia de datos a terceros pa\u00edses"],["OGPC","","Esta cookie habilita la funcionalidad de Google Maps.",".google.com","Sesi\u00f3n","S\u00ed, a EE.UU. y otros pa\u00edses"],["CGIC","","Mejora la entrega de resultados de b\u00fasqueda al completar autom\u00e1ticamente las consultas de b\u00fasqueda seg\u00fan la entrada inicial del usuario. Esta cookie tiene una duraci\u00f3n de 6 meses",".google.com","6 months","S\u00ed, a EE.UU. y otros pa\u00edses"],["SIDCC","","Google los utiliza para almacenar las preferencias del usuario y la informaci\u00f3n mientras visualiza p\u00e1ginas con mapas de Google","www.google.com","6 months","S\u00ed, a EE.UU. y otros pa\u00edses"],["DV","","Google ReCaptcha almacena una cookie para ayudar a detectar si el usuario es un robot o no (garantizar la seguridad)","www.google.com","Sesi\u00f3n","S\u00ed, a EE.UU. y otros pa\u00edses"],["rocket_social_login_initial_link","","Permite una correcta redirecci\u00f3n despu\u00e9s de identificarse o registrarse con redes sociales.","","",""],["geoip_store","","Used for display only once the store selector pop up","","1 Day","Sin transferencia de datos a terceros pa\u00edses"],["ampromo-popup","","Used for display only once the Amasty promo pop up","","1 Day","Sin transferencia de datos a terceros pa\u00edses"],["outdated_browser_popup","","Used for display only once the outdated browser pop up","","1 Day","Sin transferencia de datos a terceros pa\u00edses"]]},"functional":{"name":"functional","title":"Funcionalidad","description":"Permite el almacenamiento de informaci\u00f3n que posibilita el correcto funcionamiento del sitio web o de la aplicaci\u00f3n.","link":"aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvY29va2llcw==","required":false,"purposes":["functional"],"accept":false,"iscustom":false,"default":false,"domains":["youtube.com","googleoptimize.com",".skeepers.io"],"cookies":[["__zlcmid","\/","Utilizado por el chat de Zopim para almacenar una identificaci\u00f3n de usuario \u00fanica","zopim.com",null,null],["__cfduid","\/","El servicio CloudFlare establece la cookie '__cfduid' para identificar el tr\u00e1fico web confiable.","cloudflare.com",null,null],["_asc","\/","La anal\u00edtica de Alexa usa esta cookie para rastrear y reportar informaci\u00f3n al servicio de anal\u00edtica de Alexa","alexa.com",null,null],["_auc","\/","La anal\u00edtica de Alexa usa esta cookie para rastrear y reportar informaci\u00f3n al servicio de anal\u00edtica de Alexa","alexa.com",null,null],["atrk","\/","La anal\u00edtica de Alexa usa esta cookie para rastrear y reportar informaci\u00f3n al servicio de anal\u00edtica de Alexa","alexa.com",null,null],["atrk.gif","\/","Esta cookie se utiliza para recopilar informaci\u00f3n sobre el comportamiento del consumidor, que se env\u00eda a Alexa Analytics","alexa.com",null,null],["APID","\/","Recopila informaci\u00f3n sobre el comportamiento de los visitantes en varios sitios web. Esta informaci\u00f3n se utiliza en el sitio web para optimizar la relevancia de la publicidad","yahoo.com",null,null],["B","\/","Recopila datos an\u00f3nimos relacionados con las visitas al sitio web del usuario, como el n\u00famero de visitas, el tiempo promedio que pasa en el sitio web y las p\u00e1ginas que se han cargado","yahoo.com",null,null],["GPS","\/","Cookie de YouTube que registra un \u00fanico ID en dispositivos m\u00f3viles con fines estad\u00edsticos seg\u00fan la ubicaci\u00f3n geogr\u00e1fica","youtube.com",null,null],["MR","\/","Cookie de an\u00e1lisis que se utiliza para transmitir informaci\u00f3n sobre las acciones del usuario a la red publicitaria de Bing","bing.com",null,null],["na_id","\/","Addthis usa esto para almacenar el historial de uso del usuario.","addthis.com",null,null],["stx_user_id","\/","Entrega de contenido espec\u00edfico y relevante","sharethrough.com",null,null],["AWSALB","\/","Balanceador de carga de aplicaciones de Amazon ELB","amazon.com",null,null],["store-locator-stock","\/","Save your selected shop for easy stock viewing in the future.",null,null,null],["last_visited_store","\/","This cookie stores information about the last store or region the user visited on the website. It is used to redirect returning users to the same version of the store, ensuring a consistent and personalized browsing experience.","serrats.com",null,null]]},"ad":{"name":"ad","title":"Publicidad comportamental","description":"Las cookies de publicidad comportamental son aquellas que almacenan informaci\u00f3n del comportamiento de los usuarios obtenida a trav\u00e9s de la observaci\u00f3n continuada de sus h\u00e1bitos de navegaci\u00f3n, lo que permite desarrollar un perfil espec\u00edfico para mostrar publicidad en funci\u00f3n del mismo. La base jur\u00eddica que legitima el tratamiento es el consentimiento expreso otorgado por el usuario. Puede obtener m\u00e1s informaci\u00f3n sobre estas cookies, as\u00ed como su periodo de conservaci\u00f3n siguiendo el enlace o enlaces \u00abPol\u00edtica de cookies\u00bb.","link":"aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvY29va2llcw==","required":false,"purposes":["ad"],"accept":false,"iscustom":false,"default":false,"domains":["tiktok.com","facebook.com","googleadservices.com","doubleclick.net"],"cookies":[]},"analytics":{"name":"analytics","title":"Medici\u00f3n o an\u00e1lisis","description":"Las cookies de medici\u00f3n o an\u00e1lisis son aqu\u00e9llas que permiten al responsable de las mismas, el seguimiento y an\u00e1lisis del comportamiento de los usuarios de los sitios web a los que est\u00e1n vinculadas, incluyendo la cuantificaci\u00f3n de los impactos publicitarios. La informaci\u00f3n recogida mediante este tipo de cookies se utiliza en la medici\u00f3n de la actividad de los sitios web, aplicaci\u00f3n o plataforma y para la introducci\u00f3n de mejoras en funci\u00f3n del an\u00e1lisis de los datos de uso que hacen los usuarios del servicio. La base jur\u00eddica que legitima el tratamiento es el consentimiento expreso otorgado por el usuario. Puede obtener m\u00e1s informaci\u00f3n sobre estas cookies, as\u00ed como su periodo de conservaci\u00f3n siguiendo el\/los enlace\/s en \u00abPol\u00edtica de Cookies\u00bb.","link":"aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvY29va2llcw==","required":false,"purposes":["analytics"],"accept":false,"iscustom":false,"default":false,"domains":["google-analytics.com","clarity.ms"],"cookies":[]},"ad_user_data":{"name":"ad_user_data","title":"Datos de usuarios de anuncios","description":"Define el consentimiento para enviar a Google datos del usuario relacionados con la publicidad.","link":"aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvY29va2llcw==","required":false,"purposes":["ad_user_data"],"accept":false,"iscustom":true,"default":false,"domains":[],"cookies":[]},"ad_personalization":{"name":"ad_personalization","title":"Publicidad personalizada","description":"Define el consentimiento en materia de publicidad personalizada.","link":"aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvY29va2llcw==","required":false,"purposes":["ad_personalization"],"accept":false,"iscustom":true,"default":false,"domains":[],"cookies":[]},"personalization":{"name":"personalization","title":"Personalizaci\u00f3n","de
1607scription":"Las cookies de personalizaci\u00f3n son aquellas que permiten recordar informaci\u00f3n para que el usuario pueda acceder al servicio con algunas caracter\u00edsticas que pueden diferenciar su experiencia de la de otros usuarios.","link":"aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvY29va2llcw==","required":false,"purposes":["personalization"],"accept":false,"iscustom":false,"default":false,"domains":[],"cookies":[]}}, 1608 domain: COOKIE_CONFIG.domain, 1609 visibleConfig: false, 1610 services: {}, 1611 visibleCookies: {}, 1612 gtmIsEnabled: true, 1613 gtmInitEventName: 'init_consent', 1614 gtmUpdateEventName: 'update_consent', 1615 gtmIsConsentMode: true, 1616 gtmAllowedValue: 'granted', 1617 gtmDeniedValue: 'denied', 1618 gtmConsentModeMapping: {"analytics_storage":"analytics","ad_storage":"ad","ad_user_data":"ad_user_data","ad_personalization":"ad_personalization","personalization_storage":"personalization","functionality_storage":"functional","security_storage":"necessary"}, 1619 init: function () { 1620 if (this.cookiesPolicyUrl && window.location.pathname.includes(this.cookiesPolicyUrl)) { 1621 this.isAllowNavigation = true; 1622 } 1623 1624 this.categoriesNames = Object.keys(this.categories); 1625 this.groups = Object.fromEntries(Object.entries(this.categories).map(function (group) { 1626 return [group[0], group[1].default]; 1627 })); 1628 1629 this.currentValuesRequired = Object.fromEntries(Object.entries(this.categories).map(function (group) { 1630 return [group[0], group[1].required || group[1].default]; 1631 })); 1632 1633 for (let categoryName of Object.keys(this.categories)) { 1634 let category = this.categories[categoryName], 1635 length = category.cookies.length, 1636 cookiesNames = [], 1637 service = { 1638 name: category.name, 1639 required: category.required, 1640 cookies: [], 1641 domains: [this.domain], 1642 default: category.default, 1643 }; 1644 1645 for (let j = 0; j < length; j++) { 1646 let cookie = category.cookies[j], 1647 serviceCookies = service.cookies, 1648 name = cookie[0], 1649 cookieName = name.startsWith('/') ? name.slice(1, name.lastIndexOf('/')) : name, 1650 cookieDef = [ 1651 name.startsWith('/') ? new RegExp(cookieName) : cookieName, 1652 cookie[1] ? cookie[1] : '/', 1653 ]; 1654 1655 if (serviceCookies.indexOf(cookieDef) === -1) { 1656 cookiesNames.push(cookieName); 1657 serviceCookies.push(cookieDef); 1658 } 1659 } 1660 1661 let domainsLength = category.domains.length; 1662 for (let j = 0; j < domainsLength; j++) { 1663 let domain = category.domains[j]; 1664 service.domains.push(domain); 1665 } 1666 1667 window.cookie_consent_groups[categoryName] = service.required; 1668 window.cookie_consent_config[categoryName] = [].concat( 1669 window.cookie_consent_config[categoryName] || [], 1670 cookiesNames 1671 ); 1672 1673 this.services[service.name] = service; 1674 } 1675 1676 1677 if (window.bypass_cookie_consent) { 1678 this.acceptAll(false); 1679 this.initPushConsentCookiesPerPage(); 1680 1681 return; 1682 } 1683 1684 let content = hyva.getCookie(this.cookieName); 1685 this.currentValues = content ? JSON.parse(decodeURIComponent(content)) : false;
1686 this.versionDiffers = !!this.currentValues && this.definitionVersion !== this.currentValues.version; 1687 1688 if (this.versionDiffers) { 1689 this.removeCookie({ 1690 name: this.cookieName, 1691 path: '/', 1692 domain: this.domain 1693 }); 1694 this.currentValues = false; 1695 } 1696 1697 // update current values against to default values of groups 1698 for (let key of Object.keys(this.groups)) { 1699 if (this.currentValues && this.currentValues.consents[key] !== this.groups[key]) { 1700 this.groups[key] = window.cookie_consent_groups[key] = this.currentValues.consents[key]; 1701 } 1702 } 1703 1704 this.visibleNotice = !this.currentValues || this.versionDiffers; 1705 1706 this.createCookiesAndDomainsWhitelists(); 1707 this.removeCookiesFunction(); 1708 this.initPushConsentCookiesPerPage(); 1709 }, 1710 log: function (msg, type) { 1711 if (this.logMode && console) { 1712 if (typeof type === 'undefined') { 1713 type = 'log'; 1714 } 1715 1716 if (console[type]) { 1717 console[type](msg); 1718 } 1719 } 1720 }, 1721 getCookiesByRegexp: function (regexp, path, domains) { 1722 let regExpCookieName = regexp; 1723 1724 if (regExpCookieName instanceof RegExp) { 1725 regExpCookieName = regexp.toString(); 1726 regExpCookieName = regExpCookieName.slice(1, regExpCookieName.lastIndexOf('/')); 1727 1728 if (regExpCookieName.startsWith('^')) { 1729 regExpCookieName = regExpCookieName.slice(1); 1730 } 1731 1732 if (regExpCookieName.endsWith('$')) { 1733 regExpCookieName = regExpCookieName.slice(0, -1); 1734 } 1735 } 1736 1737 const regExp = new RegExp('(^|;) ?(' + regExpCookieName + ')=([^;]*)(;|$)', 'g'), 1738 matches = document.cookie.matchAll(regExp); 1739 1740 let output = []; 1741 1742 for (let match of matches) { 1743 if (match && match.length > 3) { 1744 for (let i = 0; i < domains.length; i++) { 1745 output.push({ 1746 name: match[2], 1747 value: match[3], 1748 path: path, 1749 domain: domains[i] ? domains[i] : this.domain, 1750 }); 1751 } 1752 } 1753 } 1754 1755 return output; 1756 }, 1757 removeCookie: function (cookie) { 1758 let cookieValue = cookie.name + '=;'; 1759 1760 if (cookie.path) { 1761 cookieValue += ' path=' + cookie.path + ';'; 1762 } 1763 1764 document.cookie = cookieValue + ' Expires=Thu, 01 Jan 1970 00:00:01 GMT;'; 1765 1766 if (cookie.domain) { 1767 cookieValue += ' domain=' + cookie.domain + ';'; 1768 } 1769 1770 document.cookie = cookieValue + ' Expires=Thu, 01 Jan 1970 00:00:01 GMT;'; 1771 }, 1772 removeCookies: function (cookies) { 1773 for (let cookie of cookies) { 1774 this.removeCookie(cookie); 1775 } 1776 }, 1777 removeCookiesFunction: function () { 1778 for (let categoryName of Object.keys(this.categories)) { 1779 if (this.services[categoryName]) { 1780 let cookies = this.services[categoryName].cookies; 1781 let accept = this.currentValues ? this.currentValues.consents[categoryName] : this.currentValuesRequired[categoryName]; 1782 1783 if (!accept) { 1784 for (let [name, path, domain] of cookies) { 1785 let existingCookies = this.getCookiesByRegexp(name, path, domain || [this.domain]); 1786 1787 if (existingCookies.length) { 1788 this.removeCookies(existingCookies); 1789 this.log('Removed cookie ' + existingCookies[0].name); 1790 } 1791 } 1792 } 1793 } 1794 } 1795 }, 1796 createCookiesAndDomainsWhitelists: function() { 1797 window.cookies_whitelist = []; 1798 this.addAcceptedCategoriesCookiesAndDomainsToWhitelist(); 1799 }, 1800 addAcceptedCategoriesCookiesAndDomainsToWhitelist: function() { 1801 window.cookies_whitelist = window.cookies_whitelist || []; 1802 window.domains_whitelist = window.domains_whitelist || []; 1803 1804 let existingCookies = []; 1805 for (let existingCookie of window.cookies_whitelist) { 1806 existingCookies.push(Object.values(existingCookie).join(';')); 1807 } 1808
1809 for (let categoryName of Object.keys(this.categories)) { 1810 if (!this.services[categoryName]) { 1811 continue 1812 } 1813 1814 let cookies = this.services[categoryName].cookies; 1815 let accept = this.currentValues ? this.currentValues.consents[categoryName] : this.currentValuesRequired[categoryName]; 1816 if (!accept) { 1817 continue; 1818 } 1819 1820 for (let [name, path, domain] of cookies) { 1821 let cookie = { 1822 'regexp': name, 1823 'path': path, 1824 'domain': domain, 1825 }; 1826 1827 if (!existingCookies.includes(Object.values(cookie).join(';'))) { 1828 window.cookies_whitelist.push(cookie); 1829 } 1830 } 1831 1832 let domains = this.services[categoryName].domains; 1833 1834 for (let domain of domains) { 1835 if (!window.domains_whitelist.includes(domain)) { 1836 window.domains_whitelist.push(domain); 1837 } 1838 } 1839 } 1840 }, 1841 acceptSelected: function (pushConsent = true) { 1842 this.currentValues = { 1843 version: this.definitionVersion, 1844 consents: this.groups, 1845 }; 1846 1847 hyva.setCookie(this.cookieName, JSON.stringify(this.currentValues)); 1848 this.visibleConfig = false; 1849 this.visibleNotice = false; 1850 1851 for (let key of Object.keys(this.groups)) { 1852 window.cookie_consent_groups[key] = this.groups[key]; 1853 } 1854 1855 this.addAcceptedCategoriesCookiesAndDomainsToWhitelist(); 1856 this.addScriptsRejectedToDOM(); 1857 this.removeCookiesFunction(); 1858 1859 if (pushConsent) { 1860 this.updatePushConsentCookies(); 1861 } 1862 }, 1863 acceptAll: function (pushConsent = true) { 1864 for (let key of Object.keys(this.groups)) { 1865 this.groups[key] = true; 1866 } 1867 this.acceptSelected(pushConsent); 1868 }, 1869 clickAcceptAll: function () { 1870 this.acceptAll(); 1871 }, 1872 clickAcceptRequired: function (pushConsent = true) { 1873 for (let key of Object.keys(this.groups)) { 1874 let enabledGroup = false; 1875 if (key == 'required') { 1876 enabledGroup = true; 1877 } 1878 1879 this.groups[key] = enabledGroup; 1880 } 1881 this.acceptSelected(pushConsent); 1882 }, 1883 clickAcceptSelected: function () { 1884 this.acceptSelected(); 1885 }, 1886 initPushConsentCookiesPerPage: function () { 1887 this.pushConsentCookies(this.gtmInitEventName, true); 1888 }, 1889 updatePushConsentCookies: function () { 1890 this.pushConsentCookies(this.gtmUpdateEventName); 1891 }, 1892 normalizeGtmValues: function (data) { 1893 const self = this; 1894 1895 return Object.keys(data).reduce(function (obj, key) { 1896 let newKey = key in self.categories && self.categories[key].iscustom ? key : key + "_storage"; 1897 obj[newKey] = (data[key] && !!data[key]) ? self.gtmAllowedValue : self.gtmDeniedValue; 1898 1899 return obj; 1900 }, {}); 1901 }, 1902 /** 1903 * Builds the Consent Mode v2 signal object for Google Tag Manager. 1904 * Maps cookie category consent values to the four required CM v2 signals: 1905 * ad_storage, analytics_storage, ad_user_data, ad_personalization. 1906 * Falls back to normalizeGtmValues when no mapping is configured. 1907 */ 1908 normalizeConsentModeV2Values: function () { 1909 const self = this; 1910 const mapping = this.gtmConsentModeMapping; 1911 const groups = window.cookie_consent_groups; 1912
1913 if (!mapping || Object.keys(mapping).length === 0) { 1914 return this.normalizeGtmValues(groups); 1915 } 1916 1917 return Object.keys(mapping).reduce(function (obj, signal) { 1918 const category = mapping[signal]; 1919 const categoryGranted = !!groups[category]; 1920 obj[signal] = categoryGranted ? self.gtmAllowedValue : self.gtmDeniedValue; 1921 1922 return obj; 1923 }, {}); 1924 }, 1925 expectArguments: function () { 1926 return arguments; 1927 }, 1928 /** 1929 * This function implements two ways of send consent cookies to datalayer 1930 * 1931 * When gtmIsConsentMode is true, emits the four Consent Mode v2 signals 1932 * (ad_storage, analytics_storage, ad_user_data, ad_personalization) mapped 1933 * from the configured cookie categories via gtmConsentModeMapping. 1934 * 1935 * [Consent Mode v2](https://developers.google.com/tag-platform/devguides/consent?hl=es). 1936 * @param eventName 1937 * @param init 1938 */ 1939 pushConsentCookies: function (eventName, init = false) { 1940 if (!this.gtmIsEnabled) { 1941 return; 1942 } 1943 1944 let normalizeConsentGroupValues = this.gtmIsConsentMode 1945 ? this.normalizeConsentModeV2Values() 1946 : this.normalizeGtmValues(window.cookie_consent_groups); 1947 1948 if (this.gtmIsConsentMode) { 1949 if (init) { 1950 window.dispatchEvent( 1951 new CustomEvent('datalayer-event', { 1952 detail: this.expectArguments('consent', 'default', normalizeConsentGroupValues) 1953 }) 1954 ); 1955 window.dispatchEvent( 1956 new CustomEvent('datalayer-event', {detail: {'event': eventName}}) 1957 ); 1958 } else { 1959 window.dispatchEvent( 1960 new CustomEvent('datalayer-event', { 1961 detail: this.expectArguments('consent', 'update', normalizeConsentGroupValues) 1962 }) 1963 ); 1964 window.dispatchEvent( 1965 new CustomEvent('datalayer-event', {detail: {'event': eventName}}) 1966 ); 1967 } 1968 } else { 1969 normalizeConsentGroupValues = {...{'event': eventName}, ...normalizeConsentGroupValues}; 1970 window.dispatchEvent(new CustomEvent('datalayer-event', {detail: normalizeConsentGroupValues})); 1971 } 1972 }, 1973 /** 1974 * Adds the removed javascript tags if later are consented by user 1975 */ 1976 addScriptsRejectedToDOM: function () { 1977 const self = this; 1978 // scripts rejected what are filled by cookie blocker 1979 window.scripts_rejected = window.scripts_rejected || []; 1980 window.domains_whitelist = window.domains_whitelist || []; 1981 const scriptsRejectedInServiceDomain = window.scripts_rejected.filter(isScriptInServiceDomain); 1982 1983 scriptsRejectedInServiceDomain.forEach((scriptSrc, index) => { 1984 if (!scriptSrc) { 1985 return; 1986 } 1987 1988 // add domain to whitelist in order to allow appendChild injection controlled by cookie blocker 1989 if (!window.domains_whitelist.includes(scriptSrc)) { 1990 window.domains_whitelist.push(scriptSrc); 1991 } 1992 1993 const script = document.createElement('script'); 1994 script.setAttribute('type', 'text/javascript'); 1995 script.setAttribute('src', scriptSrc); 1996 document.head.appendChild(script); 1997 delete window.scripts_rejected[index]; 1998 }); 1999 2000 function isScriptInServiceDomain(script) { 2001 const domains = Object.values(self.services) 2002 .reduce((acc, category) => acc.concat(category.domains), []); 2003 2004 return domains.some(domain => scriptContainsDomain(script, domain)); 2005 } 2006 2007 function scriptContainsDomain(script, domain) { 2008 return script.indexOf(domain) !== -1; 2009 } 2010 } 2011 }; 2012 } 2013</script>
vendor: 68 bytes, lines 2013-2014
2013 2014<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
2014GTM-M58G7NBG
vendor: 101 bytes, lines 2014-2015
2014" 2015 height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
2016<div x-data="{ formKey: '' }" x-init="formKey = hyva.getFormKey()"> 2017 <input name="form_key" type="hidden" :value="formKey"/> 2018</div> 2019<style> 2020 @font-face {font-family: 'Moderat'; src: url(https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/fonts/Moderat-Light.woff2) format('woff2'); font-weight: 300; font-style: normal; font-display: swap; } @font-face { font-family: 'Moderat'; src: url(https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/fonts/Moderat-Regular.woff2) format('woff2'); font-weight: 400; font-style: normal; font-display: swap; } @font-face { font-family: 'Moderat'; src: url(https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/fonts/Moderat-Medium.woff2) format('woff2'); font-weight: 500; font-style: normal; font-display: swap; } @font-face { font-family: 'Moderat'; src: url(https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/fonts/Moderat-Bold.woff2) format('woff2'); font-weight: 700; font-style: normal; font-display: swap; } 2021 @font-face {font-family: 'GT Super Display'; src: url(https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/fonts/GT-Super-Display-Regular.woff2) format('woff2'); font-weight: 400; font-style: normal; font-display: swap; } @font-face { font-family: 'GT Super Display'; src: url(https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/fonts/GT-Super-Display-Light-Italic.woff2) format('woff2'); font-weight: 300; font-style: italic; font-display: swap; } 2022</style> 2023<div class="page-wrapper js-page-wrapper"><header class="page-header sticky-header js-page-header sticky z-30"> <!-- HyväCMS cms_block --> 2024 2025<div 2026 id="smart-content-6ab59182089ff" 2027 class="smart-content-wrapper w-full" 2028 > 2029 <div class="max-w-none" 2030 > 2031 <section class="cmsb39-bg-[#1A1919] cmsb39-text-white cmsb39-overflow-hidden cmsb39-font-sans cmsb39-border-b cmsb39-border-white/10"> 2032 <div class="cmsb39-max-w-7xl cmsb39-mx-auto"> 2033 <div class="cmsb39-h-[38px] cmsb39-flex cmsb39-items-center cmsb39-justify-center cmsb39-px-4 cmsb39-sm:px-6 cmsb39-lg:px-8"> 2034 <div class="cmsb39-text-[11px] cmsb39-sm:text-xs cmsb39-md:text-sm cmsb39-font-normal cmsb39-tracking-wide cmsb39-text-center cmsb39-leading-tight"> 2035 <span>Ventresca de Bonito del Norte "Colección". Disponible hasta 28/09. ¡Unidades Limitadas!</span> 2036 </div> 2037 </div> 2038 </div> 2039</section> </div> 2040 </div> 2041
2041<script> 2042 window.addEventListener('thirdparty-trigger', (event) => { 2043 let script = document.createElement('script'); 2044 script.async = true; 2045 script.src = "https://static.klaviyo.com/onsite/js/klaviyo.js?company_id=VLMp5V"; 2046 2047 // Once Klaviyo is downloaded from cdn it will trigger new event to others could subscribe it 2048 script.addEventListener('load', () => { 2049 window.dispatchEvent(new CustomEvent('klaviyo-ready', {})) 2050 }); 2051 2052 let entry = document.getElementsByTagName('script')[0]; 2053 entry.parentNode.insertBefore(script, entry); 2054 }); 2055 </script>
2055 2056 <div x-data="initKlaviyoCustomerTracking()" x-init="trackKlaviyoCustomerData()"></div> 2057
2057<script> 2058 'use strict'; 2059 function initKlaviyoCustomerTracking() { 2060 return { 2061 trackKlaviyoCustomerData() { 2062 const privateContentLoadedIsReady = new Promise((resolve) => { 2063 window.addEventListener('private-content-loaded', (event) => { 2064 const data = event.detail.data; 2065 2066 if (data && data.customer ) { 2067 resolve(data); 2068 } 2069 }) 2070 }); 2071 const klaviyoIsReady = new Promise((resolve) => { 2072 window.addEventListener('klaviyo-ready', () => { 2073 var klaviyoInterval = setInterval(function() { 2074 if( typeof window.klaviyo !== "undefined" ){ 2075 clearInterval(klaviyoInterval); 2076 return resolve(); 2077 } 2078 }, 500); 2079 }); 2080 }); 2081 2082 const allPromises = [privateContentLoadedIsReady, klaviyoIsReady]; 2083 try { 2084 Promise.all(allPromises).then(this.sendCustomerDataToKlaviyo) 2085 } catch (e) { 2086 // Promise.all is not supported by this browser 2087 this.promiseAllPolyfill(allPromises).then(this.sendCustomerDataToKlaviyo); 2088 console.error(e); 2089 } 2090 }, 2091 sendCustomerDataToKlaviyo(data) { 2092 let klaviyo = window.klaviyo || []; 2093 data = data.shift(); 2094 let customer = data.customer; 2095 let customer_klaviyo = data.customer_klaviyo; 2096 2097 if(customer.email) { 2098 const identifyPayload = { 2099 '$email': customer.email || '', 2100 '$first_name': customer.firstname || '', 2101 '$last_name': customer.lastname || '', 2102 }; 2103 2104 if (customer_klaviyo && typeof customer_klaviyo === 'object') { 2105 for (const key in customer_klaviyo) { 2106 if (customer_klaviyo.hasOwnProperty(key)) { 2107 identifyPayload[key] = customer_klaviyo[key]; 2108 } 2109 } 2110 } 2111 klaviyo.identify(identifyPayload); 2112 } 2113 }, 2114 promiseAllPolyfill(promises) { 2115 const results = []; 2116 let completed = 0; 2117 2118 return new Promise((resolve, reject) => { 2119 promises.forEach((value, index) => { 2120 Promise.resolve(value) 2121 .then((res) => { 2122 results[index] = res; 2123 completed++; 2124 if (completed === promises.length) { 2125 resolve(results); 2126 } 2127 }).catch((err) => reject(err)); 2128 }); 2129 }); 2130 } 2131 } 2132 } 2133 2134 </script>
2134 2135<div id="preheader-container" class="preheader-container"><div></div> 2136</div>
2137<script> 2138 function initHeader() { 2139 return { 2140 searchOpen: false, 2141 fixed: false, 2142 headerPositionSticky: false, 2143 headerScrolled: false, 2144 headerSticky: false, 2145 hover: false, 2146 active: false, 2147 touchevents: false, 2148 cart: {}, 2149 init() { 2150 this.$watch('headerPositionSticky', (value) => this.isSticky(value)) 2151 this.$watch('headerScrolled', (value) => this.isSticky(value)) 2152 this.$watch('headerSticky', (value) => this.isActive(value)) 2153 this.$watch('searchOpen', (value) => this.isActive(value)) 2154 this.$watch('hover', (value) => this.isActive(value)) 2155 this.$watch('fixed', (value) => this.isActive(value)) 2156 this.$watch('active', (value) => window.dispatchEvent(new CustomEvent('header-active-change', {detail: value}))); 2157 2158 if (typeof setupHeaderObserver === "function") { 2159 setupHeaderObserver(); 2160 } 2161 }, 2162 isActive(value) { 2163 this.active = (this.headerSticky || this.searchOpen || this.hover || this.fixed) 2164 }, 2165 isSticky(value) { 2166 this.headerSticky = (this.headerPositionSticky && this.headerScrolled); 2167 window.dispatchEvent(new CustomEvent('header-sticky-scrolled-change', {detail: this.headerSticky})) 2168 }, 2169 getData(data) { 2170 if (data.cart) { this.cart = data.cart } 2171 } 2172 } 2173 } 2174 2175 function initCompareHeader() { 2176 return { 2177 compareProducts: null, 2178 itemCount: 0, 2179 receiveCompareData(data) { 2180 if (data['compare-products']) { 2181 this.compareProducts = data['compare-products']; 2182 this.itemCount = this.compareProducts.count; 2183 } 2184 } 2185 } 2186 } 2187</script>
2187 2188<nav id="header" 2189 class="z-30 w-full" 2190 data-type="default" 2191 :class="{ 'fixed top-0 right-0 bottom-0 left-0 lg:relative lg:inset-auto': fixed, '': !fixed, 'active': active, '': !active }" 2192 x-data="initHeader()" 2193 @scroll.window="headerScrolled = (window.pageYOffset > header.clientHeight) ? true : false" 2194 @header-sticky-change.window="headerPositionSticky = $event.detail" 2195 @keydown.window.escape="$dispatch('search-close')" 2196 @menu-toggle-status-change=" 2197 fixed = $event.detail.open; 2198 isMobile() && (fixed ? 2199 $dispatch('lock-screen') 2200 : 2201 $dispatch('unlock-screen'))" 2202 @private-content-loaded.window="getData(event.detail.data)" 2203 @mouseover="!touchevents ? hover = true : ''" 2204 @mouseleave="!touchevents ? hover = false : ''" 2205 @touchstart="touchevents = true" 2206> 2207 <div class="border-b border-header-separator bg-header-background" 2208 :class="{ 2209 '': active, '': !active, 2210 '': headerSticky, '': !headerSticky, 2211 '': searchOpen, '': !searchOpen, 2212 '': hover, '': !hover, 2213 '': fixed, 'relative': !fixed 2214 }" 2215 > 2216 <div><div class="header-container padding-container lg:relative flex flex-row flex-wrap items-center py-2 gap-x-2 lg:py-1 lg:gap-x-6"><div id="header-menu-icon-container" class="z-20 order-1 lg:order-1"> 2217 <div class="menu-desktop hidden lg:block"> 2218 2219<nav class="mega-menu bg-white" 2220 role="navigation" 2221 aria-label="Main menu" 2222 x-data="{ ...menuActiveTracker() }" 2223 x-init="detectActiveItem()"> 2224 <ul class="flex items-center justify-center gap-2" role="menubar"> 2225 2226 <li class="group/l1 static" role="none"> 2227 <div class="relative"> 2228 <a href="https://www.serrats.com/es_es/tienda-conservas" 2229 data-item-id="item-1775820259852-eo9dhk2zk" 2230 data-item-title="TIENDA" 2231 class="relative block transition-colors duration-300 px-3 py-3 text-[13px] font-semibold leading-[1.28] text-[#1a1919] " 2232 :class="isActive('item\u002D1775820259852\u002Deo9dhk2zk') ? '' : ''" 2233 role="menuitem" 2234 aria-haspopup="true" 2235 :aria-current="isActive('item\u002D1775820259852\u002Deo9dhk2zk') ? 'page' : null" 2236 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820259852-eo9dhk2zk","link_text":"TIENDA","link_url":"https://www.serrats.com/es_es/tienda-conservas","menu_level":1,"menu_device":"desktop","menu_type":"mega","item_type":"link"}" data-gtm-identifier="item-1775820259852-eo9dhk2zk"> 2237 <span class="relative"> 2238 TIENDA <span class="absolute left-0 -bottom-1 h-0.5 bg-[#1a1919] transition-all duration-300 ease-out group-hover/l1:w-full" 2239 :class="isActive('item\u002D1775820259852\u002Deo9dhk2zk') ? 'w\u002Dfull' : 'w-0'"></span> 2240 </span> 2241 </a> 2242 </div> 2243 2244 <div class="invisible opacity-0 group-hover/l1:visible group-hover/l1:opacity-100 absolute inset-x-0 top-full z-50 transition-all duration-200 ease-out md:delay-150 md:group-hover/l1:delay-500 bg-white shadow-xl border-t border-gray-100 min-h-[450px]"> 2245 2246<div class="columns-content mx-auto py-3 px-6 lg:px-10 max-w-full"> 2247 <div class="flex gap-8 "> 2248 2249 <div class="flex-1 min-w-0"> 2250 <div class="columns-grid grid content-start grid-cols-2 gap-8"> 2251 <div class="column-item min-w-0 flex flex-col gap-4" data-column-index="0"> 2252 <div class="column-l2-group group/l2" data-item-id="item-1775820823229-qpay89791"> 2253 <a href="https://www.serrats.com/es_es/comprar-surtidos-regalo" 2254 data-item-id="item-1775820823229-qpay89791" 2255 data-item-title="CAJAS REGALO GOURMET" 2256 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2257 :class="isActive('item\u002D1775820823229\u002Dqpay89791') ? '' : ''" 2258 :aria-current="isActive('item\u002D1775820823229\u002Dqpay89791') ? 'page' : null" 2259 role="menuitem" 2260 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-qpay89791","link_text":"CAJAS REGALO GOURMET","link_url":"https://www.serrats.com/es_es/comprar-surtidos-regalo","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775820823229-qpay89791">
2261 <span class="relative"> 2262 CAJAS REGALO GOURMET <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2263 :class="isActive('item\u002D1775820823229\u002Dqpay89791') ? 'w\u002Dfull' : 'w-0'"></span> 2264 </span> 2265 </a> 2266 2267 </div> 2268 <div class="column-l2-group group/l2" data-item-id="item-1775820858446-1sffzfc9w"> 2269 <a href="https://www.serrats.com/es_es/comprar-bonito-del-norte" 2270 data-item-id="item-1775820858446-1sffzfc9w" 2271 data-item-title="Bonito del Norte" 2272 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2273 :class="isActive('item\u002D1775820858446\u002D1sffzfc9w') ? '' : ''" 2274 :aria-current="isActive('item\u002D1775820858446\u002D1sffzfc9w') ? 'page' : null" 2275 role="menuitem" 2276 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820858446-1sffzfc9w","link_text":"Bonito del Norte","link_url":"https://www.serrats.com/es_es/comprar-bonito-del-norte","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775820858446-1sffzfc9w"> 2277 <span class="relative"> 2278 Bonito del Norte <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2279 :class="isActive('item\u002D1775820858446\u002D1sffzfc9w') ? 'w\u002Dfull' : 'w-0'"></span> 2280 </span> 2281 </a> 2282 2283 </div> 2284 <div class="column-l2-group group/l2" data-item-id="item-1775820823229-uvtx2itbg"> 2285 <a href="https://www.serrats.com/es_es/comprar-ventresca-de-bonito" 2286 data-item-id="item-1775820823229-uvtx2itbg" 2287 data-item-title="Ventresca de Bonito del Norte" 2288 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2289 :class="isActive('item\u002D1775820823229\u002Duvtx2itbg') ? '' : ''" 2290 :aria-current="isActive('item\u002D1775820823229\u002Duvtx2itbg') ? 'page' : null" 2291 role="menuitem" 2292 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-uvtx2itbg","link_text":"Ventresca de Bonito del Norte","link_url":"https://www.serrats.com/es_es/comprar-ventresca-de-bonito","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775820823229-uvtx2itbg">
2293 <span class="relative"> 2294 Ventresca de Bonito del Norte <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2295 :class="isActive('item\u002D1775820823229\u002Duvtx2itbg') ? 'w\u002Dfull' : 'w-0'"></span> 2296 </span> 2297 </a> 2298 2299 </div> 2300 <div class="column-l2-group group/l2" data-item-id="item-1775820823229-uursqr6h0"> 2301 <a href="https://www.serrats.com/es_es/comprar-cogote-de-bonito" 2302 data-item-id="item-1775820823229-uursqr6h0" 2303 data-item-title="Cogote de Bonito del Norte" 2304 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2305 :class="isActive('item\u002D1775820823229\u002Duursqr6h0') ? '' : ''" 2306 :aria-current="isActive('item\u002D1775820823229\u002Duursqr6h0') ? 'page' : null" 2307 role="menuitem" 2308 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-uursqr6h0","link_text":"Cogote de Bonito del Norte","link_url":"https://www.serrats.com/es_es/comprar-cogote-de-bonito","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775820823229-uursqr6h0"> 2309 <span class="relative"> 2310 Cogote de Bonito del Norte <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2311 :class="isActive('item\u002D1775820823229\u002Duursqr6h0') ? 'w\u002Dfull' : 'w-0'"></span> 2312 </span> 2313 </a> 2314 2315 </div> 2316 <div class="column-l2-group group/l2" data-item-id="item-1775820823229-sadkjnzzy"> 2317 <a href="https://www.serrats.com/es_es/comprar-anchoas-del-cantabrico" 2318 data-item-id="item-1775820823229-sadkjnzzy" 2319 data-item-title="Anchoas del Cantábrico" 2320 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2321 :class="isActive('item\u002D1775820823229\u002Dsadkjnzzy') ? '' : ''" 2322 :aria-current="isActive('item\u002D1775820823229\u002Dsadkjnzzy') ? 'page' : null" 2323 role="menuitem" 2324 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-sadkjnzzy","link_text":"Anchoas del Cantábrico","link_url":"https://www.serrats.com/es_es/comprar-anchoas-del-cantabrico","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775820823229-sadkjnzzy">
2325 <span class="relative"> 2326 Anchoas del Cantábrico <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2327 :class="isActive('item\u002D1775820823229\u002Dsadkjnzzy') ? 'w\u002Dfull' : 'w-0'"></span> 2328 </span> 2329 </a> 2330 2331 </div> 2332 <div class="column-l2-group group/l2" data-item-id="item-1775820823229-k37xw06p5"> 2333 <a href="https://www.serrats.com/es_es/comprar-boquerones" 2334 data-item-id="item-1775820823229-k37xw06p5" 2335 data-item-title="Boquerones del Cantábrico" 2336 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2337 :class="isActive('item\u002D1775820823229\u002Dk37xw06p5') ? '' : ''" 2338 :aria-current="isActive('item\u002D1775820823229\u002Dk37xw06p5') ? 'page' : null" 2339 role="menuitem" 2340 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-k37xw06p5","link_text":"Boquerones del Cantábrico","link_url":"https://www.serrats.com/es_es/comprar-boquerones","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775820823229-k37xw06p5"> 2341 <span class="relative"> 2342 Boquerones del Cantábrico <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2343 :class="isActive('item\u002D1775820823229\u002Dk37xw06p5') ? 'w\u002Dfull' : 'w-0'"></span> 2344 </span> 2345 </a> 2346 2347 </div> 2348 <div class="column-l2-group group/l2" data-item-id="item-1775820823229-h5q4cad1k"> 2349 <a href="https://www.serrats.com/es_es/comprar-sardinillas-en-conserva" 2350 data-item-id="item-1775820823229-h5q4cad1k" 2351 data-item-title="Sardinillas "txikis"" 2352 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2353 :class="isActive('item\u002D1775820823229\u002Dh5q4cad1k') ? '' : ''" 2354 :aria-current="isActive('item\u002D1775820823229\u002Dh5q4cad1k') ? 'page' : null" 2355 role="menuitem" 2356 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-h5q4cad1k","link_text":"Sardinillas \"txikis\"","link_url":"https://www.serrats.com/es_es/comprar-sardinillas-en-conserva","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775820823229-h5q4cad1k">
2357 <span class="relative"> 2358 Sardinillas "txikis" <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2359 :class="isActive('item\u002D1775820823229\u002Dh5q4cad1k') ? 'w\u002Dfull' : 'w-0'"></span> 2360 </span> 2361 </a> 2362 2363 </div> 2364 <div class="column-l2-group group/l2" data-item-id="item-1775820823229-8f66si65q"> 2365 <a href="https://www.serrats.com/es_es/comprar-atun-claro-en-conserva" 2366 data-item-id="item-1775820823229-8f66si65q" 2367 data-item-title="Atún Claro" 2368 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2369 :class="isActive('item\u002D1775820823229\u002D8f66si65q') ? '' : ''" 2370 :aria-current="isActive('item\u002D1775820823229\u002D8f66si65q') ? 'page' : null" 2371 role="menuitem" 2372 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-8f66si65q","link_text":"Atún Claro","link_url":"https://www.serrats.com/es_es/comprar-atun-claro-en-conserva","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775820823229-8f66si65q"> 2373 <span class="relative"> 2374 Atún Claro <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2375 :class="isActive('item\u002D1775820823229\u002D8f66si65q') ? 'w\u002Dfull' : 'w-0'"></span> 2376 </span> 2377 </a> 2378 2379 </div> 2380 <div class="column-l2-group group/l2" data-item-id="item-1775822718956-k5n51ykdj"> 2381 <a href="https://www.serrats.com/es_es/ofertas" 2382 data-item-id="item-1775822718956-k5n51ykdj" 2383 data-item-title="OFERTAS" 2384 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2385 :class="isActive('item\u002D1775822718956\u002Dk5n51ykdj') ? '' : ''" 2386 :aria-current="isActive('item\u002D1775822718956\u002Dk5n51ykdj') ? 'page' : null" 2387 role="menuitem" 2388 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775822718956-k5n51ykdj","link_text":"OFERTAS","link_url":"https://www.serrats.com/es_es/ofertas","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775822718956-k5n51ykdj">
2389 <span class="relative"> 2390 OFERTAS <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2391 :class="isActive('item\u002D1775822718956\u002Dk5n51ykdj') ? 'w\u002Dfull' : 'w-0'"></span> 2392 </span> 2393 </a> 2394 2395 </div> 2396 </div> 2397 <div class="column-item min-w-0 flex flex-col gap-4" data-column-index="1"> 2398 <div class="column-l2-group group/l2" data-item-id="item-1775821963737-n7ry1n47l"> 2399 <a href="https://www.serrats.com/es_es/comprar-mejillones-en-conserva" 2400 data-item-id="item-1775821963737-n7ry1n47l" 2401 data-item-title="Mejillones grandes" 2402 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2403 :class="isActive('item\u002D1775821963737\u002Dn7ry1n47l') ? '' : ''" 2404 :aria-current="isActive('item\u002D1775821963737\u002Dn7ry1n47l') ? 'page' : null" 2405 role="menuitem" 2406 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775821963737-n7ry1n47l","link_text":"Mejillones grandes","link_url":"https://www.serrats.com/es_es/comprar-mejillones-en-conserva","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775821963737-n7ry1n47l"> 2407 <span class="relative"> 2408 Mejillones grandes <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2409 :class="isActive('item\u002D1775821963737\u002Dn7ry1n47l') ? 'w\u002Dfull' : 'w-0'"></span> 2410 </span> 2411 </a> 2412 2413 </div> 2414 <div class="column-l2-group group/l2" data-item-id="item-1775821963737-oqfg8ydit"> 2415 <a href="https://www.serrats.com/es_es/comprar-navajas" 2416 data-item-id="item-1775821963737-oqfg8ydit" 2417 data-item-title="Navajas de las Rías Gallegas" 2418 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2419 :class="isActive('item\u002D1775821963737\u002Doqfg8ydit') ? '' : ''" 2420 :aria-current="isActive('item\u002D1775821963737\u002Doqfg8ydit') ? 'page' : null" 2421 role="menuitem" 2422 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775821963737-oqfg8ydit","link_text":"Navajas de las RÃas Gallegas","link_url":"https://www.serrats.com/es_es/comprar-navajas","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775821963737-oqfg8ydit">
2423 <span class="relative"> 2424 Navajas de las RÃas Gallegas <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2425 :class="isActive('item\u002D1775821963737\u002Doqfg8ydit') ? 'w\u002Dfull' : 'w-0'"></span> 2426 </span> 2427 </a> 2428 2429 </div> 2430 <div class="column-l2-group group/l2" data-item-id="item-1779083788975-zmbrin44ws"> 2431 <a href="https://www.serrats.com/es_es/comprar-zamburinas-en-conserva" 2432 data-item-id="item-1779083788975-zmbrin44ws" 2433 data-item-title="Zamburiñas de las Rías Gallegas" 2434 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2435 :class="isActive('item\u002D1779083788975\u002Dzmbrin44ws') ? '' : ''" 2436 :aria-current="isActive('item\u002D1779083788975\u002Dzmbrin44ws') ? 'page' : null" 2437 role="menuitem" 2438 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1779083788975-zmbrin44ws","link_text":"Zamburiñas de las RÃas Gallegas","link_url":"https://www.serrats.com/es_es/comprar-zamburinas-en-conserva","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1779083788975-zmbrin44ws"> 2439 <span class="relative"> 2440 Zamburiñas de las RÃas Gallegas <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2441 :class="isActive('item\u002D1779083788975\u002Dzmbrin44ws') ? 'w\u002Dfull' : 'w-0'"></span> 2442 </span> 2443 </a> 2444 2445 </div> 2446 <div class="column-l2-group group/l2" data-item-id="item-1775821963737-lnkpv5ycz"> 2447 <a href="https://www.serrats.com/es_es/comprar-berberechos-en-conserva" 2448 data-item-id="item-1775821963737-lnkpv5ycz" 2449 data-item-title="Berberechos de las Rías Gallegas" 2450 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2451 :class="isActive('item\u002D1775821963737\u002Dlnkpv5ycz') ? '' : ''" 2452 :aria-current="isActive('item\u002D1775821963737\u002Dlnkpv5ycz') ? 'page' : null" 2453 role="menuitem" 2454 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775821963737-lnkpv5ycz","link_text":"Berberechos de las RÃas Gallegas","link_url":"https://www.serrats.com/es_es/comprar-berberechos-en-conserva","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775821963737-lnkpv5ycz">
2455 <span class="relative"> 2456 Berberechos de las RÃas Gallegas <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2457 :class="isActive('item\u002D1775821963737\u002Dlnkpv5ycz') ? 'w\u002Dfull' : 'w-0'"></span> 2458 </span> 2459 </a> 2460 2461 </div> 2462 <div class="column-l2-group group/l2" data-item-id="item-1775821963737-llueymm1s"> 2463 <a href="https://www.serrats.com/es_es/comprar-caviar-de-oricios" 2464 data-item-id="item-1775821963737-llueymm1s" 2465 data-item-title="Caviar de Erizo de Mar" 2466 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2467 :class="isActive('item\u002D1775821963737\u002Dllueymm1s') ? '' : ''" 2468 :aria-current="isActive('item\u002D1775821963737\u002Dllueymm1s') ? 'page' : null" 2469 role="menuitem" 2470 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775821963737-llueymm1s","link_text":"Caviar de Erizo de Mar","link_url":"https://www.serrats.com/es_es/comprar-caviar-de-oricios","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775821963737-llueymm1s"> 2471 <span class="relative"> 2472 Caviar de Erizo de Mar <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2473 :class="isActive('item\u002D1775821963737\u002Dllueymm1s') ? 'w\u002Dfull' : 'w-0'"></span> 2474 </span> 2475 </a> 2476 2477 </div> 2478 <div class="column-l2-group group/l2" data-item-id="item-1775822813740-ebac7v7ey"> 2479 <a href="https://www.serrats.com/es_es/comprar-productos-coleccion" 2480 data-item-id="item-1775822813740-ebac7v7ey" 2481 data-item-title="Productos EDICIÓN LIMITADA" 2482 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2483 :class="isActive('item\u002D1775822813740\u002Debac7v7ey') ? '' : ''" 2484 :aria-current="isActive('item\u002D1775822813740\u002Debac7v7ey') ? 'page' : null" 2485 role="menuitem" 2486 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775822813740-ebac7v7ey","link_text":"Productos EDICIÃN LIMITADA","link_url":"https://www.serrats.com/es_es/comprar-productos-coleccion","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775822813740-ebac7v7ey">
2487 <span class="relative"> 2488 Productos EDICIÃN LIMITADA <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2489 :class="isActive('item\u002D1775822813740\u002Debac7v7ey') ? 'w\u002Dfull' : 'w-0'"></span> 2490 </span> 2491 </a> 2492 2493 </div> 2494 <div class="column-l2-group group/l2" data-item-id="item-1775821963737-bs0b1ukz5"> 2495 <a href="https://www.serrats.com/es_es/comprar-productos-ecologicos" 2496 data-item-id="item-1775821963737-bs0b1ukz5" 2497 data-item-title="Conservas ecológicas" 2498 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2499 :class="isActive('item\u002D1775821963737\u002Dbs0b1ukz5') ? '' : ''" 2500 :aria-current="isActive('item\u002D1775821963737\u002Dbs0b1ukz5') ? 'page' : null" 2501 role="menuitem" 2502 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775821963737-bs0b1ukz5","link_text":"Conservas ecológicas","link_url":"https://www.serrats.com/es_es/comprar-productos-ecologicos","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1775821963737-bs0b1ukz5"> 2503 <span class="relative"> 2504 Conservas ecológicas <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2505 :class="isActive('item\u002D1775821963737\u002Dbs0b1ukz5') ? 'w\u002Dfull' : 'w-0'"></span> 2506 </span> 2507 </a> 2508 2509 </div> 2510 <div class="column-l2-group group/l2" data-item-id="item-1779083788976-cnatu43ws"> 2511 <a href="https://www.serrats.com/es_es/comprar-conservas-al-natural" 2512 data-item-id="item-1779083788976-cnatu43ws" 2513 data-item-title="Conservas al Natural" 2514 class="inline-block transition-colors duration-150 py-1.5 text-base font-normal text-black " 2515 :class="isActive('item\u002D1779083788976\u002Dcnatu43ws') ? '' : ''" 2516 :aria-current="isActive('item\u002D1779083788976\u002Dcnatu43ws') ? 'page' : null" 2517 role="menuitem" 2518 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1779083788976-cnatu43ws","link_text":"Conservas al Natural","link_url":"https://www.serrats.com/es_es/comprar-conservas-al-natural","menu_level":2,"menu_device":"desktop","menu_type":"mega","item_type":"category"}" data-gtm-identifier="item-1779083788976-cnatu43ws">
2519 <span class="relative"> 2520 Conservas al Natural <span class="absolute left-0 -bottom-0.5 h-0.5 bg-black transition-all duration-300 ease-out group-hover/l2:w-full group-has-[.l3-active]/l2:w-0 group-has-[li:hover]/l2:w-0" 2521 :class="isActive('item\u002D1779083788976\u002Dcnatu43ws') ? 'w\u002Dfull' : 'w-0'"></span> 2522 </span> 2523 </a> 2524 2525 </div> 2526 </div> 2527 </div> 2528 </div> 2529 2530 2531<div class="menu-media-panel min-w-0 cursor-pointer w-6/12 " 2532 data-item-id="item-1775820259852-eo9dhk2zk" 2533 data-item-title="TIENDA"> 2534 2535 <div class="menu-cms-block max-w-none"> 2536 <style data-jit-css data-liveview-style-type="cms_block" data-liveview-style-id="6">.cmsb6-mb-4 { 2537margin-bottom: 1rem 2538} 2539.cmsb6-mb-8 { 2540margin-bottom: 2rem 2541} 2542.cmsb6-flex { 2543display: flex 2544} 2545.cmsb6-h-11 { 2546height: 2.75rem 2547} 2548.cmsb6-w-11 { 2549width: 2.75rem 2550} 2551.cmsb6-max-w-xl { 2552max-width: 36rem 2553} 2554.cmsb6-flex-shrink-0 { 2555flex-shrink: 0 2556} 2557.cmsb6-flex-col { 2558flex-direction: column 2559} 2560.cmsb6-items-center { 2561align-items: center 2562} 2563.cmsb6-justify-center { 2564justify-content: center 2565} 2566.cmsb6-gap-4 { 2567gap: 1rem 2568} 2569.cmsb6-gap-6 { 2570gap: 1.5rem 2571} 2572.cmsb6-rounded-full { 2573border-radius: 9999px 2574} 2575.cmsb6-border-b { 2576border-bottom-width: 1px 2577} 2578.cmsb6-border-gray-100 { 2579--tw-border-opacity: 1; 2580border-color: rgb(243 244 246 / var(--tw-border-opacity)) 2581} 2582.cmsb6-bg-white { 2583--tw-bg-opacity: 1; 2584background-color: rgb(255 255 255 / var(--tw-bg-opacity)) 2585} 2586.cmsb6-bg-yellow-50 { 2587--tw-bg-opacity: 1; 2588background-color: rgb(254 252 232 / var(--tw-bg-opacity)) 2589} 2590.cmsb6-px-6 { 2591padding-left: 1.5rem; 2592padding-right: 1.5rem 2593} 2594.cmsb6-text-2xl { 2595font-size: 1.375rem; 2596line-height: 1.255 2597} 2598.cmsb6-text-lg { 2599font-size: 1.125rem; 2600line-height: 1.255 2601} 2602.cmsb6-font-bold {
2603font-weight: 700 2604} 2605.cmsb6-tracking-tight { 2606letter-spacing: -0.025em 2607} 2608.cmsb6-text-gray-800 { 2609--tw-text-opacity: 1; 2610color: rgb(31 41 55 / var(--tw-text-opacity)) 2611} 2612.cmsb6-text-gray-900 { 2613--tw-text-opacity: 1; 2614color: rgb(17 24 39 / var(--tw-text-opacity)) 2615} 2616.cmsb6-text-orange-500 { 2617--tw-text-opacity: 1; 2618color: rgb(249 115 22 / var(--tw-text-opacity)) 2619}</style> <!-- HyväCMS cms_block --> 2620 2621<div 2622 id="smart-content-6ab4ef72252a6" 2623 class="smart-content-wrapper w-full" 2624 > 2625 <div class="max-w-none" 2626 > 2627 <section class="cmsb6-bg-white"> 2628 <div class="cmsb6-max-w-xl cmsb6-px-6"> 2629 <div class="cmsb6-mb-8"> 2630 <h2 class="cmsb6-text-2xl cmsb6-font-bold cmsb6-text-gray-900 cmsb6-mb-4"><span>Nuestros compromisos</span></h2> 2631 <div class="cmsb6-border-b cmsb6-border-gray-100"></div> 2632 </div> 2633 <div class="cmsb6-flex cmsb6-flex-col cmsb6-gap-6"> 2634 2635 <div class="cmsb6-flex cmsb6-items-center cmsb6-gap-4" data-liveview-group="grupo_naturales" data-liveview-group-name="Compromiso 1"> 2636 <div class="cmsb6-flex-shrink-0 cmsb6-w-11 cmsb6-h-11 cmsb6-rounded-full cmsb6-bg-yellow-50 cmsb6-flex cmsb6-items-center cmsb6-justify-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="cmsb6-text-orange-500" width="20" height="20" role="img"><path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"/><title>bold/check</title></svg> 2637</div> 2638 <span class="cmsb6-text-lg cmsb6-font-bold cmsb6-text-gray-800 cmsb6-tracking-tight"><span>100% NATURALES</span></span> 2639 </div> 2640 2641 2642 <div class="cmsb6-flex cmsb6-items-center cmsb6-gap-4" data-liveview-group="grupo_gluten" data-liveview-group-name="Compromiso 2"> 2643 <div class="cmsb6-flex-shrink-0 cmsb6-w-11 cmsb6-h-11 cmsb6-rounded-full cmsb6-bg-yellow-50 cmsb6-flex cmsb6-items-center cmsb6-justify-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="cmsb6-text-orange-500" width="20" height="20" role="img"><path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"/><title>bold/check</title></svg> 2644</div> 2645 <span class="cmsb6-text-lg cmsb6-font-bold cmsb6-text-gray-800 cmsb6-tracking-tight"><span>SIN GLUTEN</span></span> 2646 </div> 2647 2648 2649 <div class="cmsb6-flex cmsb6-items-center cmsb6-gap-4" data-liveview-group="grupo_sostenibles" data-liveview-group-name="Compromiso 3"> 2650 <div class="cmsb6-flex-shrink-0 cmsb6-w-11 cmsb6-h-11 cmsb6-rounded-full cmsb6-bg-yellow-50 cmsb6-flex cmsb6-items-center cmsb6-justify-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="cmsb6-text-orange-500" width="20" height="20" role="img"><path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"/><title>bold/check</title></svg> 2651</div> 2652 <span class="cmsb6-text-lg cmsb6-font-bold cmsb6-text-gray-800 cmsb6-tracking-tight"><span>SOSTENIBLES</span></span> 2653 </div> 2654 2655 2656 <div class="cmsb6-flex cmsb6-items-center cmsb6-gap-4" data-liveview-group="grupo_artesana" data-liveview-group-name="Compromiso 4"> 2657 <div class="cmsb6-flex-shrink-0 cmsb6-w-11 cmsb6-h-11 cmsb6-rounded-full cmsb6-bg-yellow-50 cmsb6-flex cmsb6-items-center cmsb6-justify-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="cmsb6-text-orange-500" width="20" height="20" role="img"><path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"/><title>bold/check</title></svg> 2658</div> 2659 <span class="cmsb6-text-lg cmsb6-font-bold cmsb6-text-gray-800 cmsb6-tracking-tight"><span>ELABORACIÃN ARTESANA</span></span> 2660 </div> 2661 2662 2663 <div class="cmsb6-flex cmsb6-items-center cmsb6-gap-4" data-liveview-group="grupo_satisfaccion" data-liveview-group-name="Compromiso 5"> 2664 <div class="cmsb6-flex-shrink-0 cmsb6-w-11 cmsb6-h-11 cmsb6-rounded-full cmsb6-bg-yellow-50 cmsb6-flex cmsb6-items-center cmsb6-justify-center"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="cmsb6-text-orange-500" width="20" height="20" role="img"><path d="M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z"/><title>bold/check</title></svg> 2665</div>
2666 <span class="cmsb6-text-lg cmsb6-font-bold cmsb6-text-gray-800 cmsb6-tracking-tight"><span>GARANTÃA DE SATISFACCIÃN</span></span> 2667 </div> 2668 2669 </div> 2670 </div> 2671</section> </div> 2672 </div> 2673 </div> 2674 </div> 2675 </div> 2676</div> 2677 </div> 2678 </li> 2679 2680 <li class="group/l1" role="none"> 2681 <a href="https://www.serrats.com/es_es/club-serrats" 2682 data-item-id="item-1775820446650-j8gefjoee" 2683 data-item-title="CLUB SERRATS" 2684 class="relative block transition-colors duration-300 px-3 py-3 text-[13px] font-semibold leading-[1.28] text-[#1a1919] " 2685 :class="isActive('item\u002D1775820446650\u002Dj8gefjoee') ? '' : ''" 2686 role="menuitem" 2687 :aria-current="isActive('item\u002D1775820446650\u002Dj8gefjoee') ? 'page' : null" 2688 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820446650-j8gefjoee","link_text":"CLUB SERRATS","link_url":"https://www.serrats.com/es_es/club-serrats","menu_level":1,"menu_device":"desktop","menu_type":"mega","item_type":"link"}" data-gtm-identifier="item-1775820446650-j8gefjoee"> 2689 <span class="relative"> 2690 CLUB SERRATS <span class="absolute left-0 -bottom-1 h-0.5 bg-[#1a1919] transition-all duration-300 ease-out group-hover/l1:w-full" 2691 :class="isActive('item\u002D1775820446650\u002Dj8gefjoee') ? 'w\u002Dfull' : 'w-0'"></span> 2692 </span> 2693 </a> 2694 </li> 2695 2696 <li class="group/l1 static" role="none"> 2697 <div class="relative"> 2698 <a href="https://www.serrats.com/es_es/bermeo-nuestro-origen" 2699 data-item-id="item-1775820474368-v3tn4p8ix" 2700 data-item-title="CONÓCENOS" 2701 class="relative block transition-colors duration-300 px-3 py-3 text-[13px] font-semibold leading-[1.28] text-[#1a1919] " 2702 :class="isActive('item\u002D1775820474368\u002Dv3tn4p8ix') ? '' : ''" 2703 role="menuitem" 2704 aria-haspopup="true" 2705 :aria-current="isActive('item\u002D1775820474368\u002Dv3tn4p8ix') ? 'page' : null" 2706 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820474368-v3tn4p8ix","link_text":"CONÃCENOS","link_url":"https://www.serrats.com/es_es/bermeo-nuestro-origen","menu_level":1,"menu_device":"desktop","menu_type":"mega","item_type":"link"}" data-gtm-identifier="item-1775820474368-v3tn4p8ix"> 2707 <span class="relative"> 2708 CONÃCENOS <span class="absolute left-0 -bottom-1 h-0.5 bg-[#1a1919] transition-all duration-300 ease-out group-hover/l1:w-full" 2709 :class="isActive('item\u002D1775820474368\u002Dv3tn4p8ix') ? 'w\u002Dfull' : 'w-0'"></span> 2710 </span> 2711 </a> 2712 </div> 2713 2714 <div class="invisible opacity-0 group-hover/l1:visible group-hover/l1:opacity-100 absolute inset-x-0 top-full z-50 transition-all duration-200 ease-out md:delay-150 md:group-hover/l1:delay-500 bg-white shadow-xl border-t border-gray-100 min-h-[450px]"> 2715 2716<div class="flex min-h-[320px] justify-center" 2717 x-data="{ 2718 activeTab: 0, 2719 hoverTab: 0, 2720 timeout: null, 2721 hover(i) { 2722 this.hoverTab = i; 2723 clearTimeout(this.timeout); 2724 if (i !== this.activeTab) { 2725 this.timeout = setTimeout(() => this.activeTab = i, 700); 2726 } 2727 }, 2728 leave() { 2729 clearTimeout(this.timeout); 2730 this.hoverTab = this.activeTab; 2731 } 2732 }"> 2733 2734 2735 2736<div class="menu-media-panel min-w-0 cursor-pointer w-full " 2737 data-item-id="item-1775820474368-v3tn4p8ix" 2738 data-item-title="CONÓCENOS"> 2739 2740 <div class="menu-cms-block max-w-none"> 2741 <style data-jit-css data-liveview-style-type="cms_block" data-liveview-style-id="7">.cmsb7-container { 2742width: 100%; 2743margin-right: auto; 2744margin-left: auto; 2745padding-right: 1rem; 2746padding-left: 1rem 2747} 2748@media (min-width: 640px) { 2749.cmsb7-container { 2750max-width: 640px 2751} 2752} 2753@media (min-width: 768px) { 2754.cmsb7-container { 2755max-width: 768px 2756} 2757} 2758@media (min-width: 1024px) { 2759.cmsb7-container { 2760max-width: 1024px 2761} 2762} 2763@media (min-width: 1280px) { 2764.cmsb7-container { 2765max-width: 1280px 2766} 2767} 2768@media (min-width: 1536px) { 2769.cmsb7-container { 2770max-width: 1536px 2771} 2772} 2773.cmsb7-absolute { 2774position: absolute 2775} 2776.cmsb7-relative { 2777position: relative 2778} 2779.cmsb7-inset-0 { 2780inset: 0px 2781} 2782.cmsb7-mb-6 { 2783margin-bottom: 1.5rem 2784}
2785.cmsb7-ml-2 { 2786margin-left: 0.5rem 2787} 2788.cmsb7-block { 2789display: block 2790} 2791.cmsb7-flex { 2792display: flex 2793} 2794.cmsb7-table { 2795display: table 2796} 2797.cmsb7-grid { 2798display: grid 2799} 2800.cmsb7-aspect-\[16\/9\] { 2801aspect-ratio: 16/9 2802} 2803.cmsb7-h-full { 2804height: 100% 2805} 2806.cmsb7-w-full { 2807width: 100% 2808} 2809.cmsb7-grid-cols-1 { 2810grid-template-columns: repeat(1, minmax(0, 1fr)) 2811} 2812.cmsb7-items-center { 2813align-items: center 2814} 2815.cmsb7-justify-center { 2816justify-content: center 2817} 2818.cmsb7-gap-6 { 2819gap: 1.5rem 2820} 2821.cmsb7-overflow-hidden { 2822overflow: hidden 2823} 2824.cmsb7-rounded-xl { 2825border-radius: 0.75rem 2826} 2827.cmsb7-bg-black\/40 { 2828background-color: rgb(22 23 26 / 0.4) 2829} 2830.cmsb7-bg-white { 2831--tw-bg-opacity: 1; 2832background-color: rgb(255 255 255 / var(--tw-bg-opacity)) 2833} 2834.cmsb7-object-cover { 2835object-fit: cover 2836} 2837.cmsb7-p-6 { 2838padding: 1.5rem 2839} 2840.cmsb7-py-8 { 2841padding-top: 2rem; 2842padding-bottom: 2rem 2843} 2844.cmsb7-text-center { 2845text-align: center 2846} 2847.cmsb7-font-serif { 2848font-family: "GT Super Display", ui-serif, serif 2849} 2850.cmsb7-text-2xl { 2851font-size: 1.375rem; 2852line-height: 1.255 2853} 2854.cmsb7-text-4xl { 2855font-size: 1.625rem; 2856line-height: 1.255 2857} 2858.cmsb7-font-bold {
2859font-weight: 700 2860} 2861.cmsb7-font-light { 2862font-weight: 300 2863} 2864.cmsb7-italic { 2865font-style: italic 2866} 2867.cmsb7-text-gray-900 { 2868--tw-text-opacity: 1; 2869color: rgb(17 24 39 / var(--tw-text-opacity)) 2870} 2871.cmsb7-text-white { 2872--tw-text-opacity: 1; 2873color: rgb(255 255 255 / var(--tw-text-opacity)) 2874} 2875.cmsb7-shadow-md { 2876--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); 2877--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); 2878box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow) 2879} 2880.cmsb7-transition-transform { 2881transition-property: transform; 2882transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); 2883transition-duration: 150ms 2884} 2885.cmsb7-duration-500 { 2886transition-duration: 500ms 2887} 2888.cmsb7-group:hover .cmsb7-group-hover\:scale-110 { 2889--tw-scale-x: 1.1; 2890--tw-scale-y: 1.1; 2891transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) 2892} 2893@media (min-width: 768px) { 2894.cmsb7-md\:grid-cols-3 { 2895grid-template-columns: repeat(3, minmax(0, 1fr)) 2896} 2897.cmsb7-md\:text-4xl { 2898font-size: 1.625rem; 2899line-height: 1.255 2900} 2901.cmsb7-md\:text-6xl { 2902font-size: 1.875rem; 2903line-height: 1.255 2904} 2905}</style> <!-- HyväCMS cms_block --> 2906 2907<div 2908 id="smart-content-6ab4ef72322e8" 2909 class="smart-content-wrapper cmsb7-container mx-auto" 2910 > 2911 <div class="max-w-none" 2912 > 2913 <section class="cmsb7-py-8 cmsb7-bg-white"> 2914 <div> 2915 <div class="cmsb7-text-center cmsb7-mb-6"> 2916 <h2 class="cmsb7-text-4xl cmsb7-md:text-6xl cmsb7-font-light cmsb7-text-gray-900 font-secondary"> 2917 <span class="cmsb7-font-bold"><span>Pasión por lo auténtico</span></span> 2918 <span class="cmsb7-italic cmsb7-font-serif cmsb7-ml-2"><span>es pasión por...</span></span> 2919 </h2> 2920 </div> 2921 <div class="cmsb7-grid cmsb7-grid-cols-1 cmsb7-md:grid-cols-3 cmsb7-gap-6"> 2922 <a href="https://www.serrats.com/es_es/bermeo-nuestro-origen" class="cmsb7-relative cmsb7-group cmsb7-aspect-[16/9] cmsb7-overflow-hidden cmsb7-rounded-xl cmsb7-shadow-md cmsb7-block"> 2923 <img src="https://www.serrats.com/media/cms/menu/conocenos-bermeo-origen.jpg" alt="Bermeo" class="cmsb7-absolute cmsb7-inset-0 cmsb7-w-full cmsb7-h-full cmsb7-object-cover cmsb7-transition-transform cmsb7-duration-500 cmsb7-group-hover:scale-110" loading="lazy"> 2924 <div class="cmsb7-absolute cmsb7-inset-0 cmsb7-bg-black/40 cmsb7-flex cmsb7-items-center cmsb7-justify-center cmsb7-p-6 cmsb7-text-center"> 2925 <h3 class="cmsb7-text-white cmsb7-text-2xl cmsb7-md:text-4xl cmsb7-font-light font-secondary"><span>Bermeo, nuestro origen</span></h3> 2926 </div> 2927 </a> 2928 2929 <a href="https://www.serrats.com/es_es/seleccionar-mejor-mar" class="cmsb7-relative cmsb7-group cmsb7-aspect-[16/9] cmsb7-overflow-hidden cmsb7-rounded-xl cmsb7-shadow-md cmsb7-block"> 2930 <img src="https://www.serrats.com/media/cms/menu/conocenos-mejor-del-mar.jpg" alt="Mar" class="cmsb7-absolute cmsb7-inset-0 cmsb7-w-full cmsb7-h-full cmsb7-object-cover cmsb7-transition-transform cmsb7-duration-500 cmsb7-group-hover:scale-110" loading="lazy"> 2931 <div class="cmsb7-absolute cmsb7-inset-0 cmsb7-bg-black/40 cmsb7-flex cmsb7-items-center cmsb7-justify-center cmsb7-p-6 cmsb7-text-center"> 2932 <h3 class="cmsb7-text-white cmsb7-text-2xl cmsb7-md:text-4xl cmsb7-font-light font-secondary"><span>Seleccionar lo mejor del mar</span></h3> 2933 </div> 2934 </a> 2935 2936 <a href="https://www.serrats.com/es_es/mantener-hecho-a-mano" class="cmsb7-relative cmsb7-group cmsb7-aspect-[16/9] cmsb7-overflow-hidden cmsb7-rounded-xl cmsb7-shadow-md cmsb7-block"> 2937 <img src="https://www.serrats.com/media/cms/menu/conocenos-hecho-a-mano.jpg" alt="ArtesanÃa" class="cmsb7-absolute cmsb7-inset-0 cmsb7-w-full cmsb7-h-full cmsb7-object-cover cmsb7-transition-transform cmsb7-duration-500 cmsb7-group-hover:scale-110" loading="lazy"> 2938 <div class="cmsb7-absolute cmsb7-inset-0 cmsb7-bg-black/40 cmsb7-flex cmsb7-items-center cmsb7-justify-center cmsb7-p-6 cmsb7-text-center"> 2939 <h3 class="cmsb7-text-white cmsb7-text-2xl cmsb7-md:text-4xl cmsb7-font-light font-secondary"><span>Mantener el hecho a mano</span></h3> 2940 </div> 2941 </a> 2942 2943 <a href="https://www.serrats.com/es_es/hacerte-disfrutar-la-mesa" class="cmsb7-relative cmsb7-group cmsb7-aspect-[16/9] cmsb7-overflow-hidden cmsb7-rounded-xl cmsb7-shadow-md cmsb7-block"> 2944 <img src="https://www.serrats.com/media/cms/menu/conocenos-disfrutar-mesa.jpg" alt="GastronomÃa" class="cmsb7-absolute cmsb7-inset-0 cmsb7-w-full cmsb7-h-full cmsb7-object-cover cmsb7-transition-transform cmsb7-duration-500 cmsb7-group-hover:scale-110" loading="lazy"> 2945 <div class="cmsb7-absolute cmsb7-inset-0 cmsb7-bg-black/40 cmsb7-flex cmsb7-items-center cmsb7-justify-center cmsb7-p-6 cmsb7-text-center"> 2946 <h3 class="cmsb7-text-white cmsb7-text-2xl cmsb7-md:text-4xl cmsb7-font-light font-secondary"><span>Hacerte disfrutar en la mesa</span></h3> 2947 </div> 2948 </a> 2949 2950 <a href="https://www.serrats.com/es_es/somos-sostenibles" class="cmsb7-relative cmsb7-group cmsb7-aspect-[16/9] cmsb7-overflow-hidden cmsb7-rounded-xl cmsb7-shadow-md cmsb7-block"> 2951 <img src="https://www.serrats.com/media/cms/menu/conocenos-ser-sostenibles.jpg" alt="Sostenibilidad" class="cmsb7-absolute cmsb7-inset-0 cmsb7-w-full cmsb7-h-full cmsb7-object-cover cmsb7-transition-transform cmsb7-duration-500 cmsb7-group-hover:scale-110" loading="lazy"> 2952 <div class="cmsb7-absolute cmsb7-inset-0 cmsb7-bg-black/40 cmsb7-flex cmsb7-items-center cmsb7-justify-center cmsb7-p-6 cmsb7-text-center"> 2953 <h3 class="cmsb7-text-white cmsb7-text-2xl cmsb7-md:text-4xl cmsb7-font-light font-secondary"><span>Ser sostenibles</span></h3> 2954 </div> 2955 </a> 2956 2957 <a href="https://www.serrats.com/es_es/certificados-reconocimientos" class="cmsb7-relative cmsb7-group cmsb7-aspect-[16/9] cmsb7-overflow-hidden cmsb7-rounded-xl cmsb7-shadow-md cmsb7-block"> 2958 <img src="https://www.serrats.com/media/cms/menu/conocenos-certificados-reconocimientos.jpg" alt="Calidad" class="cmsb7-absolute cmsb7-inset-0 cmsb7-w-full cmsb7-h-full cmsb7-object-cover cmsb7-transition-transform cmsb7-duration-500 cmsb7-group-hover:scale-110" loading="lazy"> 2959 <div class="cmsb7-absolute cmsb7-inset-0 cmsb7-bg-black/40 cmsb7-flex cmsb7-items-center cmsb7-justify-center cmsb7-p-6 cmsb7-text-center"> 2960 <h3 class="cmsb7-text-white cmsb7-text-2xl cmsb7-md:text-4xl cmsb7-font-light font-secondary"><span>Certificados y reconocimientos</span></h3> 2961 </div> 2962 </a> 2963 </div> 2964 </div> 2965</section> </div> 2966 </div> 2967 </div> 2968 </div> 2969 </div> 2970 </div> 2971 </li> 2972 2973 <li class="group/l1" role="none"> 2974 <a href="https://www.serrats.com/recetas/" 2975 data-item-id="item-1775820502287-7pug3vzeh" 2976 data-item-title="RECETAS Y MÁS" 2977 class="relative block transition-colors duration-300 px-3 py-3 text-[13px] font-semibold leading-[1.28] text-[#1a1919] " 2978 :class="isActive('item\u002D1775820502287\u002D7pug3vzeh') ? '' : ''" 2979 role="menuitem" 2980 :aria-current="isActive('item\u002D1775820502287\u002D7pug3vzeh') ? 'page' : null" 2981 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820502287-7pug3vzeh","link_text":"RECETAS Y MÃS","link_url":"https://www.serrats.com/recetas/","menu_level":1,"menu_device":"desktop","menu_type":"mega","item_type":"link"}" data-gtm-identifier="item-1775820502287-7pug3vzeh">
2982 <span class="relative"> 2983 RECETAS Y MÃS <span class="absolute left-0 -bottom-1 h-0.5 bg-[#1a1919] transition-all duration-300 ease-out group-hover/l1:w-full" 2984 :class="isActive('item\u002D1775820502287\u002D7pug3vzeh') ? 'w\u002Dfull' : 'w-0'"></span> 2985 </span> 2986 </a> 2987 </li> 2988 </ul> 2989</nav> 2990 </div> 2991 2992 <div class="menu-mobile lg:hidden"> 2993 2994<div x-data="{ 2995 ...menuActiveTracker(), 2996 open: false, 2997 activeL1: null, 2998 activeL2: null, 2999 hoveredL1: null, 3000 desktopQuery: null, 3001 _activeDetected: false, 3002 3003 get isDesktop() { 3004 return this.desktopQuery?.matches ?? false; 3005 }, 3006 3007 setActiveCategory(index, hasChildren) { 3008 this.hoveredL1 = index; 3009 this.activeL2 = null; 3010 if (hasChildren) { 3011 this.activeL1 = index; 3012 } else { 3013 this.activeL1 = null; 3014 } 3015 }, 3016 3017 clearHover() { 3018 this.hoveredL1 = null; 3019 }, 3020 3021 handleLeave(event) { 3022 if (!this.isDesktop) return; 3023 const related = event.relatedTarget; 3024 if (!related?.closest('[data-menu-panel], [data-subcategory-panel]')) { 3025 this.activeL1 = null; 3026 this.hoveredL1 = null; 3027 } 3028 }, 3029 3030 openMenu() { 3031 this.open = true; 3032 document.body.classList.add('overflow-hidden'); 3033 }, 3034 3035 closeMenu() { 3036 this.open = false; 3037 document.body.classList.remove('overflow-hidden'); 3038 setTimeout(() => { this.activeL1 = null; this.activeL2 = null; }, 200); 3039 } 3040 }" 3041 data-preview-auto-open 3042 x-init=" 3043 desktopQuery = window.matchMedia('(min-width: 768px)'); 3044 desktopQuery.addEventListener('change', () => { activeL1 = null; }); 3045 " 3046 class="hamburger-menu-wrapper" 3047 data-menu-id="menu" 3048 x-effect="if (open && !_activeDetected) { _activeDetected = true; detectActiveItem(); }" 3049 @open-hamburger.window="openMenu()"> 3050 3051 <button type="button" 3052 @click="openMenu()" 3053 class="menu-hamburger-trigger transition-colors duration-200 flex text-gray-700 hover:text-black" 3054 aria-label="Open menu" 3055 aria-haspopup="true" 3056 :aria-expanded="open"> 3057 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-6 h-6" width="24" height="24" aria-hidden="true"><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128ZM40,72H216a8,8,0,0,0,0-16H40a8,8,0,0,0,0,16ZM216,184H40a8,8,0,0,0,0,16H216a8,8,0,0,0,0-16Z"/></svg> 3058 </button> 3059 3060 <template x-teleport=".page-wrapper"> 3061 <div x-ref="menuContainer" class="hamburger-menu-teleported"> 3062 <div x-show="open" 3063 x-cloak 3064 x-transition:enter="transition-opacity ease-out duration-200" 3065 x-transition:enter-start="opacity-0" 3066 x-transition:enter-end="opacity-100" 3067 x-transition:leave="transition-opacity ease-in duration-150" 3068 x-transition:leave-start="opacity-100" 3069 x-transition:leave-end="opacity-0" 3070 @click="closeMenu()" 3071 class="backdrop z-40 " 3072 aria-hidden="true"> 3073 </div> 3074 3075 <nav x-show="open" 3076 x-cloak 3077 x-transition:enter="transition-all ease-out duration-300" 3078 x-transition:enter-start="opacity-0 -translate-x-full" 3079 x-transition:enter-end="opacity-100 translate-x-0" 3080 x-transition:leave="transition-all ease-in duration-200" 3081 x-transition:leave-start="opacity-100 translate-x-0" 3082 x-transition:leave-end="opacity-0 -translate-x-full" 3083 @click.stop 3084 class="fixed top-0 left-0 h-full w-full max-w-md z-50 overflow-hidden transition-[max-width] duration-300 bg-white" 3085 :class="activeL1 !== null && isDesktop ? 'md:max-w-2xl' : 'md:max-w-[300px]'" 3086 role="navigation" 3087 aria-label="Hamburger menu"> 3088 3089 <button @click="closeMenu()" 3090 type="button" 3091 class="absolute top-6 right-6 z-20 items-center justify-center rounded-full hover:scale-110 active:scale-95 transition-all duration-200 w-10 h-10 bg-primary text-white hover:bg-primary/90" 3092 :class="activeL1 !== null ? 'hidden' : 'flex'" 3093 aria-label="Close menu"> 3094 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-5 h-5" width="24" height="24" aria-hidden="true"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/></svg> 3095 </button> 3096 3097 3098 <div class="relative h-full w-full md:flex md:flex-row"> 3099 <div data-menu-panel 3100 class="absolute inset-0 h-full overflow-y-auto [padding-bottom:max(2rem,env(safe-area-inset-bottom))] transition-all duration-300 md:relative md:shrink-0 md:border-r pt-24 pb-8 md:w-[280px]" 3101 :class="{
3102 '-translate-x-full opacity-0 md:translate-x-0 md:opacity-100': activeL1 !== null && !isDesktop, 3103 'border-gray-200': activeL1 !== null && isDesktop, 3104 'border-transparent': activeL1 === null || !isDesktop 3105 }" 3106 @mouseleave="handleLeave($event)"> 3107 3108 <ul class="space-y-1" role="menu"> 3109 <li role="none"> 3110 <a href="https://www.serrats.com/es_es/tienda-conservas" 3111 @mouseenter="isDesktop && setActiveCategory(0, true)" 3112 data-item-id="item-1775820259852-eo9dhk2zk" 3113 data-item-title="TIENDA" 3114 class="hidden md:flex items-center justify-between w-full text-left transition-colors group px-6 py-3 text-lg md:text-xl font-medium text-gray-900 hover:text-black " 3115 :class="hoveredL1 === 0 || isActive('item\u002D1775820259852\u002Deo9dhk2zk') ? 'text\u002Dblack' : ''" 3116 :aria-current="isActive('item\u002D1775820259852\u002Deo9dhk2zk') ? 'page' : null" 3117 role="menuitem" 3118 aria-haspopup="true" 3119 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820259852-eo9dhk2zk","link_text":"TIENDA","link_url":"https://www.serrats.com/es_es/tienda-conservas","menu_level":1,"menu_device":"mobile","menu_type":"hamburger","item_type":"link"}" data-gtm-identifier="item-1775820259852-eo9dhk2zk"> 3120 <span class="relative"> 3121 TIENDA <span class="absolute left-0 -bottom-0.5 h-0.5 transition-all duration-300 bg-primary" 3122 :class="hoveredL1 === 0 || isActive('item\u002D1775820259852\u002Deo9dhk2zk') ? 'w\u002Dfull' : 'w-0'"></span> 3123 </span> 3124 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-5 h-5 text-black" width="20" height="20" x-show="activeL1 === 0" x-cloak="" aria-hidden="true"><path d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z"/></svg> 3125 </a> 3126 <button type="button" 3127 @click="setActiveCategory(0, true)" 3128 data-item-id="item-1775820259852-eo9dhk2zk" 3129 data-item-title="TIENDA" 3130 class="flex md:hidden items-center justify-between w-full text-left transition-colors group px-6 py-3 text-lg md:text-xl font-medium text-gray-900 hover:text-black " 3131 :class="isActive('item\u002D1775820259852\u002Deo9dhk2zk') ? 'text\u002Dblack' : ''" 3132 role="menuitem" 3133 aria-haspopup="true"> 3134 <span class="relative"> 3135 TIENDA <sp
3135an class="absolute left-0 -bottom-0.5 h-0.5 transition-all duration-300 bg-primary" 3136 :class="isActive('item\u002D1775820259852\u002Deo9dhk2zk') ? 'w\u002Dfull' : 'w-0'"></span> 3137 </span> 3138 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-5 h-5 transition-colors text-gray-400 group-hover:text-black" width="20" height="20" aria-hidden="true"><path d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z"/></svg> 3139 </button> 3140 </li> 3141 <li role="none"> 3142 <a href="https://www.serrats.com/es_es/club-serrats" 3143 data-item-id="item-1775820446650-j8gefjoee" 3144 data-item-title="CLUB SERRATS" 3145 @mouseenter="isDesktop && setActiveCategory(1, false)" 3146 class="block transition-colors px-6 py-3 text-lg md:text-xl font-medium text-gray-900 hover:text-black " 3147 :class="hoveredL1 === 1 || isActive('item\u002D1775820446650\u002Dj8gefjoee') ? 'text\u002Dblack' : ''" 3148 :aria-current="isActive('item\u002D1775820446650\u002Dj8gefjoee') ? 'page' : null" 3149 role="menuitem" 3150 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820446650-j8gefjoee","link_text":"CLUB SERRATS","link_url":"https://www.serrats.com/es_es/club-serrats","menu_level":1,"menu_device":"mobile","menu_type":"hamburger","item_type":"link"}" data-gtm-identifier="item-1775820446650-j8gefjoee"> 3151 <span class="relative"> 3152 CLUB SERRATS <span class="absolute left-0 -bottom-0.5 h-0.5 transition-all duration-300 bg-primary" 3153 :class="hoveredL1 === 1 || isActive('item\u002D1775820446650\u002Dj8gefjoee') ? 'w\u002Dfull' : 'w-0'"></span> 3154 </span> 3155 </a> 3156 </li> 3157 <li role="none"> 3158 <a href="https://www.serrats.com/es_es/bermeo-nuestro-origen" 3159 data-item-id="item-1775820474368-v3tn4p8ix" 3160 data-item-title="CONÓCENOS" 3161 @mouseenter="isDesktop && setActiveCategory(2, false)" 3162 class="block transition-colors px-6 py-3 text-lg md:text-xl font-medium text-gray-900 hover:text-black " 3163 :class="hoveredL1 === 2 || isActive('item\u002D1775820474368\u002Dv3tn4p8ix') ? 'text\u002Dblack' : ''" 3164 :aria-current="isActive('item\u002D1775820474368\u002Dv3tn4p8ix') ? 'page' : null" 3165 role="menuitem" 3166 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820474368-v3tn4p8ix","link_text":"CONÃCENOS","link_url":"https://www.serrats.com/es_es/bermeo-nuestro-origen","menu_level":1,"menu_device":"mobile","menu_type":"hamburger","item_type":"link"}" data-gtm-identifier="item-1775820474368-v3tn4p8ix">
3167 <span class="relative"> 3168 CONÃCENOS <span class="absolute left-0 -bottom-0.5 h-0.5 transition-all duration-300 bg-primary" 3169 :class="hoveredL1 === 2 || isActive('item\u002D1775820474368\u002Dv3tn4p8ix') ? 'w\u002Dfull' : 'w-0'"></span> 3170 </span> 3171 </a> 3172 </li> 3173 <li role="none"> 3174 <a href="https://www.serrats.com/recetas/" 3175 data-item-id="item-1775820502287-7pug3vzeh" 3176 data-item-title="RECETAS Y MÁS" 3177 @mouseenter="isDesktop && setActiveCategory(3, false)" 3178 class="block transition-colors px-6 py-3 text-lg md:text-xl font-medium text-gray-900 hover:text-black " 3179 :class="hoveredL1 === 3 || isActive('item\u002D1775820502287\u002D7pug3vzeh') ? 'text\u002Dblack' : ''" 3180 :aria-current="isActive('item\u002D1775820502287\u002D7pug3vzeh') ? 'page' : null" 3181 role="menuitem" 3182 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820502287-7pug3vzeh","link_text":"RECETAS Y MÃS","link_url":"https://www.serrats.com/recetas/","menu_level":1,"menu_device":"mobile","menu_type":"hamburger","item_type":"link"}" data-gtm-identifier="item-1775820502287-7pug3vzeh"> 3183 <span class="relative"> 3184 RECETAS Y MÃS <span class="absolute left-0 -bottom-0.5 h-0.5 transition-all duration-300 bg-primary" 3185 :class="hoveredL1 === 3 || isActive('item\u002D1775820502287\u002D7pug3vzeh') ? 'w\u002Dfull' : 'w-0'"></span> 3186 </span> 3187 </a> 3188 </li> 3189 </ul> 3190 </div> 3191 3192 <div data-subcategory-panel 3193 x-show="activeL1 !== null" 3194 x-cloak 3195 class="absolute inset-0 md:relative md:shrink-0 overflow-hidden md:w-[320px]" 3196 :class="isDesktop ? '' : 'z-10'" 3197 @mouseleave="handleLeave($event)"> 3198 3199 <div x-show="activeL1 === 0" 3200 x-cloak 3201 data-item-id="item-1775820259852-eo9dhk2zk" 3202 x-transition:enter="transition-all ease-out duration-300" 3203 x-transition:enter-start="opacity-0" 3204 :x-transition:enter-start="isDesktop ? 'opacity-0 -translate-x-4' : 'opacity-0 translate-x-full'" 3205 x-transition:enter-end="opacity-100 translate-x-0" 3206 x-transition:leave="transition-all ease-in duration-200" 3207 x-transition:leave-start="opacity-100 translate-x-0" 3208 x-transition:leave-end="opacity-0" 3209 class="absolute inset-0 h-full bg-white" 3210 role="menu" 3211 aria-label="TIENDA"> 3212 3213 <div class="md:hidden absolute inset-x-0 top-0 h-28 z-10 pointer-events-none bg-gradient-to-b from-white to-transparent" aria-hidden="true"></div> 3214 3215 <div class="md:hidden absolute top-6 left-6 right-6 z-20 flex items-center justify-between gap-3"> 3216 <button @click="activeL1 = null" 3217 type="button" 3218 class="flex items-center gap-1.5 transition-all duration-200 group active:scale-95 text-sm font-medium text-gray-600 hover:text-black" 3219 aria-label="Volver"> 3220 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-4 h-4 transition-transform duration-200 group-hover:-translate-x-1" width="16" height="16" aria-hidden="true"><path d="M165.66,202.34a8,8,0,0,1-11.32,11.32l-80-80a8,8,0,0,1,0-11.32l80-80a8,8,0,0,1,11.32,11.32L91.31,128Z"/></svg>
3221 <span>Volver</span> 3222 </button> 3223 3224 <span class="flex-1 text-center truncate font-semibold text-gray-900"> 3225 TIENDA </span> 3226 3227 <button @click="closeMenu()" 3228 type="button" 3229 class="flex items-center justify-center rounded-full hover:scale-110 active:scale-95 transition-all duration-200 w-10 h-10 bg-primary text-white hover:bg-primary/90" 3230 aria-label="Close menu"> 3231 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-5 h-5" width="24" height="24" aria-hidden="true"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/></svg> 3232 </button> 3233 </div> 3234 3235 <div class="h-full overflow-y-auto [padding-bottom:max(2rem,env(safe-area-inset-bottom))] pt-24 pb-8 px-6"> 3236 <a href="https://www.serrats.com/es_es/tienda-conservas" 3237 class="hidden md:block hover:underline mb-6 text-xl font-semibold text-gray-900"> 3238 TIENDA </a> 3239 <a href="https://www.serrats.com/es_es/tienda-conservas" 3240 class="md:hidden block py-2.5 text-base text-gray-400 hover:text-black"> 3241 Ver todo → 3242 </a> 3243 3244 <ul class="space-y-1"> 3245 <li role="none" class="group/l2"> 3246 <a href="https://www.serrats.com/es_es/comprar-surtidos-regalo" 3247 data-item-id="item-1775820823229-qpay89791" 3248 data-item-title="CAJAS REGALO GOURMET" 3249 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3250 :aria-current="isActive('item\u002D1775820823229\u002Dqpay89791') ? 'page' : null" 3251 role="menuitem" 3252 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-qpay89791","link_text":"CAJAS REGALO GOURMET","link_url":"https://www.serrats.com/es_es/comprar-surtidos-regalo","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775820823229-qpay89791"> 3253 <span class="relative inline-block"> 3254 CAJAS REGALO GOURMET <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3255 :class="isActive('item\u002D1775820823229\u002Dqpay89791') ? 'w\u002Dfull' : 'w-0'"></span> 3256 </span> 3257 </a> 3258 </li> 3259 <li role="none" class="group/l2"> 3260 <a href="https://www.serrats.com/es_es/comprar-bonito-del-norte" 3261 data-item-id="item-1775820858446-1sffzfc9w" 3262 data-item-title="Bonito del Norte" 3263 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3264 :aria-current="isActive('item\u002D1775820858446\u002D1sffzfc9w') ? 'page' : null" 3265 role="menuitem" 3266 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820858446-1sffzfc9w","link_text":"Bonito del Norte","link_url":"https://www.serrats.com/es_es/comprar-bonito-del-norte","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775820858446-1sffzfc9w">
3267 <span class="relative inline-block"> 3268 Bonito del Norte <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3269 :class="isActive('item\u002D1775820858446\u002D1sffzfc9w') ? 'w\u002Dfull' : 'w-0'"></span> 3270 </span> 3271 </a> 3272 </li> 3273 <li role="none" class="group/l2"> 3274 <a href="https://www.serrats.com/es_es/comprar-ventresca-de-bonito" 3275 data-item-id="item-1775820823229-uvtx2itbg" 3276 data-item-title="Ventresca de Bonito del Norte" 3277 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3278 :aria-current="isActive('item\u002D1775820823229\u002Duvtx2itbg') ? 'page' : null" 3279 role="menuitem" 3280 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-uvtx2itbg","link_text":"Ventresca de Bonito del Norte","link_url":"https://www.serrats.com/es_es/comprar-ventresca-de-bonito","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775820823229-uvtx2itbg"> 3281 <span class="relative inline-block"> 3282 Ventresca de Bonito del Norte <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3283 :class="isActive('item\u002D1775820823229\u002Duvtx2itbg') ? 'w\u002Dfull' : 'w-0'"></span> 3284 </span> 3285 </a> 3286 </li> 3287 <li role="none" class="group/l2"> 3288 <a href="https://www.serrats.com/es_es/comprar-cogote-de-bonito" 3289 data-item-id="item-1775820823229-uursqr6h0" 3290 data-item-title="Cogote de Bonito del Norte" 3291 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3292 :aria-current="isActive('item\u002D1775820823229\u002Duursqr6h0') ? 'page' : null" 3293 role="menuitem" 3294 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-uursqr6h0","link_text":"Cogote de Bonito del Norte","link_url":"https://www.serrats.com/es_es/comprar-cogote-de-bonito","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775820823229-uursqr6h0">
3295 <span class="relative inline-block"> 3296 Cogote de Bonito del Norte <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3297 :class="isActive('item\u002D1775820823229\u002Duursqr6h0') ? 'w\u002Dfull' : 'w-0'"></span> 3298 </span> 3299 </a> 3300 </li> 3301 <li role="none" class="group/l2"> 3302 <a href="https://www.serrats.com/es_es/comprar-anchoas-del-cantabrico" 3303 data-item-id="item-1775820823229-sadkjnzzy" 3304 data-item-title="Anchoas del Cantábrico" 3305 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3306 :aria-current="isActive('item\u002D1775820823229\u002Dsadkjnzzy') ? 'page' : null" 3307 role="menuitem" 3308 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-sadkjnzzy","link_text":"Anchoas del Cantábrico","link_url":"https://www.serrats.com/es_es/comprar-anchoas-del-cantabrico","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775820823229-sadkjnzzy"> 3309 <span class="relative inline-block"> 3310 Anchoas del Cantábrico <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3311 :class="isActive('item\u002D1775820823229\u002Dsadkjnzzy') ? 'w\u002Dfull' : 'w-0'"></span> 3312 </span> 3313 </a> 3314 </li> 3315 <li role="none" class="group/l2"> 3316 <a href="https://www.serrats.com/es_es/comprar-boquerones" 3317 data-item-id="item-1775820823229-k37xw06p5" 3318 data-item-title="Boquerones del Cantábrico" 3319 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3320 :aria-current="isActive('item\u002D1775820823229\u002Dk37xw06p5') ? 'page' : null" 3321 role="menuitem" 3322 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-k37xw06p5","link_text":"Boquerones del Cantábrico","link_url":"https://www.serrats.com/es_es/comprar-boquerones","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775820823229-k37xw06p5">
3323 <span class="relative inline-block"> 3324 Boquerones del Cantábrico <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3325 :class="isActive('item\u002D1775820823229\u002Dk37xw06p5') ? 'w\u002Dfull' : 'w-0'"></span> 3326 </span> 3327 </a> 3328 </li> 3329 <li role="none" class="group/l2"> 3330 <a href="https://www.serrats.com/es_es/comprar-atun-claro-en-conserva" 3331 data-item-id="item-1775820823229-8f66si65q" 3332 data-item-title="Atún Claro" 3333 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3334 :aria-current="isActive('item\u002D1775820823229\u002D8f66si65q') ? 'page' : null" 3335 role="menuitem" 3336 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-8f66si65q","link_text":"Atún Claro","link_url":"https://www.serrats.com/es_es/comprar-atun-claro-en-conserva","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775820823229-8f66si65q"> 3337 <span class="relative inline-block"> 3338 Atún Claro <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3339 :class="isActive('item\u002D1775820823229\u002D8f66si65q') ? 'w\u002Dfull' : 'w-0'"></span> 3340 </span> 3341 </a> 3342 </li> 3343 <li role="none" class="group/l2"> 3344 <a href="https://www.serrats.com/es_es/comprar-mejillones-en-conserva" 3345 data-item-id="item-1775821963737-n7ry1n47l" 3346 data-item-title="Mejillones grandes" 3347 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3348 :aria-current="isActive('item\u002D1775821963737\u002Dn7ry1n47l') ? 'page' : null" 3349 role="menuitem" 3350 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"
3350item-1775821963737-n7ry1n47l","link_text":"Mejillones grandes","link_url":"https://www.serrats.com/es_es/comprar-mejillones-en-conserva","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775821963737-n7ry1n47l"> 3351 <span class="relative inline-block"> 3352 Mejillones grandes <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3353 :class="isActive('item\u002D1775821963737\u002Dn7ry1n47l') ? 'w\u002Dfull' : 'w-0'"></span> 3354 </span> 3355 </a> 3356 </li> 3357 <li role="none" class="group/l2"> 3358 <a href="https://www.serrats.com/es_es/comprar-sardinillas-en-conserva" 3359 data-item-id="item-1775820823229-h5q4cad1k" 3360 data-item-title="Sardinillas "txikis"" 3361 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3362 :aria-current="isActive('item\u002D1775820823229\u002Dh5q4cad1k') ? 'page' : null" 3363 role="menuitem" 3364 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775820823229-h5q4cad1k","link_text":"Sardinillas \"txikis\"","link_url":"https://www.serrats.com/es_es/comprar-sardinillas-en-conserva","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775820823229-h5q4cad1k"> 3365 <span class="relative inline-block"> 3366 Sardinillas "txikis" <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3367 :class="isActive('item\u002D1775820823229\u002Dh5q4cad1k') ? 'w\u002Dfull' : 'w-0'"></span> 3368 </span> 3369 </a> 3370 </li> 3371 <li role="none" class="group/l2"> 3372 <a href="https://www.serrats.com/es_es/comprar-navajas" 3373 data-item-id="item-1775821963737-oqfg8ydit" 3374 data-item-title="Navajas de las Rías Gallegas" 3375 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3376 :aria-current="isActive('item\u002D1775821963737\u002Doqfg8ydit') ? 'page' : null" 3377 role="menuitem" 3378 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775821963737-oqfg8ydit","link_text":"Navajas de las RÃas Gallegas","link_url":"https://www.serrats.com/es_es/comprar-navajas","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775821963737-oqfg8ydit">
3379 <span class="relative inline-block"> 3380 Navajas de las RÃas Gallegas <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3381 :class="isActive('item\u002D1775821963737\u002Doqfg8ydit') ? 'w\u002Dfull' : 'w-0'"></span> 3382 </span> 3383 </a> 3384 </li> 3385 <li role="none" class="group/l2"> 3386 <a href="https://www.serrats.com/es_es/comprar-zamburinas-en-conserva" 3387 data-item-id="item-1779083788975-zmbrin44ws" 3388 data-item-title="Zamburiñas de las Rías Gallegas" 3389 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3390 :aria-current="isActive('item\u002D1779083788975\u002Dzmbrin44ws') ? 'page' : null" 3391 role="menuitem" 3392 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1779083788975-zmbrin44ws","link_text":"Zamburiñas de las RÃas Gallegas","link_url":"https://www.serrats.com/es_es/comprar-zamburinas-en-conserva","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1779083788975-zmbrin44ws"> 3393 <span class="relative inline-block"> 3394 Zamburiñas de las RÃas Gallegas <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3395 :class="isActive('item\u002D1779083788975\u002Dzmbrin44ws') ? 'w\u002Dfull' : 'w-0'"></span> 3396 </span> 3397 </a> 3398 </li> 3399 <li role="none" class="group/l2"> 3400 <a href="https://www.serrats.com/es_es/comprar-berberechos-en-conserva" 3401 data-item-id="item-1775821963737-lnkpv5ycz" 3402 data-item-title="Berberechos de las Rías Gallegas" 3403 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3404 :aria-current="isActive('item\u002D1775821963737\u002Dlnkpv5ycz') ? 'page' : null" 3405 role="menuitem" 3406 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775821963737-lnkpv5ycz","link_text":"Berberechos de las RÃas Gallegas","link_url":"https://www.serrats.com/es_es/comprar-berberechos-en-conserva","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775821963737-lnkpv5ycz">
3407 <span class="relative inline-block"> 3408 Berberechos de las RÃas Gallegas <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3409 :class="isActive('item\u002D1775821963737\u002Dlnkpv5ycz') ? 'w\u002Dfull' : 'w-0'"></span> 3410 </span> 3411 </a> 3412 </li> 3413 <li role="none" class="group/l2"> 3414 <a href="https://www.serrats.com/es_es/comprar-caviar-de-oricios" 3415 data-item-id="item-1775821963737-llueymm1s" 3416 data-item-title="Caviar de Erizo de Mar" 3417 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3418 :aria-current="isActive('item\u002D1775821963737\u002Dllueymm1s') ? 'page' : null" 3419 role="menuitem" 3420 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775821963737-llueymm1s","link_text":"Caviar de Erizo de Mar","link_url":"https://www.serrats.com/es_es/comprar-caviar-de-oricios","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775821963737-llueymm1s"> 3421 <span class="relative inline-block"> 3422 Caviar de Erizo de Mar <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3423 :class="isActive('item\u002D1775821963737\u002Dllueymm1s') ? 'w\u002Dfull' : 'w-0'"></span> 3424 </span> 3425 </a> 3426 </li> 3427 <li role="none" class="group/l2"> 3428 <a href="https://www.serrats.com/es_es/comprar-productos-coleccion" 3429 data-item-id="item-1775822813740-ebac7v7ey" 3430 data-item-title="Productos EDICIÓN LIMITADA" 3431 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3432 :aria-current="isActive('item\u002D1775822813740\u002Debac7v7ey') ? 'page' : null" 3433 role="menuitem" 3434 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775822813740-ebac7v7ey","link_text":"Productos EDICIÃN LIMITADA","link_url":"https://www.serrats.com/es_es/comprar-productos-coleccion","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775822813740-ebac7v7ey">
3435 <span class="relative inline-block"> 3436 Productos EDICIÃN LIMITADA <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3437 :class="isActive('item\u002D1775822813740\u002Debac7v7ey') ? 'w\u002Dfull' : 'w-0'"></span> 3438 </span> 3439 </a> 3440 </li> 3441 <li role="none" class="group/l2"> 3442 <a href="https://www.serrats.com/es_es/comprar-productos-ecologicos" 3443 data-item-id="item-1775821963737-bs0b1ukz5" 3444 data-item-title="Conservas ecológicas" 3445 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3446 :aria-current="isActive('item\u002D1775821963737\u002Dbs0b1ukz5') ? 'page' : null" 3447 role="menuitem" 3448 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1775821963737-bs0b1ukz5","link_text":"Conservas ecológicas","link_url":"https://www.serrats.com/es_es/comprar-productos-ecologicos","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1775821963737-bs0b1ukz5"> 3449 <span class="relative inline-block"> 3450 Conservas ecológicas <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3451 :class="isActive('item\u002D1775821963737\u002Dbs0b1ukz5') ? 'w\u002Dfull' : 'w-0'"></span> 3452 </span> 3453 </a> 3454 </li> 3455 <li role="none" class="group/l2"> 3456 <a href="https://www.serrats.com/es_es/comprar-conservas-al-natural" 3457 data-item-id="item-1779083788976-cnatu43ws" 3458 data-item-title="Conservas al Natural" 3459 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3460 :aria-current="isActive('item\u002D1779083788976\u002Dcnatu43ws') ? 'page' : null" 3461 role="menuitem" 3462 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1779083788976-cnatu43ws","link_text":"Conservas al Natural","link_url":"https://www.serrats.com/es_es/comprar-conservas-al-natural","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1779083788976-cnatu43ws">
3463 <span class="relative inline-block"> 3464 Conservas al Natural <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3465 :class="isActive('item\u002D1779083788976\u002Dcnatu43ws') ? 'w\u002Dfull' : 'w-0'"></span> 3466 </span> 3467 </a> 3468 </li> 3469 <li role="none" class="group/l2"> 3470 <a href="https://www.serrats.com/es_es/ofertas" 3471 data-item-id="item-1779958975586-yodxvilas" 3472 data-item-title="OFERTAS" 3473 class="block transition-colors group py-2.5 text-base text-gray-700 hover:text-black " 3474 :aria-current="isActive('item\u002D1779958975586\u002Dyodxvilas') ? 'page' : null" 3475 role="menuitem" 3476 gtm-tracking="1" gtm-data="{"event":"select_content","trigger":"click","content_type":"menu_link","content_id":"item-1779958975586-yodxvilas","link_text":"OFERTAS","link_url":"https://www.serrats.com/es_es/ofertas","menu_level":2,"menu_device":"mobile","menu_type":"hamburger","item_type":"category"}" data-gtm-identifier="item-1779958975586-yodxvilas"> 3477 <span class="relative inline-block"> 3478 OFERTAS <span class="absolute left-0 bottom-0 h-px transition-all duration-300 group-hover:w-full group-has-[.l3-active]/l2:w-0 bg-primary" 3479 :class="isActive('item\u002D1779958975586\u002Dyodxvilas') ? 'w\u002Dfull' : 'w-0'"></span> 3480 </span> 3481 </a> 3482 </li> 3483 </ul> 3484 </div> 3485 3486 </div> 3487 </div> 3488 </div> 3489 </nav> 3490 </div> 3491 </template> 3492</div> 3493 </div> 3494</div><div id="header-logo-icon-container" class="z-20 order-2 lg:order-2 lg:absolute m-auto header-logo-serrats-centered"><a href="https://www.serrats.com/es_es" 3495 title="" 3496 x-data="{active: null, logo_inactive: false, headerIsActive: false}" 3497 @header-sticky-scrolled-change.window="active = $event.detail" 3498 @header-active-change.window="headerIsActive = $event.detail" 3499 class="hidden lg:block transition-opacity" 3500 :class="{'lg:hidden': active, 'lg:block': !active}" 3501 aria-label="store logo" 3502 x-show="headerIsActive === !logo_inactive" > 3503 <img src="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/images/logo.svg" 3504 title="" 3505 alt="" 3506 class="" 3507 width="158" height="70" /> 3508 </a> 3509<a href="https://www.serrats.com/es_es" 3510 title=""
3511 x-data="{active: null, logo_inactive: true, headerIsActive: false}" 3512 @header-sticky-scrolled-change.window="active = $event.detail" 3513 @header-active-change.window="headerIsActive = $event.detail" 3514 class="hidden lg:block transition-opacity" 3515 :class="{'lg:hidden': active, 'lg:block': !active}" 3516 aria-label="store logo" 3517 x-show="headerIsActive === !logo_inactive" x-cloak> 3518 <img src="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/images/logo.svg" 3519 title="" 3520 alt="" 3521 class="" 3522 width="158" height="70" /> 3523 </a> 3524<a href="https://www.serrats.com/es_es" 3525 title="" 3526 x-data="{active: null, logo_inactive: false, headerIsActive: false}" 3527 @header-sticky-scrolled-change.window="active = $event.detail" 3528 @header-active-change.window="headerIsActive = $event.detail" 3529 class="block lg:hidden transition-opacity" 3530 :class="{'': active, '': !active}" 3531 aria-label="store logo" 3532 x-show="headerIsActive === !logo_inactive" > 3533 <img src="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/images/logo-small.svg" 3534 title="" 3535 alt="" 3536 class="" 3537 width="92" height="70" /> 3538 </a> 3539<a href="https://www.serrats.com/es_es" 3540 title="" 3541 x-data="{active: null, logo_inactive: true, headerIsActive: false}" 3542 @header-sticky-scrolled-change.window="active = $event.detail" 3543 @header-active-change.window="headerIsActive = $event.detail" 3544 class="block lg:hidden transition-opacity" 3545 :class="{'': active, '': !active}" 3546 aria-label="store logo" 3547 x-show="headerIsActive === !logo_inactive" x-cloak> 3548 <img src="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/images/logo-small.svg" 3549 title="" 3550 alt="" 3551 class="" 3552 width="92" height="70" /> 3553 </a> 3554<a href="https://www.serrats.com/es_es" 3555 title="" 3556 x-data="{active: null, logo_inactive: false, headerIsActive: false}" 3557 @header-sticky-scrolled-change.window="active = $event.detail" 3558 @header-active-change.window="headerIsActive = $event.detail" 3559 class="hidden transition-opacity" 3560 :class="{'hidden lg:block': active, 'hidden': !active}" 3561 aria-label="store logo" 3562 x-show="headerIsActive === !logo_inactive" > 3563 <img src="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/images/logo-scroll.svg" 3564 title="" 3565 alt="" 3566 class="" 3567 width="158" height="70" /> 3568 </a> 3569</div><div class="z-20 order-3 flex flex-row flex-nowrap items-center gap-x-3 lg:ml-auto"> 3570 <div x-data="{ open: false }" x-defer="intersect" class=""> 3571 <div class="hidden"> 3572 Lenguaje </div> 3573 <div class="relative"> 3574 <span @click.prevent="open = !open" 3575 @click.outside="open = false" 3576 @keydown.window.escape="open = false" 3577 class="flex flex-row flex-nowrap items-center cursor-pointer" 3578 aria-haspopup="true" 3579 aria-expanded="true" 3580 role="button" 3581 > 3582 <span><img class="h-4 w-4 mr-2.5" width="16" height="16" alt="Español" src="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/images/store/es_es.svg" @error="$el.style.display='none'" loading="lazy"/></span> 3583 <span class="mr-2 hidden">Español</span> 3584 <span class="transition-transform" :class="{'rotate-180': open}"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-4 h-4" width="24" height="24" role="img"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"/><title>caret-down</title></svg> 3585</span> 3586 </span> 3587 <nav x-cloak="" 3588 x-show="open" 3589 class="overflow-auto absolute left-0 top-full z-20 rounded-sm shadow-lg origin-top-left bg-container-lighter text-black mt-4"> 3590 <div class="divide-y divide-gray-light" role="menu" aria-orientation="vertical" aria-labelledby="options-menu"> 3591 <sp
3591an class="cursor-pointer flex flex-row items-center text-lg uppercase flex-no-wrap px-4 py-2 hover:bg-gray-light" @click="openLink(atob('aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvc3RvcmVzL3N0b3JlL3JlZGlyZWN0L19fX3N0b3JlL2VzX2V1L19fX2Zyb21fc3RvcmUvZXNfZXMvdWVuYy9hSFIwY0hNNkx5OTNkM2N1YzJWeWNtRjBjeTVqYjIwdlpYTmZaWFV2WTI5dGNISmhjaTFpYjI1cGRHOHRaR1ZzTFc1dmNuUmwv'), '_self')" x-data="" x-defer="intersect"> 3592 <span class="w-4"> 3593 <img 3594 class="h-4 w-4 mr-2.5" 3595 width="16" 3596 height="16" 3597 alt="Euskera" 3598 src="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/images/store/es_eu.svg" 3599 @error="$el.style.display='none'" 3600 loading="lazy" 3601 /> 3602 </span> 3603 <p class="hidden">Euskera</p> </span> 3604 </div> 3605 </nav> 3606 </div> 3607 </div> 3608<div id="header-search-icon-container" class="z-20 order-3"> 3609<span id="menu-search-icon" 3610 class=" text-header-font hover:text-header-font-hover relative flex text-2xs lg:px-1 lg:pb-3 cursor-pointer" 3611 mcclane-data="search-form-submit" 3612 :class="{ 3613 '': headerScrolled, 3614 '': !headerScrolled 3615 }; $nextTick(() => { searchOpen ? $dispatch('search-opened') : ''; })" 3616 @click.prevent="searchOpen = !searchOpen; searchOpen ? $dispatch('search-open') : $dispatch('search-close')"> 3617 <span class="hidden w-max absolute left-1/2 bottom-0 transform -translate-x-1/2 lg:block">Buscar</span> 3618 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-6 h-6" width="24" height="24" role="img"><path d="M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"/><title>magnifying-glass</title></svg> 3619</span> 3620</div><div id="header-cart-icon-container" class="z-20 order-7"> 3621<button 3622 id="menu-cart-icon" 3623 mcclane-data="minicart-button" 3624 @click.prevent.stop="$dispatch('toggle-cart',{});" 3625 class="text-header-font hover:text-header-font-hover relative pr-1 flex text-2xs lg:px-1 lg:pb-3"> 3626 <span class="hidden w-max absolute left-1/2 bottom-0 transform -translate-x-1/2 lg:block">Carrito</span> 3627 <span x-show="cart.summary_count === 0 || typeof cart.summary_count === 'undefined'"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-6 h-6" width="24" height="24" role="img"><path d="M236,69.4A16.13,16.13,0,0,0,223.92,64H176a48,48,0,0,0-96,0H32.08a16.13,16.13,0,0,0-12,5.4,16,16,0,0,0-3.92,12.48l14.26,120a16,16,0,0,0,16,14.12H209.67a16,16,0,0,0,16-14.12l14.26-120A16,16,0,0,0,236,69.4ZM128,32a32,32,0,0,1,32,32H96A32,32,0,0,1,128,32Zm81.76,168a.13.13,0,0,1-.09,0H46.25L32.08,80H224Z"/><title>tote-simple</title></svg> 3628</span> 3629 <span x-show="cart.summary_count !== 0 && typeof cart.summary_count !== 'undefined'" x-cloak><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-6 h-6" width="24" height="24" role="img"><path d="M236,69.4A16.13,16.13,0,0,0,223.92,64H176a48,48,0,0,0-96,0H32.08a16.13,16.13,0,0,0-12,5.4,16,16,0,0,0-3.92,12.48l14.26,120a16,16,0,0,0,16,14.12H209.67a16,16,0,0,0,16-14.12l14.26-120A16,16,0,0,0,236,69.4ZM128,32a32,32,0,0,1,32,32H96A32,32,0,0,1,128,32Zm81.76,168a.13.13,0,0,1-.09,0H46.25L32.08,80H224Z"/><title>tote-simple</title></svg> 3630</span> 3631 <span x-text="cart.summary_count" class="absolute text-white top-0 text-2xs right-0 text-center px-1 min-w-[14px] leading-[14px] rounded-full" :class="cart.summary_count === 0 || typeof cart.summary_count === 'undefined' ? 'bg-gray-medium' : 'bg-primary'"></span> 3632</button> 3633 3634</div><div id="header-customer-icon-container" class="z-20 order-4"><div x-data="{ open: false }" class="" @click.outside="open = false"> 3635 <button id="customer-menu" 3636 mcclane-data="customer-account-button" 3637 class="text-header-font hover:text-header-font-hover relative flex text-2xs lg:px-1 lg:pb-3" 3638 @click.prevent="$dispatch('toggle-authentication-popup', { url: 'https://www.serrats.com/es_es/comprar-bonito-del-norte' });">
3639 <span class="hidden w-max absolute left-1/2 bottom-0 transform -translate-x-1/2 lg:block">Mi cuenta</span> 3640 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-6 h-6" width="24" height="24" role="img"><path d="M230.92,212c-15.23-26.33-38.7-45.21-66.09-54.16a72,72,0,1,0-73.66,0C63.78,166.78,40.31,185.66,25.08,212a8,8,0,1,0,13.85,8c18.84-32.56,52.14-52,89.07-52s70.23,19.44,89.07,52a8,8,0,1,0,13.85-8ZM72,96a56,56,0,1,1,56,56A56.06,56.06,0,0,1,72,96Z"/><title>user</title></svg> 3641 </button> 3642 </div> 3643</div></div></div> 3644<div class="hidden" id="search-content" 3645 :class="{ 3646 'block': searchOpen, 3647 'hidden': !searchOpen, 3648 '': searchOpen && headerScrolled, 3649 '': headerScrolled, 3650 '': !headerScrolled 3651 }; $nextTick(() => { searchOpen ? $dispatch('search-opened') : ''; })" 3652 @search-close.window="searchOpen = false" 3653 @search-open.window="searchOpen = true" 3654 x-show="searchOpen" 3655 @click.outside="$dispatch('search-close')"> 3656 <div class="absolute z-30 -mt-2 inset-x-0 w-full container max-w-5xl mx-auto lg:mt-0 lg:top-2" :class="{ '': searchOpen, '': !searchOpen }"> 3657 <form class="form minisearch relative" id="search_mini_form" action="https://www.serrats.com/es_es/catalogsearch/result/" method="get"> 3658 <div class=""> 3659 <label for="search" class="absolute top-2 left-2 py-1.5 lg:left-5" data-role="minisearch-label" :class="{ '': searchOpen, '': !searchOpen }"> 3660 <span class="hidden">Buscar</span> 3661 <span class="a-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="h-5 w-5" width="24" height="24" role="img"><path d="M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"/><title>magnifying-glass</title></svg> 3662</span> 3663 </label> 3664 <div class="control p-2 bg-white border rounded-md border-input-border-focus lg:px-5 lg:pb-5"> 3665
3666<script> 3667 function inputData() { 3668 return { 3669 inputed: false, 3670 searchOpen: false, 3671 search: {}, 3672 selectedTab: "", 3673 isSearchLoading: false, 3674 handleChangeInput(event) { 3675 let inputSearch = event.target.value; 3676 3677 if (inputSearch.length < 3) return; 3678 3679 this.inputed = true; 3680 this.search = {} 3681 this.isSearchLoading = true; 3682 3683 fetch('https://www.serrats.com/es_es/graphql', { 3684 method: 'POST', 3685 headers: { 3686 'Content-Type': 'application/json', 3687 'Store': 'es_es' 3688 }, 3689 credentials: 'include', 3690 body: JSON.stringify({ 3691 query: this.getQuery(inputSearch) 3692 }) 3693 } 3694 ).then((response) => { 3695 return response.json() 3696 } 3697 ).then((data) => { 3698 if (!data.errors) { 3699 this.search = data.data.rocket_multi_search; 3700 } 3701 }).catch(error => { 3702 console.error(error); 3703 }).finally(() => { 3704 this.isSearchLoading = false; 3705 }); 3706 }, 3707 getQuery(search) { 3708 return `{ 3709 rocket_multi_search(search: "${search}") { 3710 3711 products { 3712 uid 3713 name 3714 price_range { 3715 minimum_price { 3716 regular_price { 3717 value 3718 } 3719 final_price { 3720 value 3721 } 3722 } 3723 maximum_price { 3724 regular_price { 3725 value 3726 } 3727 final_price { 3728 value 3729 } 3730 } 3731 } 3732 url_key 3733 url_suffix 3734 canonical_url 3735 url_rewrites { 3736 url 3737 } 3738 categories { 3739 name 3740 } 3741 image { 3742 label 3743 url 3744 } 3745 small_image{ 3746 url 3747 label 3748 } 3749 } 3750 3751 products { 3752 ... on ConfigurableProduct { 3753 variants { 3754 attributes { 3755 code 3756 label 3757 } 3758 product { 3759 stock_status 3760 price_range { 3761 minimum_price { 3762 final_price { 3763 value 3764 } 3765 } 3766 } 3767 } 3768 } 3769 } 3770 } 3771 3772 } 3773}`; 3774 } 3775 } 3776 } 3777</script>
3777 3778 3779<div x-data="inputData()" x-defer="intersect" @search-close.window="searchOpen = false" @search-open.window="searchOpen = true" class=""> 3780 <span @click="$dispatch('search-close')" class="a-icon cursor-pointer absolute top-3.5 right-5"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="h-5 w-5" width="24" height="24" role="img"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/><title>x</title></svg> 3781</span> 3782 <input id="search" 3783 x-ref="searchInput" 3784 @search-opened.window="$refs.searchInput.focus()" 3785 @input="$dispatch('search-open'); handleChangeInput($event)" 3786 @click="$dispatch('search-open')" 3787 mcclane-data="search-form-field" 3788 autocomplete="off" 3789 type="search" 3790 name="q" 3791 value="" 3792 placeholder="Buscar..." 3793 maxlength="128" 3794 class="pl-6 form-input h-8 rounded-none w-full border-t-0 border-l-0 border-r-0 border-b-gray px-0 py-1 focus:ring-0 text-input-text-focus" 3795 /> 3796 3797 <div class="mt-4" :class="{ '': searchOpen, '': !searchOpen }" x-cloak> 3798 <div class="flex flex-row flex-nowrap justify-center items-center" x-show="isSearchLoading"> 3799 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="animate-spin h-8 w-8" width="24" height="24" role="img"><path d="M232,128a104,104,0,0,1-208,0c0-41,23.81-78.36,60.66-95.27a8,8,0,0,1,6.68,14.54C60.15,61.59,40,93.27,40,128a88,88,0,0,0,176,0c0-34.73-20.15-66.41-51.34-80.73a8,8,0,0,1,6.68-14.54C208.19,49.64,232,87,232,128Z"/><title>circle-notch</title></svg> 3800 </div> 3801 <div x-show="!isSearchLoading && inputed" class="mt-4"> 3802 <div class="flex flex-row flex-nowrap items-center"> 3803 </div> 3804 3805 <div class="h-full max-h-96 overflow-y-auto scrollbar-thin scrollbar-thumb-gray-dark scrollbar-track-gray-light" x-show="(selectedTab === 'product.search.results') || (selectedTab === '' && 'product.search.results' === 'product.search.results')"> 3806
3807<script> 3808 window.serratsAutocompleteUnitPrice = function (product) { 3809 const price = product 3810 && product.price_range 3811 && product.price_range.minimum_price.final_price.value; 3812 const variants = (product && product.variants) || []; 3813 3814 if (!price || !variants.length) { 3815 return ''; 3816 } 3817 3818 const matching = variants 3819 .filter(variant => variant.product.price_range.minimum_price.final_price.value === price) 3820 .sort((a, b) => (b.product.stock_status === 'IN_STOCK') - (a.product.stock_status === 'IN_STOCK')); 3821 3822 if (!matching.length) { 3823 return ''; 3824 } 3825 3826 const attribute = matching[0].attributes 3827 .find(item => item.code === 'uds_caja'); 3828 const units = parseInt(attribute && attribute.label, 10); 3829 3830 if (!units || units < 2) { 3831 return ''; 3832 } 3833 3834 return hyva.str( 3835 '\u00251\u0020uds.\u0020\u00B7\u0020\u00252\u002Fu', 3836 units, 3837 hyva.formatPrice(price / units) 3838 ); 3839 } 3840</script>
3840 3841 3842<template x-if="search.products && search.products.length > 0"> 3843 <div class="grid gap-x-1.5 gap-y-6 grid-cols-2 lg:grid-cols-5"> 3844 <template x-for="product in search.products"> 3845 <div class=""> 3846 <a :href="window.BASE_URL + product.canonical_url" class="block" mcclane-data="search-form-suggestion"> 3847 <img :src="product.small_image.url" 3848 class="w-full" 3849 :alt="product.small_image.label" 3850 loading="lazy" 3851 width="400" 3852 height="400"/> 3853 <div class="flex flex-col items-start w-full mt-2"> 3854 <p x-text="product.name" class="text-product-card-title product-card-title md:product-card-title-desktop line-clamp-2 min-h-[40px]"></p> 3855 <div class="final-price "> 3856 <span x-text="hyva.formatPrice(product.price_range.minimum_price.final_price.value)" 3857 :class="{ 'price-wrapper text-product-price-discount product-page-price-discount md:product-page-price-discount-desktop': product.price_range.minimum_price.final_price.value !== product.price_range.minimum_price.regular_price.value }"></span> 3858 <span class="price-wrapper text-product-price-old product-page-price-old md:product-page-price-old-desktop" 3859 x-show="product.price_range.minimum_price.final_price.value !== product.price_range.minimum_price.regular_price.value" 3860 x-text="hyva.formatPrice(product.price_range.minimum_price.regular_price.value)" 3861 ></span> 3862 </div> 3863 <template x-if="serratsAutocompleteUnitPrice(product)"> 3864 <p class="mt-0.5 text-sm text-gray-dark whitespace-nowrap tabular-nums" 3865 x-text="serratsAutocompleteUnitPrice(product)" 3866 mcclane-data="search-form-suggestion-unit-price"></p> 3867 </template> 3868 </div> 3869 </a> 3870 </div> 3871 </template> 3872 </div> 3873</template> 3874<template x-if="!search.products || search.products.length === 0"> 3875 <div class="w-full h-full flex flex-col justify-center items-center gap-2"> 3876 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-6 h-6" width="24" height="24" role="img"><path d="M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"/><title>magnifying-glass</title></svg> 3877 <span class="text-md">No hay resultados</span> 3878 </div> 3879</template> 3880 </div> 3881 </div> 3882</div> 3883</div> 3884 3885 </div> 3886 </div> 3887 </form> 3888 </div> 3889 <div class="pointer-events-none bg-black/50 fixed inset-0 z-20" :class="{ '': searchOpen, '': !searchOpen }"></div> 3890</div> 3891</div></div> 3892</nav> 3893</header> 3894<div x-data="{searchOpen: false}" 3895 x-defer="event:search-opened" 3896 x-init="searchOpen = true" 3897 @search-close.window="searchOpen = false" 3898 @search-opened.window="searchOpen = true" 3899 class="hidden transition-all" 3900 :class="{'': searchOpen, '': !searchOpen}"></div> 3901<main id="maincontent" class="page-main"><div id="category-header-container"><div class="bg-gray-light-category"><div class="relative flex items-stretch mb-4"><div class="padding-left-container w-full md:w-1/2 relative flex flex-col gap-4 lg:gap-6 justify-center py-5 md:min-h-80 md:pr-10 lg:pr-20"> <nav class="breadcrumbs block p-0" aria-label="Breadcrumb"> 3902 <div class="block"> 3903 <ol class="items list-reset flex flex-wrap"> 3904 <li class="item flex text-gray-dark text-xs md:text-sm home"> 3905 <a href="https://www.serrats.com/es_es" 3906 class="no-underline font-bold" 3907 title="Ir a la página de inicio" 3908 ><span>Inicio</span></a> 3909 </li> 3910 <li class="item flex text-gray-dark text-xs md:text-sm category6">
3911 <span aria-hidden="true" class="separator px-2 font-bold">/</span> 3912 <span>Bonito del Norte</span> 3913 </li> 3914 </ol> 3915 </div> 3916 </nav> 3917 3918 <div class="page-title-wrapper category-title relative text-3xl font-secondary md:text-8xl lg:pb-3"> 3919 <h1 class="page-title" 3920 > 3921 <span class="base" data-ui-id="page-title-wrapper" >Bonito del Norte</span> </h1> 3922 </div> 3923 <div class="category-description text-md text-[#535353]"> 3924 <p>El <strong>Bonito del Norte</strong> del Cantábrico es una de nuestras especialidades, llevamos elaborándolo de manera artesanal desde 1890. Es el <em>Thunnus Alalunga</em> pescado, uno a uno, durante la costera del Cantábrico de junio a septiembre. Ofrecemos las <strong>conservas de Bonito del Norte</strong> con una amplia gama de coberturas: en aceite de oliva, en escabeche, al natural, en salsa catalana⦠¡Pruébalas y cuéntanos cuál es tu Bonito del Norte en conserva favorito!</p> </div> 3925</div><div class="hidden w-1/2 md:flex flex-col items-center justify-center"><div class="category-image h-full w-full flex items-center justify-center"><img src="https://www.serrats.com/media/catalog/category/Categoria_BonitoNorte.jpg" alt="Bonito del Norte" title="Bonito del Norte" class="image object-cover h-fit w-full max-h-[380px]" width="960" height="720" /></div></div></div></div></div><div class="page messages">
3925<script> 3926 window.defaultSuccessMessageTimeout = 5000; 3927 function initMessages() { 3928 "use strict"; 3929 return { 3930 messages: window.mageMessages || [], 3931 isEmpty() { 3932 return this.messages.reduce( 3933 function (isEmpty, message) { 3934 return isEmpty && message === undefined 3935 }, true 3936 ) 3937 }, 3938 hasMessages() { 3939 return !this.isEmpty(); 3940 }, 3941 hasMessage() { 3942 return !!this.message; 3943 }, 3944 removeMessage() { 3945 this.messages[this.index] = undefined; 3946 }, 3947 addMessages(messages, hideAfter) { 3948 messages.map((message) => { 3949 this.messages = this.messages.concat(message); 3950 if (hideAfter === undefined && message.type === 'success' && window.defaultSuccessMessageTimeout) { 3951 hideAfter = window.defaultSuccessMessageTimeout; 3952 } 3953 if (hideAfter) { 3954 this.setHideTimeOut(this.messages.length -1, hideAfter); 3955 } 3956 }); 3957 }, 3958 setHideTimeOut(messageIndex, hideAfter) { 3959 setTimeout((messageIndex) => { 3960 this.messages[messageIndex] = undefined; 3961 }, hideAfter, messageIndex); 3962 }, 3963 eventListeners: { 3964 ['@messages-loaded.window'](event) { 3965 this.addMessages(event.detail.messages, event.detail.hideAfter) 3966 }, 3967 ['@private-content-loaded.window'](event) { 3968 const data = event.detail.data; 3969 if ( 3970 data.messages && 3971 data.messages.messages && 3972 data.messages.messages.length 3973 ) { 3974 this.addMessages(data.messages.messages); 3975 } 3976 }, 3977 ['@clear-messages.window']() { 3978 this.messages = []; 3979 }, 3980 ['@pageshow.window'](event) { 3981 if (event.persisted) { 3982 this.messages = []; 3983 } 3984 } 3985 }, 3986 messageIcon: { 3987 'success': `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="h-6 w-6 text-success" width="24" height="24" role="img"><path d="M173.66,98.34a8,8,0,0,1,0,11.32l-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35A8,8,0,0,1,173.66,98.34ZM232,128A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128Z"/><title>check-circle</title></svg>`, 3988 'warning': `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="h-6 w-6 text-warning" width="24" height="24" role="img"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm-8-80V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z"/><title>warning-circle</title></svg>`, 3989 'error': `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="h-6 w-6 text-danger" width="24" height="24" role="img"><path d="M165.66,101.66,139.31,128l26.35,26.34a8,8,0,0,1-11.32,11.32L128,139.31l-26.34,26.35a8,8,0,0,1-11.32-11.32L116.69,128,90.34,101.66a8,8,0,0,1,11.32-11.32L128,116.69l26.34-26.35a8,8,0,0,1,11.32,11.32ZM232,128A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128Z"/><title>x-circle</title></svg>`, 3990 'notice': `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="h-6 w-6 text-warning" width="24" height="24" role="img"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm-8-80V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z"/><title>warning-circle</title></svg>`, 3991 }, 3992 messageTitle: { 3993 'success': '¡Ãxito!', 3994 'warning': '¡Alerta!', 3995 'error': '¡Vaya! Parece que hay un problema', 3996 'notice': ' ¡Aviso!' 3997 }, 3998 messageClasses: [], 3999 getMessageUiId() { 4000 return 'message-' + this.message.type; 4001 }, 4002 getMessageClasses() { 4003 return this.messageClasses[this.message.type] || ''; 4004 } 4005 } 4006 } 4007 4008 window.addEventListener('alpine:init', () => Alpine.data('initMessages', initMessages), {once: true}) 4009</script>
4009 4010<section id="messages" 4011 x-data="initMessages" 4012 x-bind="eventListeners" 4013 role="alert" 4014> 4015 <template x-if="hasMessages"> 4016 <div role="alert" class="fixed inset-0 flex items-start px-4 pt-6 pb-6 pointer-events-none z-20 md:px-6 md:pt-20 md:pb-6"> 4017 <div class="w-full flex flex-col items-center space-y-4 sm:items-end"> 4018 <template x-for="(message, index) in messages" :key="index"> 4019 <template x-if="hasMessage"> 4020 <div :ui-id="getMessageUiId" class="max-w-sm w-full bg-white shadow-lg rounded-lg pointer-events-auto ring-1 ring-black ring-opacity-5 overflow-hidden" :class="getMessageClasses()"> 4021 <div class="p-4"> 4022 <div class="flex items-start" mcclane-data="close-generic-popup"> 4023 <div class="shrink-0" x-html="messageIcon[message.type]"></div> 4024 <div class="ml-3 w-0 flex-1 pt-0.5"> 4025 <p class="text-sm font-medium text-gray-900"><span x-html="messageTitle[message.type]"></span></p> 4026 <p class="mt-1 text-sm text-gray-500"><span mcclane-data="modal-general-info" x-html="message.text"></span></p> 4027 </div> 4028 <div class="ml-4 shrink-0 flex"> 4029 <button @click="removeMessage" class="message__close-button bg-white rounded-md inline-flex text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> 4030 <span class="sr-only">Cerrar</span> 4031 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="h-5 w-5" width="24" height="24" role="img"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/><title>x</title></svg> </button> 4032 </div> 4033 </div> 4034 </div> 4035 </div> 4036 </template> 4037 </template> 4038 </div> 4039 </div> 4040 </template> 4041</section> 4042</div><div class="row"><div class="container"><div class="row"><div class="columns"><div class="column main"> 4043 <style> 4044 :root { 4045 --product-grid-mobile-cols: 2; 4046 --product-grid-tablet-cols: 2; 4047 --product-grid-desktop-cols: 3; 4048 --product-list-mobile-cols: 1; 4049 --product-list-tablet-cols: 2; 4050 --product-list-desktop-cols: 2; 4051 } 4052</style> 4053<section> 4054
4054<script> 4055 function initToolbar_6ab591821850b() { 4056 return { 4057 options: {"productListToolbarForm":{"mode":"product_list_mode","direction":"product_list_dir","order":"product_list_order","limit":"product_list_limit","modeDefault":"grid","directionDefault":"asc","orderDefault":"position","limitDefault":12,"url":"https:\/\/www.serrats.com\/es_es\/comprar-bonito-del-norte","formKey":"wPsUdywqc8Q1myxz","post":false,"page":"p"}}.productListToolbarForm || {}, 4058 getUrlParams: function () { 4059 let decode = window.decodeURIComponent, 4060 urlPaths = this.options.url.split('?'), 4061 urlParams = urlPaths[1] ? urlPaths[1].split('&') : [], 4062 params = {}, 4063 parameters, i; 4064 4065 for (i = 0; i < urlParams.length; i++) { 4066 parameters = urlParams[i].split('='); 4067 params[decode(parameters[0])] = parameters[1] !== undefined ? 4068 decode(parameters[1].replace(/\+/g, '%20')) : 4069 ''; 4070 } 4071 4072 return params; 4073 }, 4074 getCurrentLimit: function () { 4075 return this.getUrlParams()[this.options.limit] || this.options.limitDefault; 4076 }, 4077 getCurrentPage: function () { 4078 return this.getUrlParams()[this.options.page] || 1; 4079 }, 4080 changeUrl(paramName, paramValue, defaultValue) { 4081 let urlPaths = this.options.url.split('?'), 4082 baseUrl = urlPaths[0], 4083 paramData = this.getUrlParams(), 4084 currentPage = this.getCurrentPage(), 4085 newPage; 4086 4087 /** 4088 * calculates the page on which the first item of the current page will 4089 * be with the new limit and sets that number as the new page 4090 */ 4091 if (currentPage > 1 && paramName === this.options.limit) { 4092 newPage = Math.floor(this.getCurrentLimit() * (currentPage - 1) / paramValue) + 1; 4093 4094 if (newPage > 1) { 4095 paramData[this.options.page] = newPage; 4096 } else { 4097 delete paramData[this.options.page]; 4098 } 4099 } 4100 4101 paramData[paramName] = paramValue; 4102 4103 if (this.options.post) { 4104 hyva.postForm({action: baseUrl, data: paramData}); 4105 } else { 4106 if (paramValue === defaultValue.toString()) { 4107 delete paramData[paramName]; 4108 } 4109 paramData = Object.keys(paramData).length === 0 4110 ? '' 4111 : '?' + (new URLSearchParams(paramData)); 4112 location.href = baseUrl + paramData 4113 } 4114 } 4115 } 4116 } 4117</script>
4117 4118 4119<div x-data="initToolbar_6ab591821850b()" 4120 x-defer="intersect" 4121 class="flex flex-row flex-nowrap justify-between items-strech mb-5 md:justify-end"> 4122 4123 <div class="w-full md:w-auto flex gap-x-2.5"> 4124 <div class="w-full md:hidden"><div class="md:hidden"> 4125 <button x-data="{ visible: true, selectedFilters: 0 }" 4126 @hide-sidebar-modal-button.window="visible = false" 4127 class="btn btn-dark-stroke min-w-fit w-full" 4128 :disabled="!visible" 4129 @click="$dispatch('sidebar-modal')"> 4130 <span class="text-sm sm:text-base inline-flex flex-row gap-0.5">Filtros <span class="" x-show="selectedFilters > 0" x-text="'('+selectedFilters+')'"></span></span> 4131 <span class="a-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-4 h-4" width="24" height="24" role="img"><path d="M230.6,49.53A15.81,15.81,0,0,0,216,40H40A16,16,0,0,0,28.19,66.76l.08.09L96,139.17V216a16,16,0,0,0,24.87,13.32l32-21.34A16,16,0,0,0,160,194.66V139.17l67.74-72.32.08-.09A15.8,15.8,0,0,0,230.6,49.53ZM40,56h0Zm106.18,74.58A8,8,0,0,0,144,136v58.66L112,216V136a8,8,0,0,0-2.16-5.47L40,56H216Z"/><title>funnel</title></svg> 4132</span> 4133 </button> 4134</div> 4135</div> <div class="toolbar-sorter sorter relative w-full min-w-fit md:min-w-[250px] flex flex-row align-center"> 4136 <span class="sr-only sorter-label"> 4137 Ordenar por </span> 4138 <label for="order_by" class="sorter-options btn btn-dark-stroke w-full flex flex-row flex-nowrap items-center px-1.5 cursor-pointer text-sm sm:text-base"> 4139 Ordenar por Posición <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-5 h-5" width="24" height="24" role="img"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"/><title>caret-down</title></svg> 4140 </label> 4141 <select data-role="sorter" 4142 aria-label="Ordenar por" 4143 x-ref="orderBy" 4144 class="sorter-options btn btn-dark-stroke w-full flex flex-row flex-nowrap items-center px-1.5 cursor-pointer text-sm sm:text-base appearance-none !bg-none bg-transparent text-transparent hover:text-transparent focus:text-transparent focus:bg-transparent absolute inset-0 normal-case" 4145 @change="changeUrl( 4146 'product_list_order', 4147 $event.currentTarget.options[$event.currentTarget.selectedIndex].value, 4148 options.orderDefault 4149 )"> 4150 <option value="position" 4151 class="text-primary" 4152 selected="selected" 4153 > 4154 Posición </option> 4155 <option value="name" 4156 class="text-primary" 4157 > 4158 Nombre </option> 4159 <option value="price" 4160 class="text-primary" 4161 > 4162 Precio </option> 4163 </select> 4164</div> 4165 <a title="Fijar Dirección Descendente" 4166 href="#" 4167 class="sorter-action sort-asc flex flex-col flex-nowrap justify-center pr-2.5" 4168 @click.prevent="changeUrl('product_list_dir', 'desc', options.directionDefault)" 4169 > 4170 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-5 h-5 lg:w-6 lg:h-6" width="24" height="24" role="img"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm37.66-85.66a8,8,0,0,1,0,11.32l-32,32a8,8,0,0,1-11.32,0l-32-32a8,8,0,0,1,11.32-11.32L120,148.69V88a8,8,0,0,1,16,0v60.69l18.34-18.35A8,8,0,0,1,165.66,130.34Z"/><title>arrow-circle-down</title></svg> 4171 </a> 4172 </div> 4173 </div> 4174 <div class="products wrapper mode-grid products-grid"> 4175 <div class="mx-auto pb-12 grid gap-1.5 md:gap-5 grid-cols-[repeat(var(--product-grid-mobile-cols),minmax(0,1fr))] sm:grid-cols-[repeat(var(--product-grid-tablet-cols),minmax(0,1fr))] xl:grid-cols-[repeat(var(--product-grid-desktop-cols),minmax(0,1fr))]"> 4176 <form method="post" 4177 action="https://www.serrats.com/es_es/checkout/cart/add/uenc/%25uenc%25/product/106/" 4178 class="item product product-item product_addtocart_form bg-product-bg-color border-product-bg-border attribute_set_id_4 group/card flex flex-1 flex-col transition-shadow duration-300 ease-in shadow-[0px_0px_20px_rgba(0,0,0,0.05)] hover:shadow-[0px_0px_20px_rgba(0,0,0,0.1)]" 4179 x-data="{activeItem: false, activeDetails: false}" 4180 @mouseenter="activeItem = true" 4181 @mouseleave="activeItem = false" 4182 :class="{'bg-product-bg-hover-color border-product-bg-hover-border no-hover': activeItem }" 4183> 4184 <div x-data="{ formKey: '' }" x-init="formKey = hyva.getFormKey()"> 4185 <input name="form_key" type="hidden" :value="formKey"/> 4186</div> 4187 <input type="hidden" name="product" value="106"/> 4188 <div class="container-card flex flex-col h-full"> 4189 <div class="relative"> 4190 4191<div class="relative"> 4192<div class="grid grid-cols-2 gap-2 p-2 absolute right-0 left-0 bottom-0 top-0 pointer-events-none"> 4193 </div> 4194 4195<a class="relative product photo product-item-photo block overflow-hidden" href="https://www.serrats.com/es_es/bonito-del-norte-aceite-oliva-tipica-120g" 4196 mcclane-data="category-item"> 4197 <img x-data="showHoverImage()" 4198 @update-gallery-106.window="$root.src = $event.detail" 4199 class="h-full object-contain w-full md:group-hover/card:scale-[1.05] transition-all" 4200 @mouseover="onHover()" 4201 @mouseleave="onLeave()" 4202 loading="lazy" 4203 alt="Bonito del Norte en aceite de oliva. ¡La más TÍPICA! Lata 115g." 4204 title="Bonito del Norte en aceite de oliva. ¡La más TÍPICA! Lata 115g." 4205 src="https://www.serrats.com/media/catalog/product/s/e/serrats_ro120_bno_tipica.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 4206 src-hover="" 4207 src-leave="https://www.serrats.com/media/catalog/product/s/e/serrats_ro120_bno_tipica.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 4208 width="420" 4209 height="420" 4210/> 4211 4212 4213</a> 4214</div> 4215 </div> 4216 <div class="flex flex-col pt-3 p-2.5 lg:p-4 gap-2 h-full"> 4217 <div class="flex flex-col gap-2 lg:gap-3.5"> 4218 </div> 4219 <div class="flex justify-between"> 4220 <div class="flex"> 4221 4222<a class="product-item-link" href="https://www.serrats.com/es_es/bonito-del-norte-aceite-oliva-tipica-120g" 4223 > 4224 <span class="product-card-title md:product-card-title-desktop text-product-card-title line-clamp-3 min-h-[3.5em]"> 4225 Bonito del Norte en aceite de oliva. ¡La más TÃPICA! Lata 115g.</span> 4226</a> 4227 </div> 4228 <div class="flex"> 4229 </div> 4230 </div> 4231 <div class="flex flex-col gap-3 h-full"> 4232 4233 <span class="line-clamp-1 text-sm text-gray-dark">Lata</span> 4234 <div class=""> 4235
4235<script> 4236 function initConfigurableSwatchOptions_106() { 4237 const configurableOptionsComponent = initConfigurableOptions( 4238 '106', 4239 {"attributes":{"182":{"id":"182","code":"uds_caja","label":"Uds Caja","options":[{"id":"49","label":"25","products":["31"],"type":"0","value":"25"}],"position":"0"}},"template":"<%- data.price %>\u00a0\u20ac","currencyFormat":"%s\u00a0\u20ac","optionPrices":{"31":{"baseOldPrice":{"amount":80.909089909091},"oldPrice":{"amount":89},"basePrice":{"amount":80.909089909091},"finalPrice":{"amount":89},"tierPrices":[],"msrpPrice":{"amount":0}}},"priceFormat":{"pattern":"%s\u00a0\u20ac","precision":2,"requiredPrecision":2,"decimalSymbol":",","groupSymbol":".","groupLength":3,"integerRequired":false},"prices":{"baseOldPrice":{"amount":80.909089909091},"oldPrice":{"amount":89},"basePrice":{"amount":80.909089909091},"finalPrice":{"amount":89}},"productId":"106","chooseText":"Elegir una opci\u00f3n...","images":[],"index":{"31":{"182":"49"}},"salable":[],"canDisplayShowOutOfStockStatus":false,"saleable":{"31":true},"preselect_sku_child":"SERRATS_RO120_BNO_25","childProducts":{"SERRATS_RO120_BNO_25":"31"}} ); 4240 const swatchOptionsComponent = initSwatchOptions({"182":{"49":{"type":"0","value":"25","label":"25"},"additional_data":"{\"swatch_input_type\":\"text\",\"update_product_preview_image\":\"0\",\"use_product_image_for_swatch\":0}"}}); 4241 4242 if (typeof window.configurableOptionsInitialized === "undefined") { 4243 window.configurableOptionsInitialized = []; 4244 } 4245 4246 return Object.assign( 4247 configurableOptionsComponent, 4248 swatchOptionsComponent, 4249 { 4250 mediaCallback: "https\u003A\u002F\u002Fwww.serrats.com\u002Fes_es\u002Fswatches\u002Fajax\u002Fmedia\u002F", 4251 changeOption(optionId, value, skipUpdateGallery) { 4252 this.selectedValues[optionId] = value; 4253 this.findSimpleIndex(); 4254 this.findAllowedAttributeOptions(); 4255 this.updatePrices(); 4256 !skipUpdateGallery && this.updateGallery(); 4257 4258 window.dispatchEvent( 4259 new CustomEvent( 4260 'list-configurable-selection-changed', 4261 { 4262 detail: { 4263 productId: this.productId, 4264 optionId, 4265 value, 4266 productIndex: this.productIndex, 4267 selectedValues: this.selectedValues, 4268 saleable: this.optionConfig.saleable[this.productIndex] 4269 } 4270 } 4271 ) 4272 ); 4273 }, 4274 syncConfigurableSwatchOptions(event) { 4275 let product = event.detail; 4276 if (product.productId !== this.productId) return; 4277 if (product.productIndex !== this.productIndex) this.productIndex = product.productIndex 4278 if (product.selectedValues !== this.selectedValues) this.selectedValues = product.selectedValues 4279 }, 4280 resetSwatches() { 4281 let featured = []; 4282 this.selectedValues = featured; 4283 }, 4284 updateGallery() { 4285 let configSkipGalleryUpdate = 0; 4286 4287 if (!this.productIndex || configSkipGalleryUpdate ) { 4288 return; 4289 } 4290 4291 fetch(`${this.mediaCallback}?product_id=${this.productIndex}`, { 4292 method: 'GET', 4293 headers: { 4294 'Content-Type': 'application/json', 4295 'X-Requested-With': 'XMLHttpRequest' 4296 } 4297 } 4298 ).then(response => { 4299 return response.json() 4300 } 4301 ).then(data => { 4302 if (data.errors) { 4303 // non critical failure only console logged 4304 console.warn(data.errors); 4305 } else { 4306 const image = data && data.medium; 4307 4308 image && window.dispatchEvent( 4309 new CustomEvent( 4310 "update-gallery-106", 4311 {detail: image} 4312 ) 4313 ); 4314 } 4315 }).catch(error => { 4316 console.warn(error) 4317 }); 4318 }, 4319 preselectQuerystringItems() { 4320 // pre-select option like ?size=167 4321 const urlQueryParams = new URLSearchParams(window.location.search.replace('?', '')); 4322 Object.values(this.optionConfig.attributes).map(attribute => { 4323 // Don't update images on load, since PLPs already set the main image to the selected options 4324 const skipUpdateGallery = true; 4325 urlQueryParams.get(attribute.code) && 4326 this.changeOption(attribute.id, urlQueryParams.get(attribute.code), skipUpdateGallery); 4327 }); 4328 }, 4329 mouseDown: false, 4330 startX: 0, 4331 maxScroll: 0, 4332 scrollLeft: null, 4333 slider: null, 4334 attributeIdFeatured: null, 4335 items: [], 4336 limitToScroll: 0, 4337 limitToScrollMobile: 3, 4338 limitToScrollDesktop: 5, 4339 scrollEvents: { 4340 ['@mousedown'](e) { 4341 this.slider = e.target.closest('.snap'); 4342 if (!this.slider) { 4343 return; 4344 } 4345 this.maxScroll = this.slider.scrollWidth - this.slider.offsetWidth; 4346 this.startX = e.pageX - this.slider.offsetLeft; 4347 this.scrollLeft = this.slider.scrollLeft; 4348 this.mouseDown = true; 4349 }, 4350 ['@mouseout.self']() { 4351 this.mouseDown = false;
4352 }, 4353 ['@mouseup']() { 4354 this.mouseDown = false; 4355 }, 4356 ['@mousemove'](e) { 4357 e.preventDefault(); 4358 if (!this.mouseDown) { 4359 return; 4360 } 4361 const x = e.pageX - this.slider.offsetLeft; 4362 const scroll = x - this.startX; 4363 const scrollLeft = this.scrollLeft - scroll; 4364 4365 if (scrollLeft > this.maxScroll) { 4366 this.slider.scrollLeft = this.maxScroll; 4367 return 4368 } 4369 this.slider.scrollLeft = this.scrollLeft - scroll; 4370 }, 4371 ['@onselectstart']() { 4372 return false; 4373 }, 4374 ['@resize.window']() { 4375 this.initShowScrollSwatches(); 4376 }, 4377 ['@tabchange.window']() { 4378 this.initShowScrollSwatches(); 4379 } 4380 }, 4381 clickLeftEvent() { 4382 this.slider = this.$root.querySelector('.snap'); 4383 this.slider.scrollLeft -= this.slider.offsetWidth; 4384 }, 4385 clickRightEvent() { 4386 this.slider = this.$root.querySelector('.snap'); 4387 this.slider.scrollLeft += this.slider.offsetWidth; 4388 }, 4389 setLimitScroll() { 4390 this.limitToScroll = window.innerWidth > 767 ? this.limitToScrollDesktop : this.limitToScrollMobile; 4391 }, 4392 initShowScrollSwatches() { 4393 this.$nextTick(() => { 4394 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
4394der => { 4395 this.items = slider.querySelectorAll(':scope > div:not(.hidden)'); 4396 this.setLimitScroll(); 4397 4398 if (this.limitToScroll > this.items.length) { 4399 this.limitToScroll = this.items.length; 4400 } 4401 4402 let itemLimit = this.items[this.limitToScroll - 1]; 4403 let marginOffset = parseFloat(getComputedStyle(slider.parentElement).marginLeft) + parseFloat(getComputedStyle(slider.parentElement).marginRight); 4404 4405 let widthMax = this.$root.offsetWidth - marginOffset; 4406 let width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 4407 4408 slider.style.width = width + 'px'; 4409 slider.scrollLeft = 0; 4410 4411 while (width > widthMax && this.limitToScroll > 1) { 4412 this.limitToScroll--; 4413 itemLimit = this.items[this.limitToScroll - 1]; 4414 width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 4415 slider.style.width = width + 'px'; 4416 slider.scrollLeft = 0; 4417 } 4418 }); 4419 }); 4420 }, 4421 resizeEvent() { 4422 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
4422der => { 4423 slider.scrollLeft = 0; 4424 }) 4425 }, 4426 contentLoaded(eventData) { 4427 if (typeof window.configurableOptionsInitialized[this.productId] !== "undefined") { 4428 return; 4429 } 4430 4431 this.onGetCartData(eventData); 4432 window.configurableOptionsInitialized[this.productId] = true; 4433 } 4434 } 4435 ); 4436 } 4437</script>
4437 4438 4439 4440<div x-data="initConfigurableSwatchOptions_106()" 4441 x-init="findAllowedAttributeOptions(); initShowSwatchesIntersect();" 4442 @list-configurable-selection-changed.window="syncConfigurableSwatchOptions($event)" 4443 @list-swatches-reset-106.window="resetSwatches()" 4444 @private-content-loaded.window="contentLoaded($event.detail.data)" 4445 @resize.window="resizeEvent()" 4446> 4447 <div class="flex flex-col flex-nowrap gap-y-3"> 4448 4449 4450<div class="flex flex-col swatch-attribute"> 4451 <div class="flex mx-0 serrats-table-header uppercase border-b border-[#d9ddd7]"> 4452 <div class="w-1/3 px-0">Unidades caja</div> 4453 <div class="w-1/3 px-0 text-center">Precio unidad</div> 4454 <div class="w-1/3 px-0 text-center font-semibold"><span>Precio caja</span></div> 4455 </div> 4456 <template x-for="(item, index) in optionConfig.attributes[182].options" :key="item.id"> 4457 <div class="py-2"> 4458 <template x-if="optionIsEnabled(182, item.id)"> 4459 <label 4460 :for="'attribute-option-106-'+item.id" 4461 :mcclane-data="'product-configurable-custom-option-'+item.id" 4462 @touchend.passive="selectedValues[182] ? '' : changeOption(182, item.id)" 4463 class="flex items-center gap-2" 4464 > 4465 <input 4466 :id="'attribute-option-106-'+item.id" 4467 :value="item.id" 4468 name="super_attribute[182]" 4469 type="radio" 4470 class="border-0 focus:border-0 focus:ring-0 inline-block p-0 opacity-0 product-option-value-input absolute" 4471 style="z-index:-1" 4472 x-on:focus="focusLabel(item.id)" 4473 x-on:blur="blurLabel()" 4474 x-on:change="changeOption(182, $event.target.value)" 4475 @list-configurable-selection-changed.window="findAllowedAttributeOptions();" 4476 x-model="selectedValues[182]" 4477 :required="getAllowedAttributeOptions(182).filter(attributeOption => selectedValues[attributeOption]).length === 0" 4478 /> 4479 <div class="flex flex-grow items-center mx-0 cursor-pointer" x-data="{prices: optionConfig.optionPrices[item.availableProductsId[0]]}"> 4480 <div class="w-1/3"> 4481 <span class="inline-block lowercase text-sm serrats-custom-swatch-container flex items-center" :class="{'selected': selectedValues[182] === item.id}" x-text="getSwatchText(182, item.id) + ' uds.'"></span> 4482 </div> 4483 <div class="w-1/3 px-0 text-center"> 4484 <span class="inline-block font-medium text-sm line-through text-gray-medium" x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" x-text="hyva.formatPrice(prices.oldPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 4485 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 4486 </div> 4487 <div class="w-1/3 px-0 text-center"> 4488 <span x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" class="line-through text-gray-medium inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.oldPrice.amount, false, optionConfig.priceFormat)"></span> 4489 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount, false, optionConfig.priceFormat)"></span> 4490 </div> 4491 </div> 4492 </label> 4493 </template> 4494</div> 4495 </template> 4496</div> 4497 </div> 4498 <template x-if="isTooltipVisible()"> 4499 <div class="absolute" :style="getTooltipPosition()"> 4500 <div class="whitespace-nowrap shadow-lg absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-full z-10 p-1.5 -mt-1.5 text-xs text-white bg-black shadow-lg text-center"> 4501 <template x-if="isVisualSwatch(activeTooltipItem.attribute, activeTooltipItem.item)"> 4502 <div class="hidden border shadow-sm border-container" 4503 :style="getTooltipImageStyle(activeTooltipItem.attribute, activeTooltipItem.item)" 4504 ></div> 4505 </template>
4506 <span x-html="getTooltipLabel()"></span> 4507 </div> 4508 <svg xmlns="http://www.w3.org/2000/svg" 4509 viewBox="0 0 9 4.5" 4510 width="9" 4511 height="9" 4512 class="shadow-lg absolute left-1/2 transform -translate-x-1/2 -translate-y-full"> 4513 <path d="M-.025 0L4.5-4.525 9.025 0 4.5 4.525z"/> 4514 </svg> 4515 </div> 4516</template> 4517 </div> 4518 </div> 4519 4520 <div 4521 class="mt-auto" 4522 x-data="{showAddToCartButton: true, productId: '106' }" 4523 :class="{'': showAddToCartButton, '': !showAddToCartButton}" 4524 @list-configurable-selection-changed.window="if(productId === $event.detail.productId) showAddToCartButton = $event.detail.saleable"> 4525 <div x-cloak x-show="!showAddToCartButton"> 4526 <a class="btn bg-gray w-full shadow rounded" href="https://www.serrats.com/es_es/bonito-del-norte-aceite-oliva-tipica-120g"> 4527 <span>No está disponible</span> 4528 </a> 4529 </div> 4530 <button class="btn btn-dark-fill shadow w-full" 4531 x-show="showAddToCartButton" 4532 aria-label="Añadir al carrito"> 4533 <span class="">Añadir al carrito</span> 4534 </button> 4535 </div> 4536 </div> 4537 </div> 4538 </div> 4539 4540 </form> 4541 <form method="post" 4542 action="https://www.serrats.com/es_es/checkout/cart/add/uenc/%25uenc%25/product/198/" 4543 class="item product product-item product_addtocart_form bg-product-bg-color border-product-bg-border attribute_set_id_4 group/card flex flex-1 flex-col transition-shadow duration-300 ease-in shadow-[0px_0px_20px_rgba(0,0,0,0.05)] hover:shadow-[0px_0px_20px_rgba(0,0,0,0.1)]" 4544 x-data="{activeItem: false, activeDetails: false}" 4545 @mouseenter="activeItem = true" 4546 @mouseleave="activeItem = false" 4547 :class="{'bg-product-bg-hover-color border-product-bg-hover-border no-hover': activeItem }" 4548> 4549 <div x-data="{ formKey: '' }" x-init="formKey = hyva.getFormKey()"> 4550 <input name="form_key" type="hidden" :value="formKey"/> 4551</div> 4552 <input type="hidden" name="product" value="198"/> 4553 <div class="container-card flex flex-col h-full"> 4554 <div class="relative"> 4555 4556<div class="relative"> 4557<div class="grid grid-cols-2 gap-2 p-2 absolute right-0 left-0 bottom-0 top-0 pointer-events-none"> 4558 </div> 4559 4560<a class="relative product photo product-item-photo block overflow-hidden" href="https://www.serrats.com/es_es/bonito-norte-al-natural-lata-115g" 4561 mcclane-data="category-item"> 4562 <img x-data="showHoverImage()" 4563 @update-gallery-198.window="$root.src = $event.detail" 4564 class="h-full object-contain w-full md:group-hover/card:scale-[1.05] transition-all" 4565 @mouseover="onHover()" 4566 @mouseleave="onLeave()" 4567 loading="lazy" 4568 alt="Bonito del Norte al natural. Lata 115g." 4569 title="Bonito del Norte al natural. Lata 115g." 4570 src="https://www.serrats.com/media/catalog/product/m/i/miniatura_serrats_ro120_bnn_msc.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 4571 src-hover="" 4572 src-leave="https://www.serrats.com/media/catalog/product/m/i/miniatura_serrats_ro120_bnn_msc.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 4573 width="420" 4574 height="420" 4575/> 4576 4577 4578</a> 4579</div> 4580 </div> 4581 <div class="flex flex-col pt-3 p-2.5 lg:p-4 gap-2 h-full"> 4582 <div class="flex flex-col gap-2 lg:gap-3.5"> 4583 </div> 4584 <div class="flex justify-between"> 4585 <div class="flex"> 4586 4587<a class="product-item-link" href="https://www.serrats.com/es_es/bonito-norte-al-natural-lata-115g" 4588 > 4589 <span class="product-card-title md:product-card-title-desktop text-product-card-title line-clamp-3 min-h-[3.5em]"> 4590 Bonito del Norte al natural. Lata 115g.</span> 4591</a> 4592 </div> 4593 <div class="flex"> 4594 </div> 4595 </div> 4596 <div class="flex flex-col gap-3 h-full"> 4597 4598 <span class="line-clamp-1 text-sm text-gray-dark">Lata</span> 4599 <div class=""> 4600
4600<script> 4601 function initConfigurableSwatchOptions_198() { 4602 const configurableOptionsComponent = initConfigurableOptions( 4603 '198', 4604 {"attributes":{"182":{"id":"182","code":"uds_caja","label":"Uds Caja","options":[{"id":"49","label":"25","products":["197"],"type":"0","value":"25"}],"position":"0"}},"template":"<%- data.price %>\u00a0\u20ac","currencyFormat":"%s\u00a0\u20ac","optionPrices":{"197":{"baseOldPrice":{"amount":79.090908090909},"oldPrice":{"amount":87},"basePrice":{"amount":79.090908090909},"finalPrice":{"amount":87},"tierPrices":[],"msrpPrice":{"amount":0}}},"priceFormat":{"pattern":"%s\u00a0\u20ac","precision":2,"requiredPrecision":2,"decimalSymbol":",","groupSymbol":".","groupLength":3,"integerRequired":false},"prices":{"baseOldPrice":{"amount":79.090908090909},"oldPrice":{"amount":87},"basePrice":{"amount":79.090908090909},"finalPrice":{"amount":87}},"productId":"198","chooseText":"Elegir una opci\u00f3n...","images":[],"index":{"197":{"182":"49"}},"salable":[],"canDisplayShowOutOfStockStatus":false,"saleable":{"197":true},"preselect_sku_child":"SERRATS_RO120_BNN_25","childProducts":{"SERRATS_RO120_BNN_25":"197"}} ); 4605 const swatchOptionsComponent = initSwatchOptions({"182":{"49":{"type":"0","value":"25","label":"25"},"additional_data":"{\"swatch_input_type\":\"text\",\"update_product_preview_image\":\"0\",\"use_product_image_for_swatch\":0}"}}); 4606 4607 if (typeof window.configurableOptionsInitialized === "undefined") { 4608 window.configurableOptionsInitialized = []; 4609 } 4610 4611 return Object.assign( 4612 configurableOptionsComponent, 4613 swatchOptionsComponent, 4614 { 4615 mediaCallback: "https\u003A\u002F\u002Fwww.serrats.com\u002Fes_es\u002Fswatches\u002Fajax\u002Fmedia\u002F", 4616 changeOption(optionId, value, skipUpdateGallery) { 4617 this.selectedValues[optionId] = value; 4618 this.findSimpleIndex(); 4619 this.findAllowedAttributeOptions(); 4620 this.updatePrices(); 4621 !skipUpdateGallery && this.updateGallery(); 4622 4623 window.dispatchEvent( 4624 new CustomEvent( 4625 'list-configurable-selection-changed', 4626 { 4627 detail: { 4628 productId: this.productId, 4629 optionId, 4630 value, 4631 productIndex: this.productIndex, 4632 selectedValues: this.selectedValues, 4633 saleable: this.optionConfig.saleable[this.productIndex] 4634 } 4635 } 4636 ) 4637 ); 4638 }, 4639 syncConfigurableSwatchOptions(event) { 4640 let product = event.detail; 4641 if (product.productId !== this.productId) return; 4642 if (product.productIndex !== this.productIndex) this.productIndex = product.productIndex 4643 if (product.selectedValues !== this.selectedValues) this.selectedValues = product.selectedValues 4644 }, 4645 resetSwatches() { 4646 let featured = []; 4647 this.selectedValues = featured; 4648 }, 4649 updateGallery() { 4650 let configSkipGalleryUpdate = 0; 4651 4652 if (!this.productIndex || configSkipGalleryUpdate ) { 4653 return; 4654 } 4655 4656 fetch(`${this.mediaCallback}?product_id=${this.productIndex}`, { 4657 method: 'GET', 4658 headers: { 4659 'Content-Type': 'application/json', 4660 'X-Requested-With': 'XMLHttpRequest' 4661 } 4662 } 4663 ).then(response => { 4664 return response.json() 4665 } 4666 ).then(data => { 4667 if (data.errors) { 4668 // non critical failure only console logged 4669 console.warn(data.errors); 4670 } else { 4671 const image = data && data.medium; 4672 4673 image && window.dispatchEvent( 4674 new CustomEvent( 4675 "update-gallery-198", 4676 {detail: image} 4677 ) 4678 ); 4679 } 4680 }).catch(error => { 4681 console.warn(error) 4682 }); 4683 }, 4684 preselectQuerystringItems() { 4685 // pre-select option like ?size=167 4686 const urlQueryParams = new URLSearchParams(window.location.search.replace('?', '')); 4687 Object.values(this.optionConfig.attributes).map(attribute => { 4688 // Don't update images on load, since PLPs already set the main image to the selected options 4689 const skipUpdateGallery = true; 4690 urlQueryParams.get(attribute.code) && 4691 this.changeOption(attribute.id, urlQueryParams.get(attribute.code), skipUpdateGallery); 4692 }); 4693 }, 4694 mouseDown: false, 4695 startX: 0, 4696 maxScroll: 0, 4697 scrollLeft: null, 4698 slider: null, 4699 attributeIdFeatured: null, 4700 items: [], 4701 limitToScroll: 0, 4702 limitToScrollMobile: 3, 4703 limitToScrollDesktop: 5, 4704 scrollEvents: { 4705 ['@mousedown'](e) { 4706 this.slider = e.target.closest('.snap'); 4707 if (!this.slider) { 4708 return; 4709 } 4710 this.maxScroll = this.slider.scrollWidth - this.slider.offsetWidth; 4711 this.startX = e.pageX - this.slider.offsetLeft; 4712 this.scrollLeft = this.slider.scrollLeft; 4713 this.mouseDown = true; 4714 }, 4715 ['@mouseout.self']() { 4716 this.mouseDown = false;
4717 }, 4718 ['@mouseup']() { 4719 this.mouseDown = false; 4720 }, 4721 ['@mousemove'](e) { 4722 e.preventDefault(); 4723 if (!this.mouseDown) { 4724 return; 4725 } 4726 const x = e.pageX - this.slider.offsetLeft; 4727 const scroll = x - this.startX; 4728 const scrollLeft = this.scrollLeft - scroll; 4729 4730 if (scrollLeft > this.maxScroll) { 4731 this.slider.scrollLeft = this.maxScroll; 4732 return 4733 } 4734 this.slider.scrollLeft = this.scrollLeft - scroll; 4735 }, 4736 ['@onselectstart']() { 4737 return false; 4738 }, 4739 ['@resize.window']() { 4740 this.initShowScrollSwatches(); 4741 }, 4742 ['@tabchange.window']() { 4743 this.initShowScrollSwatches(); 4744 } 4745 }, 4746 clickLeftEvent() { 4747 this.slider = this.$root.querySelector('.snap'); 4748 this.slider.scrollLeft -= this.slider.offsetWidth; 4749 }, 4750 clickRightEvent() { 4751 this.slider = this.$root.querySelector('.snap'); 4752 this.slider.scrollLeft += this.slider.offsetWidth; 4753 }, 4754 setLimitScroll() { 4755 this.limitToScroll = window.innerWidth > 767 ? this.limitToScrollDesktop : this.limitToScrollMobile; 4756 }, 4757 initShowScrollSwatches() { 4758 this.$nextTick(() => { 4759 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
4759der => { 4760 this.items = slider.querySelectorAll(':scope > div:not(.hidden)'); 4761 this.setLimitScroll(); 4762 4763 if (this.limitToScroll > this.items.length) { 4764 this.limitToScroll = this.items.length; 4765 } 4766 4767 let itemLimit = this.items[this.limitToScroll - 1]; 4768 let marginOffset = parseFloat(getComputedStyle(slider.parentElement).marginLeft) + parseFloat(getComputedStyle(slider.parentElement).marginRight); 4769 4770 let widthMax = this.$root.offsetWidth - marginOffset; 4771 let width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 4772 4773 slider.style.width = width + 'px'; 4774 slider.scrollLeft = 0; 4775 4776 while (width > widthMax && this.limitToScroll > 1) { 4777 this.limitToScroll--; 4778 itemLimit = this.items[this.limitToScroll - 1]; 4779 width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 4780 slider.style.width = width + 'px'; 4781 slider.scrollLeft = 0; 4782 } 4783 }); 4784 }); 4785 }, 4786 resizeEvent() { 4787 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
4787der => { 4788 slider.scrollLeft = 0; 4789 }) 4790 }, 4791 contentLoaded(eventData) { 4792 if (typeof window.configurableOptionsInitialized[this.productId] !== "undefined") { 4793 return; 4794 } 4795 4796 this.onGetCartData(eventData); 4797 window.configurableOptionsInitialized[this.productId] = true; 4798 } 4799 } 4800 ); 4801 } 4802</script>
4802 4803 4804 4805<div x-data="initConfigurableSwatchOptions_198()" 4806 x-init="findAllowedAttributeOptions(); initShowSwatchesIntersect();" 4807 @list-configurable-selection-changed.window="syncConfigurableSwatchOptions($event)" 4808 @list-swatches-reset-198.window="resetSwatches()" 4809 @private-content-loaded.window="contentLoaded($event.detail.data)" 4810 @resize.window="resizeEvent()" 4811> 4812 <div class="flex flex-col flex-nowrap gap-y-3"> 4813 4814 4815<div class="flex flex-col swatch-attribute"> 4816 <div class="flex mx-0 serrats-table-header uppercase border-b border-[#d9ddd7]"> 4817 <div class="w-1/3 px-0">Unidades caja</div> 4818 <div class="w-1/3 px-0 text-center">Precio unidad</div> 4819 <div class="w-1/3 px-0 text-center font-semibold"><span>Precio caja</span></div> 4820 </div> 4821 <template x-for="(item, index) in optionConfig.attributes[182].options" :key="item.id"> 4822 <div class="py-2"> 4823 <template x-if="optionIsEnabled(182, item.id)"> 4824 <label 4825 :for="'attribute-option-198-'+item.id" 4826 :mcclane-data="'product-configurable-custom-option-'+item.id" 4827 @touchend.passive="selectedValues[182] ? '' : changeOption(182, item.id)" 4828 class="flex items-center gap-2" 4829 > 4830 <input 4831 :id="'attribute-option-198-'+item.id" 4832 :value="item.id" 4833 name="super_attribute[182]" 4834 type="radio" 4835 class="border-0 focus:border-0 focus:ring-0 inline-block p-0 opacity-0 product-option-value-input absolute" 4836 style="z-index:-1" 4837 x-on:focus="focusLabel(item.id)" 4838 x-on:blur="blurLabel()" 4839 x-on:change="changeOption(182, $event.target.value)" 4840 @list-configurable-selection-changed.window="findAllowedAttributeOptions();" 4841 x-model="selectedValues[182]" 4842 :required="getAllowedAttributeOptions(182).filter(attributeOption => selectedValues[attributeOption]).length === 0" 4843 /> 4844 <div class="flex flex-grow items-center mx-0 cursor-pointer" x-data="{prices: optionConfig.optionPrices[item.availableProductsId[0]]}"> 4845 <div class="w-1/3"> 4846 <span class="inline-block lowercase text-sm serrats-custom-swatch-container flex items-center" :class="{'selected': selectedValues[182] === item.id}" x-text="getSwatchText(182, item.id) + ' uds.'"></span> 4847 </div> 4848 <div class="w-1/3 px-0 text-center"> 4849 <span class="inline-block font-medium text-sm line-through text-gray-medium" x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" x-text="hyva.formatPrice(prices.oldPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 4850 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 4851 </div> 4852 <div class="w-1/3 px-0 text-center"> 4853 <span x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" class="line-through text-gray-medium inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.oldPrice.amount, false, optionConfig.priceFormat)"></span> 4854 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount, false, optionConfig.priceFormat)"></span> 4855 </div> 4856 </div> 4857 </label> 4858 </template> 4859</div> 4860 </template> 4861</div> 4862 </div> 4863 <template x-if="isTooltipVisible()"> 4864 <div class="absolute" :style="getTooltipPosition()"> 4865 <div class="whitespace-nowrap shadow-lg absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-full z-10 p-1.5 -mt-1.5 text-xs text-white bg-black shadow-lg text-center"> 4866 <template x-if="isVisualSwatch(activeTooltipItem.attribute, activeTooltipItem.item)"> 4867 <div class="hidden border shadow-sm border-container" 4868 :style="getTooltipImageStyle(activeTooltipItem.attribute, activeTooltipItem.item)" 4869 ></div> 4870 </template>
4871 <span x-html="getTooltipLabel()"></span> 4872 </div> 4873 <svg xmlns="http://www.w3.org/2000/svg" 4874 viewBox="0 0 9 4.5" 4875 width="9" 4876 height="9" 4877 class="shadow-lg absolute left-1/2 transform -translate-x-1/2 -translate-y-full"> 4878 <path d="M-.025 0L4.5-4.525 9.025 0 4.5 4.525z"/> 4879 </svg> 4880 </div> 4881</template> 4882 </div> 4883 </div> 4884 4885 <div 4886 class="mt-auto" 4887 x-data="{showAddToCartButton: true, productId: '198' }" 4888 :class="{'': showAddToCartButton, '': !showAddToCartButton}" 4889 @list-configurable-selection-changed.window="if(productId === $event.detail.productId) showAddToCartButton = $event.detail.saleable"> 4890 <div x-cloak x-show="!showAddToCartButton"> 4891 <a class="btn bg-gray w-full shadow rounded" href="https://www.serrats.com/es_es/bonito-norte-al-natural-lata-115g"> 4892 <span>No está disponible</span> 4893 </a> 4894 </div> 4895 <button class="btn btn-dark-fill shadow w-full" 4896 x-show="showAddToCartButton" 4897 aria-label="Añadir al carrito"> 4898 <span class="">Añadir al carrito</span> 4899 </button> 4900 </div> 4901 </div> 4902 </div> 4903 </div> 4904 4905 </form> 4906 <form method="post" 4907 action="https://www.serrats.com/es_es/checkout/cart/add/uenc/%25uenc%25/product/95/" 4908 class="item product product-item product_addtocart_form bg-product-bg-color border-product-bg-border attribute_set_id_4 group/card flex flex-1 flex-col transition-shadow duration-300 ease-in shadow-[0px_0px_20px_rgba(0,0,0,0.05)] hover:shadow-[0px_0px_20px_rgba(0,0,0,0.1)]" 4909 x-data="{activeItem: false, activeDetails: false}" 4910 @mouseenter="activeItem = true" 4911 @mouseleave="activeItem = false" 4912 :class="{'bg-product-bg-hover-color border-product-bg-hover-border no-hover': activeItem }" 4913> 4914 <div x-data="{ formKey: '' }" x-init="formKey = hyva.getFormKey()"> 4915 <input name="form_key" type="hidden" :value="formKey"/> 4916</div> 4917 <input type="hidden" name="product" value="95"/> 4918 <div class="container-card flex flex-col h-full"> 4919 <div class="relative"> 4920 4921<div class="relative"> 4922<div class="grid grid-cols-2 gap-2 p-2 absolute right-0 left-0 bottom-0 top-0 pointer-events-none"> 4923 </div> 4924 4925<a class="relative product photo product-item-photo block overflow-hidden" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-120g-25u" 4926 mcclane-data="category-item"> 4927 <img x-data="showHoverImage()" 4928 @update-gallery-95.window="$root.src = $event.detail" 4929 class="h-full object-contain w-full md:group-hover/card:scale-[1.05] transition-all" 4930 @mouseover="onHover()" 4931 @mouseleave="onLeave()" 4932 loading="lazy" 4933 alt="Bonito del Norte en aceite de oliva. Lata 112g." 4934 title="Bonito del Norte en aceite de oliva. Lata 112g." 4935 src="https://www.serrats.com/media/catalog/product/m/i/miniatura_ol120_litografiado_1.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 4936 src-hover="" 4937 src-leave="https://www.serrats.com/media/catalog/product/m/i/miniatura_ol120_litografiado_1.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 4938 width="420" 4939 height="420" 4940/> 4941 4942 4943</a> 4944</div> 4945 </div> 4946 <div class="flex flex-col pt-3 p-2.5 lg:p-4 gap-2 h-full"> 4947 <div class="flex flex-col gap-2 lg:gap-3.5"> 4948 </div> 4949 <div class="flex justify-between"> 4950 <div class="flex"> 4951 4952<a class="product-item-link" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-120g-25u" 4953 > 4954 <span class="product-card-title md:product-card-title-desktop text-product-card-title line-clamp-3 min-h-[3.5em]"> 4955 Bonito del Norte en aceite de oliva. Lata 112g.</span> 4956</a> 4957 </div> 4958 <div class="flex"> 4959 </div> 4960 </div> 4961 <div class="flex flex-col gap-3 h-full"> 4962 4963 <span class="line-clamp-1 text-sm text-gray-dark">Lata</span> 4964 <div class=""> 4965
4965<script> 4966 function initConfigurableSwatchOptions_95() { 4967 const configurableOptionsComponent = initConfigurableOptions( 4968 '95', 4969 {"attributes":{"182":{"id":"182","code":"uds_caja","label":"Uds Caja","options":[{"id":"43","label":"12","products":["21"],"type":"0","value":"12"}],"position":"0"}},"template":"<%- data.price %>\u00a0\u20ac","currencyFormat":"%s\u00a0\u20ac","optionPrices":{"21":{"baseOldPrice":{"amount":39.999999},"oldPrice":{"amount":44},"basePrice":{"amount":39.999999},"finalPrice":{"amount":44},"tierPrices":[],"msrpPrice":{"amount":0}}},"priceFormat":{"pattern":"%s\u00a0\u20ac","precision":2,"requiredPrecision":2,"decimalSymbol":",","groupSymbol":".","groupLength":3,"integerRequired":false},"prices":{"baseOldPrice":{"amount":39.999999},"oldPrice":{"amount":44},"basePrice":{"amount":39.999999},"finalPrice":{"amount":44}},"productId":"95","chooseText":"Elegir una opci\u00f3n...","images":[],"index":{"21":{"182":"43"}},"salable":[],"canDisplayShowOutOfStockStatus":false,"preSelectedGallery":[],"saleable":{"21":true},"preselect_sku_child":"SERRATS_OL120_BNO_12","childProducts":{"SERRATS_OL120_BNO_12":"21"}} ); 4970 const swatchOptionsComponent = initSwatchOptions({"182":{"43":{"type":"0","value":"12","label":"12"},"additional_data":"{\"swatch_input_type\":\"text\",\"update_product_preview_image\":\"0\",\"use_product_image_for_swatch\":0}"}}); 4971 4972 if (typeof window.configurableOptionsInitialized === "undefined") { 4973 window.configurableOptionsInitialized = []; 4974 } 4975 4976 return Object.assign( 4977 configurableOptionsComponent, 4978 swatchOptionsComponent, 4979 { 4980 mediaCallback: "https\u003A\u002F\u002Fwww.serrats.com\u002Fes_es\u002Fswatches\u002Fajax\u002Fmedia\u002F", 4981 changeOption(optionId, value, skipUpdateGallery) { 4982 this.selectedValues[optionId] = value; 4983 this.findSimpleIndex(); 4984 this.findAllowedAttributeOptions(); 4985 this.updatePrices(); 4986 !skipUpdateGallery && this.updateGallery(); 4987 4988 window.dispatchEvent( 4989 new CustomEvent( 4990 'list-configurable-selection-changed', 4991 { 4992 detail: { 4993 productId: this.productId, 4994 optionId, 4995 value, 4996 productIndex: this.productIndex, 4997 selectedValues: this.selectedValues, 4998 saleable: this.optionConfig.saleable[this.productIndex] 4999 } 5000 } 5001 ) 5002 ); 5003 }, 5004 syncConfigurableSwatchOptions(event) { 5005 let product = event.detail; 5006 if (product.productId !== this.productId) return; 5007 if (product.productIndex !== this.productIndex) this.productIndex = product.productIndex 5008 if (product.selectedValues !== this.selectedValues) this.selectedValues = product.selectedValues 5009 }, 5010 resetSwatches() { 5011 let featured = []; 5012 this.selectedValues = featured; 5013 }, 5014 updateGallery() { 5015 let configSkipGalleryUpdate = 0; 5016 5017 if (!this.productIndex || configSkipGalleryUpdate ) { 5018 return; 5019 } 5020 5021 fetch(`${this.mediaCallback}?product_id=${this.productIndex}`, { 5022 method: 'GET', 5023 headers: { 5024 'Content-Type': 'application/json', 5025 'X-Requested-With': 'XMLHttpRequest' 5026 } 5027 } 5028 ).then(response => { 5029 return response.json() 5030 } 5031 ).then(data => { 5032 if (data.errors) { 5033 // non critical failure only console logged 5034 console.warn(data.errors); 5035 } else { 5036 const image = data && data.medium; 5037 5038 image && window.dispatchEvent( 5039 new CustomEvent( 5040 "update-gallery-95", 5041 {detail: image} 5042 ) 5043 ); 5044 } 5045 }).catch(error => { 5046 console.warn(error) 5047 }); 5048 }, 5049 preselectQuerystringItems() { 5050 // pre-select option like ?size=167 5051 const urlQueryParams = new URLSearchParams(window.location.search.replace('?', '')); 5052 Object.values(this.optionConfig.attributes).map(attribute => { 5053 // Don't update images on load, since PLPs already set the main image to the selected options 5054 const skipUpdateGallery = true; 5055 urlQueryParams.get(attribute.code) && 5056 this.changeOption(attribute.id, urlQueryParams.get(attribute.code), skipUpdateGallery); 5057 }); 5058 }, 5059 mouseDown: false, 5060 startX: 0, 5061 maxScroll: 0, 5062 scrollLeft: null, 5063 slider: null, 5064 attributeIdFeatured: null, 5065 items: [], 5066 limitToScroll: 0, 5067 limitToScrollMobile: 3, 5068 limitToScrollDesktop: 5, 5069 scrollEvents: { 5070 ['@mousedown'](e) { 5071 this.slider = e.target.closest('.snap'); 5072 if (!this.slider) { 5073 return; 5074 } 5075 this.maxScroll = this.slider.scrollWidth - this.slider.offsetWidth; 5076 this.startX = e.pageX - this.slider.offsetLeft; 5077 this.scrollLeft = this.slider.scrollLeft; 5078 this.mouseDown = true; 5079 }, 5080 ['@mouseout.self']() { 5081 this.mouseDown = false;
5082 }, 5083 ['@mouseup']() { 5084 this.mouseDown = false; 5085 }, 5086 ['@mousemove'](e) { 5087 e.preventDefault(); 5088 if (!this.mouseDown) { 5089 return; 5090 } 5091 const x = e.pageX - this.slider.offsetLeft; 5092 const scroll = x - this.startX; 5093 const scrollLeft = this.scrollLeft - scroll; 5094 5095 if (scrollLeft > this.maxScroll) { 5096 this.slider.scrollLeft = this.maxScroll; 5097 return 5098 } 5099 this.slider.scrollLeft = this.scrollLeft - scroll; 5100 }, 5101 ['@onselectstart']() { 5102 return false; 5103 }, 5104 ['@resize.window']() { 5105 this.initShowScrollSwatches(); 5106 }, 5107 ['@tabchange.window']() { 5108 this.initShowScrollSwatches(); 5109 } 5110 }, 5111 clickLeftEvent() { 5112 this.slider = this.$root.querySelector('.snap'); 5113 this.slider.scrollLeft -= this.slider.offsetWidth; 5114 }, 5115 clickRightEvent() { 5116 this.slider = this.$root.querySelector('.snap'); 5117 this.slider.scrollLeft += this.slider.offsetWidth; 5118 }, 5119 setLimitScroll() { 5120 this.limitToScroll = window.innerWidth > 767 ? this.limitToScrollDesktop : this.limitToScrollMobile; 5121 }, 5122 initShowScrollSwatches() { 5123 this.$nextTick(() => { 5124 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
5124der => { 5125 this.items = slider.querySelectorAll(':scope > div:not(.hidden)'); 5126 this.setLimitScroll(); 5127 5128 if (this.limitToScroll > this.items.length) { 5129 this.limitToScroll = this.items.length; 5130 } 5131 5132 let itemLimit = this.items[this.limitToScroll - 1]; 5133 let marginOffset = parseFloat(getComputedStyle(slider.parentElement).marginLeft) + parseFloat(getComputedStyle(slider.parentElement).marginRight); 5134 5135 let widthMax = this.$root.offsetWidth - marginOffset; 5136 let width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 5137 5138 slider.style.width = width + 'px'; 5139 slider.scrollLeft = 0; 5140 5141 while (width > widthMax && this.limitToScroll > 1) { 5142 this.limitToScroll--; 5143 itemLimit = this.items[this.limitToScroll - 1]; 5144 width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 5145 slider.style.width = width + 'px'; 5146 slider.scrollLeft = 0; 5147 } 5148 }); 5149 }); 5150 }, 5151 resizeEvent() { 5152 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
5152der => { 5153 slider.scrollLeft = 0; 5154 }) 5155 }, 5156 contentLoaded(eventData) { 5157 if (typeof window.configurableOptionsInitialized[this.productId] !== "undefined") { 5158 return; 5159 } 5160 5161 this.onGetCartData(eventData); 5162 window.configurableOptionsInitialized[this.productId] = true; 5163 } 5164 } 5165 ); 5166 } 5167</script>
5167 5168 5169 5170<div x-data="initConfigurableSwatchOptions_95()" 5171 x-init="findAllowedAttributeOptions(); initShowSwatchesIntersect();" 5172 @list-configurable-selection-changed.window="syncConfigurableSwatchOptions($event)" 5173 @list-swatches-reset-95.window="resetSwatches()" 5174 @private-content-loaded.window="contentLoaded($event.detail.data)" 5175 @resize.window="resizeEvent()" 5176> 5177 <div class="flex flex-col flex-nowrap gap-y-3"> 5178 5179 5180<div class="flex flex-col swatch-attribute"> 5181 <div class="flex mx-0 serrats-table-header uppercase border-b border-[#d9ddd7]"> 5182 <div class="w-1/3 px-0">Unidades caja</div> 5183 <div class="w-1/3 px-0 text-center">Precio unidad</div> 5184 <div class="w-1/3 px-0 text-center font-semibold"><span>Precio caja</span></div> 5185 </div> 5186 <template x-for="(item, index) in optionConfig.attributes[182].options" :key="item.id"> 5187 <div class="py-2"> 5188 <template x-if="optionIsEnabled(182, item.id)"> 5189 <label 5190 :for="'attribute-option-95-'+item.id" 5191 :mcclane-data="'product-configurable-custom-option-'+item.id" 5192 @touchend.passive="selectedValues[182] ? '' : changeOption(182, item.id)" 5193 class="flex items-center gap-2" 5194 > 5195 <input 5196 :id="'attribute-option-95-'+item.id" 5197 :value="item.id" 5198 name="super_attribute[182]" 5199 type="radio" 5200 class="border-0 focus:border-0 focus:ring-0 inline-block p-0 opacity-0 product-option-value-input absolute" 5201 style="z-index:-1" 5202 x-on:focus="focusLabel(item.id)" 5203 x-on:blur="blurLabel()" 5204 x-on:change="changeOption(182, $event.target.value)" 5205 @list-configurable-selection-changed.window="findAllowedAttributeOptions();" 5206 x-model="selectedValues[182]" 5207 :required="getAllowedAttributeOptions(182).filter(attributeOption => selectedValues[attributeOption]).length === 0" 5208 /> 5209 <div class="flex flex-grow items-center mx-0 cursor-pointer" x-data="{prices: optionConfig.optionPrices[item.availableProductsId[0]]}"> 5210 <div class="w-1/3"> 5211 <span class="inline-block lowercase text-sm serrats-custom-swatch-container flex items-center" :class="{'selected': selectedValues[182] === item.id}" x-text="getSwatchText(182, item.id) + ' uds.'"></span> 5212 </div> 5213 <div class="w-1/3 px-0 text-center"> 5214 <span class="inline-block font-medium text-sm line-through text-gray-medium" x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" x-text="hyva.formatPrice(prices.oldPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 5215 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 5216 </div> 5217 <div class="w-1/3 px-0 text-center"> 5218 <span x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" class="line-through text-gray-medium inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.oldPrice.amount, false, optionConfig.priceFormat)"></span> 5219 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount, false, optionConfig.priceFormat)"></span> 5220 </div> 5221 </div> 5222 </label> 5223 </template> 5224</div> 5225 </template> 5226</div> 5227 </div> 5228 <template x-if="isTooltipVisible()"> 5229 <div class="absolute" :style="getTooltipPosition()"> 5230 <div class="whitespace-nowrap shadow-lg absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-full z-10 p-1.5 -mt-1.5 text-xs text-white bg-black shadow-lg text-center"> 5231 <template x-if="isVisualSwatch(activeTooltipItem.attribute, activeTooltipItem.item)"> 5232 <div class="hidden border shadow-sm border-container" 5233 :style="getTooltipImageStyle(activeTooltipItem.attribute, activeTooltipItem.item)" 5234 ></div> 5235 </template>
5236 <span x-html="getTooltipLabel()"></span> 5237 </div> 5238 <svg xmlns="http://www.w3.org/2000/svg" 5239 viewBox="0 0 9 4.5" 5240 width="9" 5241 height="9" 5242 class="shadow-lg absolute left-1/2 transform -translate-x-1/2 -translate-y-full"> 5243 <path d="M-.025 0L4.5-4.525 9.025 0 4.5 4.525z"/> 5244 </svg> 5245 </div> 5246</template> 5247 </div> 5248 </div> 5249 5250 <div 5251 class="mt-auto" 5252 x-data="{showAddToCartButton: true, productId: '95' }" 5253 :class="{'': showAddToCartButton, '': !showAddToCartButton}" 5254 @list-configurable-selection-changed.window="if(productId === $event.detail.productId) showAddToCartButton = $event.detail.saleable"> 5255 <div x-cloak x-show="!showAddToCartButton"> 5256 <a class="btn bg-gray w-full shadow rounded" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-120g-25u"> 5257 <span>No está disponible</span> 5258 </a> 5259 </div> 5260 <button class="btn btn-dark-fill shadow w-full" 5261 x-show="showAddToCartButton" 5262 aria-label="Añadir al carrito"> 5263 <span class="">Añadir al carrito</span> 5264 </button> 5265 </div> 5266 </div> 5267 </div> 5268 </div> 5269 5270 </form> 5271 <form method="post" 5272 action="https://www.serrats.com/es_es/checkout/cart/add/uenc/%25uenc%25/product/97/" 5273 class="item product product-item product_addtocart_form bg-product-bg-color border-product-bg-border attribute_set_id_4 group/card flex flex-1 flex-col transition-shadow duration-300 ease-in shadow-[0px_0px_20px_rgba(0,0,0,0.05)] hover:shadow-[0px_0px_20px_rgba(0,0,0,0.1)]" 5274 x-data="{activeItem: false, activeDetails: false}" 5275 @mouseenter="activeItem = true" 5276 @mouseleave="activeItem = false" 5277 :class="{'bg-product-bg-hover-color border-product-bg-hover-border no-hover': activeItem }" 5278> 5279 <div x-data="{ formKey: '' }" x-init="formKey = hyva.getFormKey()"> 5280 <input name="form_key" type="hidden" :value="formKey"/> 5281</div> 5282 <input type="hidden" name="product" value="97"/> 5283 <div class="container-card flex flex-col h-full"> 5284 <div class="relative"> 5285 5286<div class="relative"> 5287<div class="grid grid-cols-2 gap-2 p-2 absolute right-0 left-0 bottom-0 top-0 pointer-events-none"> 5288 </div> 5289 5290<a class="relative product photo product-item-photo block overflow-hidden" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-virgen-ecologico-120g" 5291 mcclane-data="category-item"> 5292 <img x-data="showHoverImage()" 5293 @update-gallery-97.window="$root.src = $event.detail" 5294 class="h-full object-contain w-full md:group-hover/card:scale-[1.05] transition-all" 5295 @mouseover="onHover()" 5296 @mouseleave="onLeave()" 5297 loading="lazy" 5298 alt="Bonito del Norte en aceite de oliva virgen ECOLÓGICO. Lata 112g." 5299 title="Bonito del Norte en aceite de oliva virgen ECOLÓGICO. Lata 112g." 5300 src="https://www.serrats.com/media/catalog/product/m/i/miniatura_ol120_bn_eco.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 5301 src-hover="" 5302 src-leave="https://www.serrats.com/media/catalog/product/m/i/miniatura_ol120_bn_eco.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 5303 width="420" 5304 height="420" 5305/> 5306 5307 5308</a> 5309</div> 5310 </div> 5311 <div class="flex flex-col pt-3 p-2.5 lg:p-4 gap-2 h-full"> 5312 <div class="flex flex-col gap-2 lg:gap-3.5"> 5313 </div> 5314 <div class="flex justify-between"> 5315 <div class="flex"> 5316 5317<a class="product-item-link" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-virgen-ecologico-120g" 5318 > 5319 <span class="product-card-title md:product-card-title-desktop text-product-card-title line-clamp-3 min-h-[3.5em]"> 5320 Bonito del Norte en aceite de oliva virgen ECOLÃGICO. Lata 112g.</span> 5321</a> 5322 </div> 5323 <div class="flex"> 5324 </div> 5325 </div> 5326 <div class="flex flex-col gap-3 h-full"> 5327 5328 <span class="line-clamp-1 text-sm text-gray-dark">Lata</span> 5329 <div class=""> 5330
5330<script> 5331 function initConfigurableSwatchOptions_97() { 5332 const configurableOptionsComponent = initConfigurableOptions( 5333 '97', 5334 {"attributes":{"182":{"id":"182","code":"uds_caja","label":"Uds Caja","options":[{"id":"43","label":"12","products":["152"],"type":"0","value":"12"}],"position":"0"}},"template":"<%- data.price %>\u00a0\u20ac","currencyFormat":"%s\u00a0\u20ac","optionPrices":{"152":{"baseOldPrice":{"amount":41.818180818182},"oldPrice":{"amount":46},"basePrice":{"amount":41.818180818182},"finalPrice":{"amount":46},"tierPrices":[],"msrpPrice":{"amount":0}}},"priceFormat":{"pattern":"%s\u00a0\u20ac","precision":2,"requiredPrecision":2,"decimalSymbol":",","groupSymbol":".","groupLength":3,"integerRequired":false},"prices":{"baseOldPrice":{"amount":41.818180818182},"oldPrice":{"amount":46},"basePrice":{"amount":41.818180818182},"finalPrice":{"amount":46}},"productId":"97","chooseText":"Elegir una opci\u00f3n...","images":[],"index":{"152":{"182":"43"}},"salable":[],"canDisplayShowOutOfStockStatus":false,"saleable":{"152":true},"preselect_sku_child":"SERRATS_OL120_BNO_ECO_12","childProducts":{"SERRATS_OL120_BNO_ECO_12":"152"}} ); 5335 const swatchOptionsComponent = initSwatchOptions({"182":{"43":{"type":"0","value":"12","label":"12"},"additional_data":"{\"swatch_input_type\":\"text\",\"update_product_preview_image\":\"0\",\"use_product_image_for_swatch\":0}"}}); 5336 5337 if (typeof window.configurableOptionsInitialized === "undefined") { 5338 window.configurableOptionsInitialized = []; 5339 } 5340 5341 return Object.assign( 5342 configurableOptionsComponent, 5343 swatchOptionsComponent, 5344 { 5345 mediaCallback: "https\u003A\u002F\u002Fwww.serrats.com\u002Fes_es\u002Fswatches\u002Fajax\u002Fmedia\u002F", 5346 changeOption(optionId, value, skipUpdateGallery) { 5347 this.selectedValues[optionId] = value; 5348 this.findSimpleIndex(); 5349 this.findAllowedAttributeOptions(); 5350 this.updatePrices(); 5351 !skipUpdateGallery && this.updateGallery(); 5352 5353 window.dispatchEvent( 5354 new CustomEvent( 5355 'list-configurable-selection-changed', 5356 { 5357 detail: { 5358 productId: this.productId, 5359 optionId, 5360 value, 5361 productIndex: this.productIndex, 5362 selectedValues: this.selectedValues, 5363 saleable: this.optionConfig.saleable[this.productIndex] 5364 } 5365 } 5366 ) 5367 ); 5368 }, 5369 syncConfigurableSwatchOptions(event) { 5370 let product = event.detail; 5371 if (product.productId !== this.productId) return; 5372 if (product.productIndex !== this.productIndex) this.productIndex = product.productIndex 5373 if (product.selectedValues !== this.selectedValues) this.selectedValues = product.selectedValues 5374 }, 5375 resetSwatches() { 5376 let featured = []; 5377 this.selectedValues = featured; 5378 }, 5379 updateGallery() { 5380 let configSkipGalleryUpdate = 0; 5381 5382 if (!this.productIndex || configSkipGalleryUpdate ) { 5383 return; 5384 } 5385 5386 fetch(`${this.mediaCallback}?product_id=${this.productIndex}`, { 5387 method: 'GET', 5388 headers: { 5389 'Content-Type': 'application/json', 5390 'X-Requested-With': 'XMLHttpRequest' 5391 } 5392 } 5393 ).then(response => { 5394 return response.json() 5395 } 5396 ).then(data => { 5397 if (data.errors) { 5398 // non critical failure only console logged 5399 console.warn(data.errors); 5400 } else { 5401 const image = data && data.medium; 5402 5403 image && window.dispatchEvent( 5404 new CustomEvent( 5405 "update-gallery-97", 5406 {detail: image} 5407 ) 5408 ); 5409 } 5410 }).catch(error => { 5411 console.warn(error) 5412 }); 5413 }, 5414 preselectQuerystringItems() { 5415 // pre-select option like ?size=167 5416 const urlQueryParams = new URLSearchParams(window.location.search.replace('?', '')); 5417 Object.values(this.optionConfig.attributes).map(attribute => { 5418 // Don't update images on load, since PLPs already set the main image to the selected options 5419 const skipUpdateGallery = true; 5420 urlQueryParams.get(attribute.code) && 5421 this.changeOption(attribute.id, urlQueryParams.get(attribute.code), skipUpdateGallery); 5422 }); 5423 }, 5424 mouseDown: false, 5425 startX: 0, 5426 maxScroll: 0, 5427 scrollLeft: null, 5428 slider: null, 5429 attributeIdFeatured: null, 5430 items: [], 5431 limitToScroll: 0, 5432 limitToScrollMobile: 3, 5433 limitToScrollDesktop: 5, 5434 scrollEvents: { 5435 ['@mousedown'](e) { 5436 this.slider = e.target.closest('.snap'); 5437 if (!this.slider) { 5438 return; 5439 } 5440 this.maxScroll = this.slider.scrollWidth - this.slider.offsetWidth; 5441 this.startX = e.pageX - this.slider.offsetLeft; 5442 this.scrollLeft = this.slider.scrollLeft; 5443 this.mouseDown = true; 5444 }, 5445 ['@mouseout.self']() { 5446 this.mouseDown = false;
5447 }, 5448 ['@mouseup']() { 5449 this.mouseDown = false; 5450 }, 5451 ['@mousemove'](e) { 5452 e.preventDefault(); 5453 if (!this.mouseDown) { 5454 return; 5455 } 5456 const x = e.pageX - this.slider.offsetLeft; 5457 const scroll = x - this.startX; 5458 const scrollLeft = this.scrollLeft - scroll; 5459 5460 if (scrollLeft > this.maxScroll) { 5461 this.slider.scrollLeft = this.maxScroll; 5462 return 5463 } 5464 this.slider.scrollLeft = this.scrollLeft - scroll; 5465 }, 5466 ['@onselectstart']() { 5467 return false; 5468 }, 5469 ['@resize.window']() { 5470 this.initShowScrollSwatches(); 5471 }, 5472 ['@tabchange.window']() { 5473 this.initShowScrollSwatches(); 5474 } 5475 }, 5476 clickLeftEvent() { 5477 this.slider = this.$root.querySelector('.snap'); 5478 this.slider.scrollLeft -= this.slider.offsetWidth; 5479 }, 5480 clickRightEvent() { 5481 this.slider = this.$root.querySelector('.snap'); 5482 this.slider.scrollLeft += this.slider.offsetWidth; 5483 }, 5484 setLimitScroll() { 5485 this.limitToScroll = window.innerWidth > 767 ? this.limitToScrollDesktop : this.limitToScrollMobile; 5486 }, 5487 initShowScrollSwatches() { 5488 this.$nextTick(() => { 5489 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
5489der => { 5490 this.items = slider.querySelectorAll(':scope > div:not(.hidden)'); 5491 this.setLimitScroll(); 5492 5493 if (this.limitToScroll > this.items.length) { 5494 this.limitToScroll = this.items.length; 5495 } 5496 5497 let itemLimit = this.items[this.limitToScroll - 1]; 5498 let marginOffset = parseFloat(getComputedStyle(slider.parentElement).marginLeft) + parseFloat(getComputedStyle(slider.parentElement).marginRight); 5499 5500 let widthMax = this.$root.offsetWidth - marginOffset; 5501 let width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 5502 5503 slider.style.width = width + 'px'; 5504 slider.scrollLeft = 0; 5505 5506 while (width > widthMax && this.limitToScroll > 1) { 5507 this.limitToScroll--; 5508 itemLimit = this.items[this.limitToScroll - 1]; 5509 width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 5510 slider.style.width = width + 'px'; 5511 slider.scrollLeft = 0; 5512 } 5513 }); 5514 }); 5515 }, 5516 resizeEvent() { 5517 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
5517der => { 5518 slider.scrollLeft = 0; 5519 }) 5520 }, 5521 contentLoaded(eventData) { 5522 if (typeof window.configurableOptionsInitialized[this.productId] !== "undefined") { 5523 return; 5524 } 5525 5526 this.onGetCartData(eventData); 5527 window.configurableOptionsInitialized[this.productId] = true; 5528 } 5529 } 5530 ); 5531 } 5532</script>
5532 5533 5534 5535<div x-data="initConfigurableSwatchOptions_97()" 5536 x-init="findAllowedAttributeOptions(); initShowSwatchesIntersect();" 5537 @list-configurable-selection-changed.window="syncConfigurableSwatchOptions($event)" 5538 @list-swatches-reset-97.window="resetSwatches()" 5539 @private-content-loaded.window="contentLoaded($event.detail.data)" 5540 @resize.window="resizeEvent()" 5541> 5542 <div class="flex flex-col flex-nowrap gap-y-3"> 5543 5544 5545<div class="flex flex-col swatch-attribute"> 5546 <div class="flex mx-0 serrats-table-header uppercase border-b border-[#d9ddd7]"> 5547 <div class="w-1/3 px-0">Unidades caja</div> 5548 <div class="w-1/3 px-0 text-center">Precio unidad</div> 5549 <div class="w-1/3 px-0 text-center font-semibold"><span>Precio caja</span></div> 5550 </div> 5551 <template x-for="(item, index) in optionConfig.attributes[182].options" :key="item.id"> 5552 <div class="py-2"> 5553 <template x-if="optionIsEnabled(182, item.id)"> 5554 <label 5555 :for="'attribute-option-97-'+item.id" 5556 :mcclane-data="'product-configurable-custom-option-'+item.id" 5557 @touchend.passive="selectedValues[182] ? '' : changeOption(182, item.id)" 5558 class="flex items-center gap-2" 5559 > 5560 <input 5561 :id="'attribute-option-97-'+item.id" 5562 :value="item.id" 5563 name="super_attribute[182]" 5564 type="radio" 5565 class="border-0 focus:border-0 focus:ring-0 inline-block p-0 opacity-0 product-option-value-input absolute" 5566 style="z-index:-1" 5567 x-on:focus="focusLabel(item.id)" 5568 x-on:blur="blurLabel()" 5569 x-on:change="changeOption(182, $event.target.value)" 5570 @list-configurable-selection-changed.window="findAllowedAttributeOptions();" 5571 x-model="selectedValues[182]" 5572 :required="getAllowedAttributeOptions(182).filter(attributeOption => selectedValues[attributeOption]).length === 0" 5573 /> 5574 <div class="flex flex-grow items-center mx-0 cursor-pointer" x-data="{prices: optionConfig.optionPrices[item.availableProductsId[0]]}"> 5575 <div class="w-1/3"> 5576 <span class="inline-block lowercase text-sm serrats-custom-swatch-container flex items-center" :class="{'selected': selectedValues[182] === item.id}" x-text="getSwatchText(182, item.id) + ' uds.'"></span> 5577 </div> 5578 <div class="w-1/3 px-0 text-center"> 5579 <span class="inline-block font-medium text-sm line-through text-gray-medium" x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" x-text="hyva.formatPrice(prices.oldPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 5580 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 5581 </div> 5582 <div class="w-1/3 px-0 text-center"> 5583 <span x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" class="line-through text-gray-medium inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.oldPrice.amount, false, optionConfig.priceFormat)"></span> 5584 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount, false, optionConfig.priceFormat)"></span> 5585 </div> 5586 </div> 5587 </label> 5588 </template> 5589</div> 5590 </template> 5591</div> 5592 </div> 5593 <template x-if="isTooltipVisible()"> 5594 <div class="absolute" :style="getTooltipPosition()"> 5595 <div class="whitespace-nowrap shadow-lg absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-full z-10 p-1.5 -mt-1.5 text-xs text-white bg-black shadow-lg text-center"> 5596 <template x-if="isVisualSwatch(activeTooltipItem.attribute, activeTooltipItem.item)"> 5597 <div class="hidden border shadow-sm border-container" 5598 :style="getTooltipImageStyle(activeTooltipItem.attribute, activeTooltipItem.item)" 5599 ></div> 5600 </template>
5601 <span x-html="getTooltipLabel()"></span> 5602 </div> 5603 <svg xmlns="http://www.w3.org/2000/svg" 5604 viewBox="0 0 9 4.5" 5605 width="9" 5606 height="9" 5607 class="shadow-lg absolute left-1/2 transform -translate-x-1/2 -translate-y-full"> 5608 <path d="M-.025 0L4.5-4.525 9.025 0 4.5 4.525z"/> 5609 </svg> 5610 </div> 5611</template> 5612 </div> 5613 </div> 5614 5615 <div 5616 class="mt-auto" 5617 x-data="{showAddToCartButton: true, productId: '97' }" 5618 :class="{'': showAddToCartButton, '': !showAddToCartButton}" 5619 @list-configurable-selection-changed.window="if(productId === $event.detail.productId) showAddToCartButton = $event.detail.saleable"> 5620 <div x-cloak x-show="!showAddToCartButton"> 5621 <a class="btn bg-gray w-full shadow rounded" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-virgen-ecologico-120g"> 5622 <span>No está disponible</span> 5623 </a> 5624 </div> 5625 <button class="btn btn-dark-fill shadow w-full" 5626 x-show="showAddToCartButton" 5627 aria-label="Añadir al carrito"> 5628 <span class="">Añadir al carrito</span> 5629 </button> 5630 </div> 5631 </div> 5632 </div> 5633 </div> 5634 5635 </form> 5636 <div 5637 class="item product product-item product_addtocart_form bg-product-bg-color border-product-bg-border attribute_set_id_4 group/card flex flex-1 flex-col transition-shadow duration-300 ease-in shadow-[0px_0px_20px_rgba(0,0,0,0.05)] hover:shadow-[0px_0px_20px_rgba(0,0,0,0.1)]" 5638 x-data="{activeItem: false, activeDetails: false}" 5639 @mouseenter="activeItem = true" 5640 @mouseleave="activeItem = false" 5641 :class="{'bg-product-bg-hover-color border-product-bg-hover-border no-hover': activeItem }" 5642> 5643 <div class="container-card flex flex-col h-full"> 5644 <div class="relative"> 5645 5646<div class="relative"> 5647<div class="grid grid-cols-2 gap-2 p-2 absolute right-0 left-0 bottom-0 top-0 pointer-events-none"> 5648 </div> 5649 5650<a class="relative product photo product-item-photo block overflow-hidden" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-bajo-en-sal-lata-120g" 5651 mcclane-data="category-item"> 5652 <img x-data="showHoverImage()" 5653 @update-gallery-96.window="$root.src = $event.detail" 5654 class="h-full object-contain w-full md:group-hover/card:scale-[1.05] transition-all" 5655 @mouseover="onHover()" 5656 @mouseleave="onLeave()" 5657 loading="lazy" 5658 alt="Bonito del Norte en aceite de oliva BAJO EN SAL. Lata 112g." 5659 title="Bonito del Norte en aceite de oliva BAJO EN SAL. Lata 112g." 5660 src="https://www.serrats.com/media/catalog/product/m/i/miniatura_ol120_bnbajo_2-2.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 5661 src-hover="" 5662 src-leave="https://www.serrats.com/media/catalog/product/m/i/miniatura_ol120_bnbajo_2-2.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 5663 width="420" 5664 height="420" 5665/> 5666 5667 5668</a> 5669</div> 5670 </div> 5671 <div class="flex flex-col pt-3 p-2.5 lg:p-4 gap-2 h-full"> 5672 <div class="flex flex-col gap-2 lg:gap-3.5"> 5673 </div> 5674 <div class="flex justify-between"> 5675 <div class="flex"> 5676 5677<a class="product-item-link" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-bajo-en-sal-lata-120g" 5678 > 5679 <span class="product-card-title md:product-card-title-desktop text-product-card-title line-clamp-3 min-h-[3.5em]"> 5680 Bonito del Norte en aceite de oliva BAJO EN SAL. Lata 112g.</span> 5681</a> 5682 </div> 5683 <div class="flex"> 5684 </div> 5685 </div> 5686 <div class="flex flex-col gap-3 h-full"> 5687 5688 <span class="line-clamp-1 text-sm text-gray-dark">Lata</span> 5689 5690 <div 5691 class="mt-auto"
5692 x-data="{showAddToCartButton: false, productId: '96' }" 5693 :class="{'': showAddToCartButton, '': !showAddToCartButton}" 5694 @list-configurable-selection-changed.window="if(productId === $event.detail.productId) showAddToCartButton = $event.detail.saleable"> 5695 <div x-cloak x-show="!showAddToCartButton"> 5696 <a class="btn bg-gray w-full shadow rounded" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-bajo-en-sal-lata-120g"> 5697 <span>No está disponible</span> 5698 </a> 5699 </div> 5700 <button class="btn btn-dark-fill shadow w-full" 5701 x-show="showAddToCartButton" 5702 aria-label="Añadir al carrito"> 5703 <span class="">Añadir al carrito</span> 5704 </button> 5705 </div> 5706 </div> 5707 </div> 5708 </div> 5709 5710 </div> 5711 <form method="post" 5712 action="https://www.serrats.com/es_es/checkout/cart/add/uenc/%25uenc%25/product/94/" 5713 class="item product product-item product_addtocart_form bg-product-bg-color border-product-bg-border attribute_set_id_4 group/card flex flex-1 flex-col transition-shadow duration-300 ease-in shadow-[0px_0px_20px_rgba(0,0,0,0.05)] hover:shadow-[0px_0px_20px_rgba(0,0,0,0.1)]" 5714 x-data="{activeItem: false, activeDetails: false}" 5715 @mouseenter="activeItem = true" 5716 @mouseleave="activeItem = false" 5717 :class="{'bg-product-bg-hover-color border-product-bg-hover-border no-hover': activeItem }" 5718> 5719 <div x-data="{ formKey: '' }" x-init="formKey = hyva.getFormKey()"> 5720 <input name="form_key" type="hidden" :value="formKey"/> 5721</div> 5722 <input type="hidden" name="product" value="94"/> 5723 <div class="container-card flex flex-col h-full"> 5724 <div class="relative"> 5725 5726<div class="relative"> 5727<div class="grid grid-cols-2 gap-2 p-2 absolute right-0 left-0 bottom-0 top-0 pointer-events-none"> 5728 </div> 5729 5730<a class="relative product photo product-item-photo block overflow-hidden" href="https://www.serrats.com/es_es/bonito-del-norte-escabeche-lata-120g" 5731 mcclane-data="category-item"> 5732 <img x-data="showHoverImage()" 5733 @update-gallery-94.window="$root.src = $event.detail" 5734 class="h-full object-contain w-full md:group-hover/card:scale-[1.05] transition-all" 5735 @mouseover="onHover()" 5736 @mouseleave="onLeave()" 5737 loading="lazy" 5738 alt="Bonito del Norte en Escabeche. Lata 112g." 5739 title="Bonito del Norte en Escabeche. Lata 112g." 5740 src="https://www.serrats.com/media/catalog/product/m/i/miniatura_ol120_bne.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 5741 src-hover="" 5742 src-leave="https://www.serrats.com/media/catalog/product/m/i/miniatura_ol120_bne.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 5743 width="420" 5744 height="420" 5745/> 5746 5747 5748</a> 5749</div> 5750 </div> 5751 <div class="flex flex-col pt-3 p-2.5 lg:p-4 gap-2 h-full"> 5752 <div class="flex flex-col gap-2 lg:gap-3.5"> 5753 </div> 5754 <div class="flex justify-between"> 5755 <div class="flex"> 5756 5757<a class="product-item-link" href="https://www.serrats.com/es_es/bonito-del-norte-escabeche-lata-120g" 5758 > 5759 <span class="product-card-title md:product-card-title-desktop text-product-card-title line-clamp-3 min-h-[3.5em]"> 5760 Bonito del Norte en Escabeche. Lata 112g.</span> 5761</a> 5762 </div> 5763 <div class="flex"> 5764 </div> 5765 </div> 5766 <div class="flex flex-col gap-3 h-full"> 5767 5768 <span class="line-clamp-1 text-sm text-gray-dark">Lata</span> 5769 <div class=""> 5770
5770<script> 5771 function initConfigurableSwatchOptions_94() { 5772 const configurableOptionsComponent = initConfigurableOptions( 5773 '94', 5774 {"attributes":{"182":{"id":"182","code":"uds_caja","label":"Uds Caja","options":[{"id":"43","label":"12","products":["151"],"type":"0","value":"12"}],"position":"0"}},"template":"<%- data.price %>\u00a0\u20ac","currencyFormat":"%s\u00a0\u20ac","optionPrices":{"151":{"baseOldPrice":{"amount":39.999999},"oldPrice":{"amount":44},"basePrice":{"amount":39.999999},"finalPrice":{"amount":44},"tierPrices":[],"msrpPrice":{"amount":0}}},"priceFormat":{"pattern":"%s\u00a0\u20ac","precision":2,"requiredPrecision":2,"decimalSymbol":",","groupSymbol":".","groupLength":3,"integerRequired":false},"prices":{"baseOldPrice":{"amount":39.999999},"oldPrice":{"amount":44},"basePrice":{"amount":39.999999},"finalPrice":{"amount":44}},"productId":"94","chooseText":"Elegir una opci\u00f3n...","images":[],"index":{"151":{"182":"43"}},"salable":[],"canDisplayShowOutOfStockStatus":false,"preSelectedGallery":[],"saleable":{"151":true},"preselect_sku_child":"SERRATS_OL120_BNE_12","childProducts":{"SERRATS_OL120_BNE_12":"151"}} ); 5775 const swatchOptionsComponent = initSwatchOptions({"182":{"43":{"type":"0","value":"12","label":"12"},"additional_data":"{\"swatch_input_type\":\"text\",\"update_product_preview_image\":\"0\",\"use_product_image_for_swatch\":0}"}}); 5776 5777 if (typeof window.configurableOptionsInitialized === "undefined") { 5778 window.configurableOptionsInitialized = []; 5779 } 5780 5781 return Object.assign( 5782 configurableOptionsComponent, 5783 swatchOptionsComponent, 5784 { 5785 mediaCallback: "https\u003A\u002F\u002Fwww.serrats.com\u002Fes_es\u002Fswatches\u002Fajax\u002Fmedia\u002F", 5786 changeOption(optionId, value, skipUpdateGallery) { 5787 this.selectedValues[optionId] = value; 5788 this.findSimpleIndex(); 5789 this.findAllowedAttributeOptions(); 5790 this.updatePrices(); 5791 !skipUpdateGallery && this.updateGallery(); 5792 5793 window.dispatchEvent( 5794 new CustomEvent( 5795 'list-configurable-selection-changed', 5796 { 5797 detail: { 5798 productId: this.productId, 5799 optionId, 5800 value, 5801 productIndex: this.productIndex, 5802 selectedValues: this.selectedValues, 5803 saleable: this.optionConfig.saleable[this.productIndex] 5804 } 5805 } 5806 ) 5807 ); 5808 }, 5809 syncConfigurableSwatchOptions(event) { 5810 let product = event.detail; 5811 if (product.productId !== this.productId) return; 5812 if (product.productIndex !== this.productIndex) this.productIndex = product.productIndex 5813 if (product.selectedValues !== this.selectedValues) this.selectedValues = product.selectedValues 5814 }, 5815 resetSwatches() { 5816 let featured = []; 5817 this.selectedValues = featured; 5818 }, 5819 updateGallery() { 5820 let configSkipGalleryUpdate = 0; 5821 5822 if (!this.productIndex || configSkipGalleryUpdate ) { 5823 return; 5824 } 5825 5826 fetch(`${this.mediaCallback}?product_id=${this.productIndex}`, { 5827 method: 'GET', 5828 headers: { 5829 'Content-Type': 'application/json', 5830 'X-Requested-With': 'XMLHttpRequest' 5831 } 5832 } 5833 ).then(response => { 5834 return response.json() 5835 } 5836 ).then(data => { 5837 if (data.errors) { 5838 // non critical failure only console logged 5839 console.warn(data.errors); 5840 } else { 5841 const image = data && data.medium; 5842 5843 image && window.dispatchEvent( 5844 new CustomEvent( 5845 "update-gallery-94", 5846 {detail: image} 5847 ) 5848 ); 5849 } 5850 }).catch(error => { 5851 console.warn(error) 5852 }); 5853 }, 5854 preselectQuerystringItems() { 5855 // pre-select option like ?size=167 5856 const urlQueryParams = new URLSearchParams(window.location.search.replace('?', '')); 5857 Object.values(this.optionConfig.attributes).map(attribute => { 5858 // Don't update images on load, since PLPs already set the main image to the selected options 5859 const skipUpdateGallery = true; 5860 urlQueryParams.get(attribute.code) && 5861 this.changeOption(attribute.id, urlQueryParams.get(attribute.code), skipUpdateGallery); 5862 }); 5863 }, 5864 mouseDown: false, 5865 startX: 0, 5866 maxScroll: 0, 5867 scrollLeft: null, 5868 slider: null, 5869 attributeIdFeatured: null, 5870 items: [], 5871 limitToScroll: 0, 5872 limitToScrollMobile: 3, 5873 limitToScrollDesktop: 5, 5874 scrollEvents: { 5875 ['@mousedown'](e) { 5876 this.slider = e.target.closest('.snap'); 5877 if (!this.slider) { 5878 return; 5879 } 5880 this.maxScroll = this.slider.scrollWidth - this.slider.offsetWidth; 5881 this.startX = e.pageX - this.slider.offsetLeft; 5882 this.scrollLeft = this.slider.scrollLeft; 5883 this.mouseDown = true; 5884 }, 5885 ['@mouseout.self']() { 5886 this.mouseDown = false;
5887 }, 5888 ['@mouseup']() { 5889 this.mouseDown = false; 5890 }, 5891 ['@mousemove'](e) { 5892 e.preventDefault(); 5893 if (!this.mouseDown) { 5894 return; 5895 } 5896 const x = e.pageX - this.slider.offsetLeft; 5897 const scroll = x - this.startX; 5898 const scrollLeft = this.scrollLeft - scroll; 5899 5900 if (scrollLeft > this.maxScroll) { 5901 this.slider.scrollLeft = this.maxScroll; 5902 return 5903 } 5904 this.slider.scrollLeft = this.scrollLeft - scroll; 5905 }, 5906 ['@onselectstart']() { 5907 return false; 5908 }, 5909 ['@resize.window']() { 5910 this.initShowScrollSwatches(); 5911 }, 5912 ['@tabchange.window']() { 5913 this.initShowScrollSwatches(); 5914 } 5915 }, 5916 clickLeftEvent() { 5917 this.slider = this.$root.querySelector('.snap'); 5918 this.slider.scrollLeft -= this.slider.offsetWidth; 5919 }, 5920 clickRightEvent() { 5921 this.slider = this.$root.querySelector('.snap'); 5922 this.slider.scrollLeft += this.slider.offsetWidth; 5923 }, 5924 setLimitScroll() { 5925 this.limitToScroll = window.innerWidth > 767 ? this.limitToScrollDesktop : this.limitToScrollMobile; 5926 }, 5927 initShowScrollSwatches() { 5928 this.$nextTick(() => { 5929 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
5929der => { 5930 this.items = slider.querySelectorAll(':scope > div:not(.hidden)'); 5931 this.setLimitScroll(); 5932 5933 if (this.limitToScroll > this.items.length) { 5934 this.limitToScroll = this.items.length; 5935 } 5936 5937 let itemLimit = this.items[this.limitToScroll - 1]; 5938 let marginOffset = parseFloat(getComputedStyle(slider.parentElement).marginLeft) + parseFloat(getComputedStyle(slider.parentElement).marginRight); 5939 5940 let widthMax = this.$root.offsetWidth - marginOffset; 5941 let width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 5942 5943 slider.style.width = width + 'px'; 5944 slider.scrollLeft = 0; 5945 5946 while (width > widthMax && this.limitToScroll > 1) { 5947 this.limitToScroll--; 5948 itemLimit = this.items[this.limitToScroll - 1]; 5949 width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 5950 slider.style.width = width + 'px'; 5951 slider.scrollLeft = 0; 5952 } 5953 }); 5954 }); 5955 }, 5956 resizeEvent() { 5957 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
5957der => { 5958 slider.scrollLeft = 0; 5959 }) 5960 }, 5961 contentLoaded(eventData) { 5962 if (typeof window.configurableOptionsInitialized[this.productId] !== "undefined") { 5963 return; 5964 } 5965 5966 this.onGetCartData(eventData); 5967 window.configurableOptionsInitialized[this.productId] = true; 5968 } 5969 } 5970 ); 5971 } 5972</script>
5972 5973 5974 5975<div x-data="initConfigurableSwatchOptions_94()" 5976 x-init="findAllowedAttributeOptions(); initShowSwatchesIntersect();" 5977 @list-configurable-selection-changed.window="syncConfigurableSwatchOptions($event)" 5978 @list-swatches-reset-94.window="resetSwatches()" 5979 @private-content-loaded.window="contentLoaded($event.detail.data)" 5980 @resize.window="resizeEvent()" 5981> 5982 <div class="flex flex-col flex-nowrap gap-y-3"> 5983 5984 5985<div class="flex flex-col swatch-attribute"> 5986 <div class="flex mx-0 serrats-table-header uppercase border-b border-[#d9ddd7]"> 5987 <div class="w-1/3 px-0">Unidades caja</div> 5988 <div class="w-1/3 px-0 text-center">Precio unidad</div> 5989 <div class="w-1/3 px-0 text-center font-semibold"><span>Precio caja</span></div> 5990 </div> 5991 <template x-for="(item, index) in optionConfig.attributes[182].options" :key="item.id"> 5992 <div class="py-2"> 5993 <template x-if="optionIsEnabled(182, item.id)"> 5994 <label 5995 :for="'attribute-option-94-'+item.id" 5996 :mcclane-data="'product-configurable-custom-option-'+item.id" 5997 @touchend.passive="selectedValues[182] ? '' : changeOption(182, item.id)" 5998 class="flex items-center gap-2" 5999 > 6000 <input 6001 :id="'attribute-option-94-'+item.id" 6002 :value="item.id" 6003 name="super_attribute[182]" 6004 type="radio" 6005 class="border-0 focus:border-0 focus:ring-0 inline-block p-0 opacity-0 product-option-value-input absolute" 6006 style="z-index:-1" 6007 x-on:focus="focusLabel(item.id)" 6008 x-on:blur="blurLabel()" 6009 x-on:change="changeOption(182, $event.target.value)" 6010 @list-configurable-selection-changed.window="findAllowedAttributeOptions();" 6011 x-model="selectedValues[182]" 6012 :required="getAllowedAttributeOptions(182).filter(attributeOption => selectedValues[attributeOption]).length === 0" 6013 /> 6014 <div class="flex flex-grow items-center mx-0 cursor-pointer" x-data="{prices: optionConfig.optionPrices[item.availableProductsId[0]]}"> 6015 <div class="w-1/3"> 6016 <span class="inline-block lowercase text-sm serrats-custom-swatch-container flex items-center" :class="{'selected': selectedValues[182] === item.id}" x-text="getSwatchText(182, item.id) + ' uds.'"></span> 6017 </div> 6018 <div class="w-1/3 px-0 text-center"> 6019 <span class="inline-block font-medium text-sm line-through text-gray-medium" x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" x-text="hyva.formatPrice(prices.oldPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 6020 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 6021 </div> 6022 <div class="w-1/3 px-0 text-center"> 6023 <span x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" class="line-through text-gray-medium inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.oldPrice.amount, false, optionConfig.priceFormat)"></span> 6024 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount, false, optionConfig.priceFormat)"></span> 6025 </div> 6026 </div> 6027 </label> 6028 </template> 6029</div> 6030 </template> 6031</div> 6032 </div> 6033 <template x-if="isTooltipVisible()"> 6034 <div class="absolute" :style="getTooltipPosition()"> 6035 <div class="whitespace-nowrap shadow-lg absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-full z-10 p-1.5 -mt-1.5 text-xs text-white bg-black shadow-lg text-center"> 6036 <template x-if="isVisualSwatch(activeTooltipItem.attribute, activeTooltipItem.item)"> 6037 <div class="hidden border shadow-sm border-container" 6038 :style="getTooltipImageStyle(activeTooltipItem.attribute, activeTooltipItem.item)" 6039 ></div> 6040 </template>
6041 <span x-html="getTooltipLabel()"></span> 6042 </div> 6043 <svg xmlns="http://www.w3.org/2000/svg" 6044 viewBox="0 0 9 4.5" 6045 width="9" 6046 height="9" 6047 class="shadow-lg absolute left-1/2 transform -translate-x-1/2 -translate-y-full"> 6048 <path d="M-.025 0L4.5-4.525 9.025 0 4.5 4.525z"/> 6049 </svg> 6050 </div> 6051</template> 6052 </div> 6053 </div> 6054 6055 <div 6056 class="mt-auto" 6057 x-data="{showAddToCartButton: true, productId: '94' }" 6058 :class="{'': showAddToCartButton, '': !showAddToCartButton}" 6059 @list-configurable-selection-changed.window="if(productId === $event.detail.productId) showAddToCartButton = $event.detail.saleable"> 6060 <div x-cloak x-show="!showAddToCartButton"> 6061 <a class="btn bg-gray w-full shadow rounded" href="https://www.serrats.com/es_es/bonito-del-norte-escabeche-lata-120g"> 6062 <span>No está disponible</span> 6063 </a> 6064 </div> 6065 <button class="btn btn-dark-fill shadow w-full" 6066 x-show="showAddToCartButton" 6067 aria-label="Añadir al carrito"> 6068 <span class="">Añadir al carrito</span> 6069 </button> 6070 </div> 6071 </div> 6072 </div> 6073 </div> 6074 6075 </form> 6076 <form method="post" 6077 action="https://www.serrats.com/es_es/checkout/cart/add/uenc/%25uenc%25/product/98/" 6078 class="item product product-item product_addtocart_form bg-product-bg-color border-product-bg-border attribute_set_id_4 group/card flex flex-1 flex-col transition-shadow duration-300 ease-in shadow-[0px_0px_20px_rgba(0,0,0,0.05)] hover:shadow-[0px_0px_20px_rgba(0,0,0,0.1)]" 6079 x-data="{activeItem: false, activeDetails: false}" 6080 @mouseenter="activeItem = true" 6081 @mouseleave="activeItem = false" 6082 :class="{'bg-product-bg-hover-color border-product-bg-hover-border no-hover': activeItem }" 6083> 6084 <div x-data="{ formKey: '' }" x-init="formKey = hyva.getFormKey()"> 6085 <input name="form_key" type="hidden" :value="formKey"/> 6086</div> 6087 <input type="hidden" name="product" value="98"/> 6088 <div class="container-card flex flex-col h-full"> 6089 <div class="relative"> 6090 6091<div class="relative"> 6092<div class="grid grid-cols-2 gap-2 p-2 absolute right-0 left-0 bottom-0 top-0 pointer-events-none"> 6093 </div> 6094 6095<a class="relative product photo product-item-photo block overflow-hidden" href="https://www.serrats.com/es_es/bonito-del-norte-salsa-lata-120g" 6096 mcclane-data="category-item"> 6097 <img x-data="showHoverImage()" 6098 @update-gallery-98.window="$root.src = $event.detail" 6099 class="h-full object-contain w-full md:group-hover/card:scale-[1.05] transition-all" 6100 @mouseover="onHover()" 6101 @mouseleave="onLeave()" 6102 loading="lazy" 6103 alt="Bonito del Norte en Salsa. Lata 112g." 6104 title="Bonito del Norte en Salsa. Lata 112g." 6105 src="https://www.serrats.com/media/catalog/product/m/i/miniatura_ol120_bnsalsa.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 6106 src-hover="" 6107 src-leave="https://www.serrats.com/media/catalog/product/m/i/miniatura_ol120_bnsalsa.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 6108 width="420" 6109 height="420" 6110/> 6111 6112 6113</a> 6114</div> 6115 </div> 6116 <div class="flex flex-col pt-3 p-2.5 lg:p-4 gap-2 h-full"> 6117 <div class="flex flex-col gap-2 lg:gap-3.5"> 6118 </div> 6119 <div class="flex justify-between"> 6120 <div class="flex"> 6121 6122<a class="product-item-link" href="https://www.serrats.com/es_es/bonito-del-norte-salsa-lata-120g" 6123 > 6124 <span class="product-card-title md:product-card-title-desktop text-product-card-title line-clamp-3 min-h-[3.5em]">
6125 Bonito del Norte en Salsa. Lata 112g.</span> 6126</a> 6127 </div> 6128 <div class="flex"> 6129 </div> 6130 </div> 6131 <div class="flex flex-col gap-3 h-full"> 6132 6133 <span class="line-clamp-1 text-sm text-gray-dark">Lata</span> 6134 <div class=""> 6135
6135<script> 6136 function initConfigurableSwatchOptions_98() { 6137 const configurableOptionsComponent = initConfigurableOptions( 6138 '98', 6139 {"attributes":{"182":{"id":"182","code":"uds_caja","label":"Uds Caja","options":[{"id":"43","label":"12","products":["153"],"type":"0","value":"12"}],"position":"0"}},"template":"<%- data.price %>\u00a0\u20ac","currencyFormat":"%s\u00a0\u20ac","optionPrices":{"153":{"baseOldPrice":{"amount":39.999999},"oldPrice":{"amount":44},"basePrice":{"amount":39.999999},"finalPrice":{"amount":44},"tierPrices":[],"msrpPrice":{"amount":0}}},"priceFormat":{"pattern":"%s\u00a0\u20ac","precision":2,"requiredPrecision":2,"decimalSymbol":",","groupSymbol":".","groupLength":3,"integerRequired":false},"prices":{"baseOldPrice":{"amount":39.999999},"oldPrice":{"amount":44},"basePrice":{"amount":39.999999},"finalPrice":{"amount":44}},"productId":"98","chooseText":"Elegir una opci\u00f3n...","images":[],"index":{"153":{"182":"43"}},"salable":[],"canDisplayShowOutOfStockStatus":false,"saleable":{"153":true},"preselect_sku_child":"SERRATS_OL120_BNS_12","childProducts":{"SERRATS_OL120_BNS_12":"153"}} ); 6140 const swatchOptionsComponent = initSwatchOptions({"182":{"43":{"type":"0","value":"12","label":"12"},"additional_data":"{\"swatch_input_type\":\"text\",\"update_product_preview_image\":\"0\",\"use_product_image_for_swatch\":0}"}}); 6141 6142 if (typeof window.configurableOptionsInitialized === "undefined") { 6143 window.configurableOptionsInitialized = []; 6144 } 6145 6146 return Object.assign( 6147 configurableOptionsComponent, 6148 swatchOptionsComponent, 6149 { 6150 mediaCallback: "https\u003A\u002F\u002Fwww.serrats.com\u002Fes_es\u002Fswatches\u002Fajax\u002Fmedia\u002F", 6151 changeOption(optionId, value, skipUpdateGallery) { 6152 this.selectedValues[optionId] = value; 6153 this.findSimpleIndex(); 6154 this.findAllowedAttributeOptions(); 6155 this.updatePrices(); 6156 !skipUpdateGallery && this.updateGallery(); 6157 6158 window.dispatchEvent( 6159 new CustomEvent( 6160 'list-configurable-selection-changed', 6161 { 6162 detail: { 6163 productId: this.productId, 6164 optionId, 6165 value, 6166 productIndex: this.productIndex, 6167 selectedValues: this.selectedValues, 6168 saleable: this.optionConfig.saleable[this.productIndex] 6169 } 6170 } 6171 ) 6172 ); 6173 }, 6174 syncConfigurableSwatchOptions(event) { 6175 let product = event.detail; 6176 if (product.productId !== this.productId) return; 6177 if (product.productIndex !== this.productIndex) this.productIndex = product.productIndex 6178 if (product.selectedValues !== this.selectedValues) this.selectedValues = product.selectedValues 6179 }, 6180 resetSwatches() { 6181 let featured = []; 6182 this.selectedValues = featured; 6183 }, 6184 updateGallery() { 6185 let configSkipGalleryUpdate = 0; 6186 6187 if (!this.productIndex || configSkipGalleryUpdate ) { 6188 return; 6189 } 6190 6191 fetch(`${this.mediaCallback}?product_id=${this.productIndex}`, { 6192 method: 'GET', 6193 headers: { 6194 'Content-Type': 'application/json', 6195 'X-Requested-With': 'XMLHttpRequest' 6196 } 6197 } 6198 ).then(response => { 6199 return response.json() 6200 } 6201 ).then(data => { 6202 if (data.errors) { 6203 // non critical failure only console logged 6204 console.warn(data.errors); 6205 } else { 6206 const image = data && data.medium; 6207 6208 image && window.dispatchEvent( 6209 new CustomEvent( 6210 "update-gallery-98", 6211 {detail: image} 6212 ) 6213 ); 6214 } 6215 }).catch(error => { 6216 console.warn(error) 6217 }); 6218 }, 6219 preselectQuerystringItems() { 6220 // pre-select option like ?size=167 6221 const urlQueryParams = new URLSearchParams(window.location.search.replace('?', '')); 6222 Object.values(this.optionConfig.attributes).map(attribute => { 6223 // Don't update images on load, since PLPs already set the main image to the selected options 6224 const skipUpdateGallery = true; 6225 urlQueryParams.get(attribute.code) && 6226 this.changeOption(attribute.id, urlQueryParams.get(attribute.code), skipUpdateGallery); 6227 }); 6228 }, 6229 mouseDown: false, 6230 startX: 0, 6231 maxScroll: 0, 6232 scrollLeft: null, 6233 slider: null, 6234 attributeIdFeatured: null, 6235 items: [], 6236 limitToScroll: 0, 6237 limitToScrollMobile: 3, 6238 limitToScrollDesktop: 5, 6239 scrollEvents: { 6240 ['@mousedown'](e) { 6241 this.slider = e.target.closest('.snap'); 6242 if (!this.slider) { 6243 return; 6244 } 6245 this.maxScroll = this.slider.scrollWidth - this.slider.offsetWidth; 6246 this.startX = e.pageX - this.slider.offsetLeft; 6247 this.scrollLeft = this.slider.scrollLeft; 6248 this.mouseDown = true; 6249 }, 6250 ['@mouseout.self']() { 6251 this.mouseDown = false;
6252 }, 6253 ['@mouseup']() { 6254 this.mouseDown = false; 6255 }, 6256 ['@mousemove'](e) { 6257 e.preventDefault(); 6258 if (!this.mouseDown) { 6259 return; 6260 } 6261 const x = e.pageX - this.slider.offsetLeft; 6262 const scroll = x - this.startX; 6263 const scrollLeft = this.scrollLeft - scroll; 6264 6265 if (scrollLeft > this.maxScroll) { 6266 this.slider.scrollLeft = this.maxScroll; 6267 return 6268 } 6269 this.slider.scrollLeft = this.scrollLeft - scroll; 6270 }, 6271 ['@onselectstart']() { 6272 return false; 6273 }, 6274 ['@resize.window']() { 6275 this.initShowScrollSwatches(); 6276 }, 6277 ['@tabchange.window']() { 6278 this.initShowScrollSwatches(); 6279 } 6280 }, 6281 clickLeftEvent() { 6282 this.slider = this.$root.querySelector('.snap'); 6283 this.slider.scrollLeft -= this.slider.offsetWidth; 6284 }, 6285 clickRightEvent() { 6286 this.slider = this.$root.querySelector('.snap'); 6287 this.slider.scrollLeft += this.slider.offsetWidth; 6288 }, 6289 setLimitScroll() { 6290 this.limitToScroll = window.innerWidth > 767 ? this.limitToScrollDesktop : this.limitToScrollMobile; 6291 }, 6292 initShowScrollSwatches() { 6293 this.$nextTick(() => { 6294 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
6294der => { 6295 this.items = slider.querySelectorAll(':scope > div:not(.hidden)'); 6296 this.setLimitScroll(); 6297 6298 if (this.limitToScroll > this.items.length) { 6299 this.limitToScroll = this.items.length; 6300 } 6301 6302 let itemLimit = this.items[this.limitToScroll - 1]; 6303 let marginOffset = parseFloat(getComputedStyle(slider.parentElement).marginLeft) + parseFloat(getComputedStyle(slider.parentElement).marginRight); 6304 6305 let widthMax = this.$root.offsetWidth - marginOffset; 6306 let width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 6307 6308 slider.style.width = width + 'px'; 6309 slider.scrollLeft = 0; 6310 6311 while (width > widthMax && this.limitToScroll > 1) { 6312 this.limitToScroll--; 6313 itemLimit = this.items[this.limitToScroll - 1]; 6314 width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 6315 slider.style.width = width + 'px'; 6316 slider.scrollLeft = 0; 6317 } 6318 }); 6319 }); 6320 }, 6321 resizeEvent() { 6322 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
6322der => { 6323 slider.scrollLeft = 0; 6324 }) 6325 }, 6326 contentLoaded(eventData) { 6327 if (typeof window.configurableOptionsInitialized[this.productId] !== "undefined") { 6328 return; 6329 } 6330 6331 this.onGetCartData(eventData); 6332 window.configurableOptionsInitialized[this.productId] = true; 6333 } 6334 } 6335 ); 6336 } 6337</script>
6337 6338 6339 6340<div x-data="initConfigurableSwatchOptions_98()" 6341 x-init="findAllowedAttributeOptions(); initShowSwatchesIntersect();" 6342 @list-configurable-selection-changed.window="syncConfigurableSwatchOptions($event)" 6343 @list-swatches-reset-98.window="resetSwatches()" 6344 @private-content-loaded.window="contentLoaded($event.detail.data)" 6345 @resize.window="resizeEvent()" 6346> 6347 <div class="flex flex-col flex-nowrap gap-y-3"> 6348 6349 6350<div class="flex flex-col swatch-attribute"> 6351 <div class="flex mx-0 serrats-table-header uppercase border-b border-[#d9ddd7]"> 6352 <div class="w-1/3 px-0">Unidades caja</div> 6353 <div class="w-1/3 px-0 text-center">Precio unidad</div> 6354 <div class="w-1/3 px-0 text-center font-semibold"><span>Precio caja</span></div> 6355 </div> 6356 <template x-for="(item, index) in optionConfig.attributes[182].options" :key="item.id"> 6357 <div class="py-2"> 6358 <template x-if="optionIsEnabled(182, item.id)"> 6359 <label 6360 :for="'attribute-option-98-'+item.id" 6361 :mcclane-data="'product-configurable-custom-option-'+item.id" 6362 @touchend.passive="selectedValues[182] ? '' : changeOption(182, item.id)" 6363 class="flex items-center gap-2" 6364 > 6365 <input 6366 :id="'attribute-option-98-'+item.id" 6367 :value="item.id" 6368 name="super_attribute[182]" 6369 type="radio" 6370 class="border-0 focus:border-0 focus:ring-0 inline-block p-0 opacity-0 product-option-value-input absolute" 6371 style="z-index:-1" 6372 x-on:focus="focusLabel(item.id)" 6373 x-on:blur="blurLabel()" 6374 x-on:change="changeOption(182, $event.target.value)" 6375 @list-configurable-selection-changed.window="findAllowedAttributeOptions();" 6376 x-model="selectedValues[182]" 6377 :required="getAllowedAttributeOptions(182).filter(attributeOption => selectedValues[attributeOption]).length === 0" 6378 /> 6379 <div class="flex flex-grow items-center mx-0 cursor-pointer" x-data="{prices: optionConfig.optionPrices[item.availableProductsId[0]]}"> 6380 <div class="w-1/3"> 6381 <span class="inline-block lowercase text-sm serrats-custom-swatch-container flex items-center" :class="{'selected': selectedValues[182] === item.id}" x-text="getSwatchText(182, item.id) + ' uds.'"></span> 6382 </div> 6383 <div class="w-1/3 px-0 text-center"> 6384 <span class="inline-block font-medium text-sm line-through text-gray-medium" x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" x-text="hyva.formatPrice(prices.oldPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 6385 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 6386 </div> 6387 <div class="w-1/3 px-0 text-center"> 6388 <span x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" class="line-through text-gray-medium inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.oldPrice.amount, false, optionConfig.priceFormat)"></span> 6389 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount, false, optionConfig.priceFormat)"></span> 6390 </div> 6391 </div> 6392 </label> 6393 </template> 6394</div> 6395 </template> 6396</div> 6397 </div> 6398 <template x-if="isTooltipVisible()"> 6399 <div class="absolute" :style="getTooltipPosition()"> 6400 <div class="whitespace-nowrap shadow-lg absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-full z-10 p-1.5 -mt-1.5 text-xs text-white bg-black shadow-lg text-center"> 6401 <template x-if="isVisualSwatch(activeTooltipItem.attribute, activeTooltipItem.item)"> 6402 <div class="hidden border shadow-sm border-container" 6403 :style="getTooltipImageStyle(activeTooltipItem.attribute, activeTooltipItem.item)" 6404 ></div> 6405 </template>
6406 <span x-html="getTooltipLabel()"></span> 6407 </div> 6408 <svg xmlns="http://www.w3.org/2000/svg" 6409 viewBox="0 0 9 4.5" 6410 width="9" 6411 height="9" 6412 class="shadow-lg absolute left-1/2 transform -translate-x-1/2 -translate-y-full"> 6413 <path d="M-.025 0L4.5-4.525 9.025 0 4.5 4.525z"/> 6414 </svg> 6415 </div> 6416</template> 6417 </div> 6418 </div> 6419 6420 <div 6421 class="mt-auto" 6422 x-data="{showAddToCartButton: true, productId: '98' }" 6423 :class="{'': showAddToCartButton, '': !showAddToCartButton}" 6424 @list-configurable-selection-changed.window="if(productId === $event.detail.productId) showAddToCartButton = $event.detail.saleable"> 6425 <div x-cloak x-show="!showAddToCartButton"> 6426 <a class="btn bg-gray w-full shadow rounded" href="https://www.serrats.com/es_es/bonito-del-norte-salsa-lata-120g"> 6427 <span>No está disponible</span> 6428 </a> 6429 </div> 6430 <button class="btn btn-dark-fill shadow w-full" 6431 x-show="showAddToCartButton" 6432 aria-label="Añadir al carrito"> 6433 <span class="">Añadir al carrito</span> 6434 </button> 6435 </div> 6436 </div> 6437 </div> 6438 </div> 6439 6440 </form> 6441 <form method="post" 6442 action="https://www.serrats.com/es_es/checkout/cart/add/uenc/%25uenc%25/product/141/" 6443 class="item product product-item product_addtocart_form bg-product-bg-color border-product-bg-border attribute_set_id_4 group/card flex flex-1 flex-col transition-shadow duration-300 ease-in shadow-[0px_0px_20px_rgba(0,0,0,0.05)] hover:shadow-[0px_0px_20px_rgba(0,0,0,0.1)]" 6444 x-data="{activeItem: false, activeDetails: false}" 6445 @mouseenter="activeItem = true" 6446 @mouseleave="activeItem = false" 6447 :class="{'bg-product-bg-hover-color border-product-bg-hover-border no-hover': activeItem }" 6448> 6449 <div x-data="{ formKey: '' }" x-init="formKey = hyva.getFormKey()"> 6450 <input name="form_key" type="hidden" :value="formKey"/> 6451</div> 6452 <input type="hidden" name="product" value="141"/> 6453 <div class="container-card flex flex-col h-full"> 6454 <div class="relative"> 6455 6456<div class="relative"> 6457<div class="grid grid-cols-2 gap-2 p-2 absolute right-0 left-0 bottom-0 top-0 pointer-events-none"> 6458 </div> 6459 6460<a class="relative product photo product-item-photo block overflow-hidden" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-frasco-212g" 6461 mcclane-data="category-item"> 6462 <img x-data="showHoverImage()" 6463 @update-gallery-141.window="$root.src = $event.detail" 6464 class="h-full object-contain w-full md:group-hover/card:scale-[1.05] transition-all" 6465 @mouseover="onHover()" 6466 @mouseleave="onLeave()" 6467 loading="lazy" 6468 alt="Bonito del Norte en aceite de oliva. Frasco 190g." 6469 title="Bonito del Norte en aceite de oliva. Frasco 190g." 6470 src="https://www.serrats.com/media/catalog/product/m/i/miniatura_rt212_bno.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 6471 src-hover="" 6472 src-leave="https://www.serrats.com/media/catalog/product/m/i/miniatura_rt212_bno.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 6473 width="420" 6474 height="420" 6475/> 6476 6477 6478</a> 6479</div> 6480 </div> 6481 <div class="flex flex-col pt-3 p-2.5 lg:p-4 gap-2 h-full"> 6482 <div class="flex flex-col gap-2 lg:gap-3.5"> 6483 </div> 6484 <div class="flex justify-between"> 6485 <div class="flex"> 6486 6487<a class="product-item-link" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-frasco-212g" 6488 > 6489 <span class="product-card-title md:product-card-title-desktop text-product-card-title line-clamp-3 min-h-[3.5em]"> 6490 Bonito del Norte en aceite de oliva. Frasco 190g.</span> 6491</a> 6492 </div> 6493 <div class="flex"> 6494 </div> 6495 </div> 6496 <div class="flex flex-col gap-3 h-full"> 6497 6498 <span class="line-clamp-1 text-sm text-gray-dark">Frasco de Cristal</span> 6499 <div class=""> 6500
6500<script> 6501 function initConfigurableSwatchOptions_141() { 6502 const configurableOptionsComponent = initConfigurableOptions( 6503 '141', 6504 {"attributes":{"182":{"id":"182","code":"uds_caja","label":"Uds Caja","options":[{"id":"41","label":"6","products":["73"],"type":"0","value":"6"},{"id":"43","label":"12","products":["72"],"type":"0","value":"12"}],"position":"0"}},"template":"<%- data.price %>\u00a0\u20ac","currencyFormat":"%s\u00a0\u20ac","optionPrices":{"73":{"baseOldPrice":{"amount":31.818180818182},"oldPrice":{"amount":35},"basePrice":{"amount":31.818180818182},"finalPrice":{"amount":35},"tierPrices":[],"msrpPrice":{"amount":0}},"72":{"baseOldPrice":{"amount":62.727271727273},"oldPrice":{"amount":69},"basePrice":{"amount":62.727271727273},"finalPrice":{"amount":69},"tierPrices":[],"msrpPrice":{"amount":0}}},"priceFormat":{"pattern":"%s\u00a0\u20ac","precision":2,"requiredPrecision":2,"decimalSymbol":",","groupSymbol":".","groupLength":3,"integerRequired":false},"prices":{"baseOldPrice":{"amount":31.818180818182},"oldPrice":{"amount":35},"basePrice":{"amount":31.818180818182},"finalPrice":{"amount":35}},"productId":"141","chooseText":"Elegir una opci\u00f3n...","images":[],"index":{"73":{"182":"41"},"72":{"182":"43"}},"salable":[],"canDisplayShowOutOfStockStatus":false,"saleable":{"73":true,"72":true},"preselect_sku_child":"SERRATS_RT212_BNO_6","childProducts":{"SERRATS_RT212_BNO_6":"73","SERRATS_RT212_BNO_12":"72"}} ); 6505 const swatchOptionsComponent = initSwatchOptions({"182":{"41":{"type":"0","value":"6","label":"6"},"43":{"type":"0","value":"12","label":"12"},"additional_data":"{\"swatch_input_type\":\"text\",\"update_product_preview_image\":\"0\",\"use_product_image_for_swatch\":0}"}}); 6506 6507 if (typeof window.configurableOptionsInitialized === "undefined") { 6508 window.configurableOptionsInitialized = []; 6509 } 6510 6511 return Object.assign( 6512 configurableOptionsComponent, 6513 swatchOptionsComponent, 6514 { 6515 mediaCallback: "https\u003A\u002F\u002Fwww.serrats.com\u002Fes_es\u002Fswatches\u002Fajax\u002Fmedia\u002F", 6516 changeOption(optionId, value, skipUpdateGallery) { 6517 this.selectedValues[optionId] = value; 6518 this.findSimpleIndex(); 6519 this.findAllowedAttributeOptions(); 6520 this.updatePrices(); 6521 !skipUpdateGallery && this.updateGallery(); 6522 6523 window.dispatchEvent( 6524 new CustomEvent( 6525 'list-configurable-selection-changed', 6526 { 6527 detail: { 6528 productId: this.productId, 6529 optionId, 6530 value, 6531 productIndex: this.productIndex, 6532 selectedValues: this.selectedValues, 6533 saleable: this.optionConfig.saleable[this.productIndex] 6534 } 6535 } 6536 ) 6537 ); 6538 }, 6539 syncConfigurableSwatchOptions(event) { 6540 let product = event.detail; 6541 if (product.productId !== this.productId) return; 6542 if (product.productIndex !== this.productIndex) this.productIndex = product.productIndex 6543 if (product.selectedValues !== this.selectedValues) this.selectedValues = product.selectedValues 6544 }, 6545 resetSwatches() { 6546 let featured = []; 6547 this.selectedValues = featured; 6548 }, 6549 updateGallery() { 6550 let configSkipGalleryUpdate = 0; 6551 6552 if (!this.productIndex || configSkipGalleryUpdate ) { 6553 return; 6554 } 6555 6556 fetch(`${this.mediaCallback}?product_id=${this.productIndex}`, { 6557 method: 'GET', 6558 headers: { 6559 'Content-Type': 'application/json', 6560 'X-Requested-With': 'XMLHttpRequest' 6561 } 6562 } 6563 ).then(response => { 6564 return response.json() 6565 } 6566 ).then(data => { 6567 if (data.errors) { 6568 // non critical failure only console logged 6569 console.warn(data.errors); 6570 } else { 6571 const image = data && data.medium; 6572 6573 image && window.dispatchEvent( 6574 new CustomEvent( 6575 "update-gallery-141", 6576 {detail: image} 6577 ) 6578 ); 6579 } 6580 }).catch(error => { 6581 console.warn(error) 6582 }); 6583 }, 6584 preselectQuerystringItems() { 6585 // pre-select option like ?size=167 6586 const urlQueryParams = new URLSearchParams(window.location.search.replace('?', '')); 6587 Object.values(this.optionConfig.attributes).map(attribute => { 6588 // Don't update images on load, since PLPs already set the main image to the selected options 6589 const skipUpdateGallery = true; 6590 urlQueryParams.get(attribute.code) && 6591 this.changeOption(attribute.id, urlQueryParams.get(attribute.code), skipUpdateGallery); 6592 }); 6593 }, 6594 mouseDown: false, 6595 startX: 0, 6596 maxScroll: 0, 6597 scrollLeft: null, 6598 slider: null, 6599 attributeIdFeatured: null, 6600 items: [], 6601 limitToScroll: 0, 6602 limitToScrollMobile: 3, 6603 limitToScrollDesktop: 5, 6604 scrollEvents: { 6605 ['@mousedown'](e) { 6606 this.slider = e.target.closest('.snap'); 6607 if (!this.slider) { 6608 return; 6609 } 6610 this.maxScroll = this.slider.scrollWidth - this.slider.offsetWidth; 6611 this.startX = e.pageX - this.slider.offsetLeft; 6612 this.scrollLeft = this.slider.scrollLeft; 6613 this.mouseDown = true; 6614 }, 6615 ['@mouseout.self']() { 6616 this.mouseDown = false;
6617 }, 6618 ['@mouseup']() { 6619 this.mouseDown = false; 6620 }, 6621 ['@mousemove'](e) { 6622 e.preventDefault(); 6623 if (!this.mouseDown) { 6624 return; 6625 } 6626 const x = e.pageX - this.slider.offsetLeft; 6627 const scroll = x - this.startX; 6628 const scrollLeft = this.scrollLeft - scroll; 6629 6630 if (scrollLeft > this.maxScroll) { 6631 this.slider.scrollLeft = this.maxScroll; 6632 return 6633 } 6634 this.slider.scrollLeft = this.scrollLeft - scroll; 6635 }, 6636 ['@onselectstart']() { 6637 return false; 6638 }, 6639 ['@resize.window']() { 6640 this.initShowScrollSwatches(); 6641 }, 6642 ['@tabchange.window']() { 6643 this.initShowScrollSwatches(); 6644 } 6645 }, 6646 clickLeftEvent() { 6647 this.slider = this.$root.querySelector('.snap'); 6648 this.slider.scrollLeft -= this.slider.offsetWidth; 6649 }, 6650 clickRightEvent() { 6651 this.slider = this.$root.querySelector('.snap'); 6652 this.slider.scrollLeft += this.slider.offsetWidth; 6653 }, 6654 setLimitScroll() { 6655 this.limitToScroll = window.innerWidth > 767 ? this.limitToScrollDesktop : this.limitToScrollMobile; 6656 }, 6657 initShowScrollSwatches() { 6658 this.$nextTick(() => { 6659 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
6659der => { 6660 this.items = slider.querySelectorAll(':scope > div:not(.hidden)'); 6661 this.setLimitScroll(); 6662 6663 if (this.limitToScroll > this.items.length) { 6664 this.limitToScroll = this.items.length; 6665 } 6666 6667 let itemLimit = this.items[this.limitToScroll - 1]; 6668 let marginOffset = parseFloat(getComputedStyle(slider.parentElement).marginLeft) + parseFloat(getComputedStyle(slider.parentElement).marginRight); 6669 6670 let widthMax = this.$root.offsetWidth - marginOffset; 6671 let width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 6672 6673 slider.style.width = width + 'px'; 6674 slider.scrollLeft = 0; 6675 6676 while (width > widthMax && this.limitToScroll > 1) { 6677 this.limitToScroll--; 6678 itemLimit = this.items[this.limitToScroll - 1]; 6679 width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 6680 slider.style.width = width + 'px'; 6681 slider.scrollLeft = 0; 6682 } 6683 }); 6684 }); 6685 }, 6686 resizeEvent() { 6687 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
6687der => { 6688 slider.scrollLeft = 0; 6689 }) 6690 }, 6691 contentLoaded(eventData) { 6692 if (typeof window.configurableOptionsInitialized[this.productId] !== "undefined") { 6693 return; 6694 } 6695 6696 this.onGetCartData(eventData); 6697 window.configurableOptionsInitialized[this.productId] = true; 6698 } 6699 } 6700 ); 6701 } 6702</script>
6702 6703 6704 6705<div x-data="initConfigurableSwatchOptions_141()" 6706 x-init="findAllowedAttributeOptions(); initShowSwatchesIntersect();" 6707 @list-configurable-selection-changed.window="syncConfigurableSwatchOptions($event)" 6708 @list-swatches-reset-141.window="resetSwatches()" 6709 @private-content-loaded.window="contentLoaded($event.detail.data)" 6710 @resize.window="resizeEvent()" 6711> 6712 <div class="flex flex-col flex-nowrap gap-y-3"> 6713 6714 6715<div class="flex flex-col swatch-attribute"> 6716 <div class="flex mx-0 serrats-table-header uppercase border-b border-[#d9ddd7]"> 6717 <div class="w-1/3 px-0">Unidades caja</div> 6718 <div class="w-1/3 px-0 text-center">Precio unidad</div> 6719 <div class="w-1/3 px-0 text-center font-semibold"><span>Precio caja</span></div> 6720 </div> 6721 <template x-for="(item, index) in optionConfig.attributes[182].options" :key="item.id"> 6722 <div class="py-2"> 6723 <template x-if="optionIsEnabled(182, item.id)"> 6724 <label 6725 :for="'attribute-option-141-'+item.id" 6726 :mcclane-data="'product-configurable-custom-option-'+item.id" 6727 @touchend.passive="selectedValues[182] ? '' : changeOption(182, item.id)" 6728 class="flex items-center gap-2" 6729 > 6730 <input 6731 :id="'attribute-option-141-'+item.id" 6732 :value="item.id" 6733 name="super_attribute[182]" 6734 type="radio" 6735 class="border-0 focus:border-0 focus:ring-0 inline-block p-0 opacity-0 product-option-value-input absolute" 6736 style="z-index:-1" 6737 x-on:focus="focusLabel(item.id)" 6738 x-on:blur="blurLabel()" 6739 x-on:change="changeOption(182, $event.target.value)" 6740 @list-configurable-selection-changed.window="findAllowedAttributeOptions();" 6741 x-model="selectedValues[182]" 6742 :required="getAllowedAttributeOptions(182).filter(attributeOption => selectedValues[attributeOption]).length === 0" 6743 /> 6744 <div class="flex flex-grow items-center mx-0 cursor-pointer" x-data="{prices: optionConfig.optionPrices[item.availableProductsId[0]]}"> 6745 <div class="w-1/3"> 6746 <span class="inline-block lowercase text-sm serrats-custom-swatch-container flex items-center" :class="{'selected': selectedValues[182] === item.id}" x-text="getSwatchText(182, item.id) + ' uds.'"></span> 6747 </div> 6748 <div class="w-1/3 px-0 text-center"> 6749 <span class="inline-block font-medium text-sm line-through text-gray-medium" x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" x-text="hyva.formatPrice(prices.oldPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 6750 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 6751 </div> 6752 <div class="w-1/3 px-0 text-center"> 6753 <span x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" class="line-through text-gray-medium inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.oldPrice.amount, false, optionConfig.priceFormat)"></span> 6754 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount, false, optionConfig.priceFormat)"></span> 6755 </div> 6756 </div> 6757 </label> 6758 </template> 6759</div> 6760 </template> 6761</div> 6762 </div> 6763 <template x-if="isTooltipVisible()"> 6764 <div class="absolute" :style="getTooltipPosition()"> 6765 <div class="whitespace-nowrap shadow-lg absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-full z-10 p-1.5 -mt-1.5 text-xs text-white bg-black shadow-lg text-center"> 6766 <template x-if="isVisualSwatch(activeTooltipItem.attribute, activeTooltipItem.item)"> 6767 <div class="hidden border shadow-sm border-container" 6768 :style="getTooltipImageStyle(activeTooltipItem.attribute, activeTooltipItem.item)" 6769 ></div> 6770 </template>
6771 <span x-html="getTooltipLabel()"></span> 6772 </div> 6773 <svg xmlns="http://www.w3.org/2000/svg" 6774 viewBox="0 0 9 4.5" 6775 width="9" 6776 height="9" 6777 class="shadow-lg absolute left-1/2 transform -translate-x-1/2 -translate-y-full"> 6778 <path d="M-.025 0L4.5-4.525 9.025 0 4.5 4.525z"/> 6779 </svg> 6780 </div> 6781</template> 6782 </div> 6783 </div> 6784 6785 <div 6786 class="mt-auto" 6787 x-data="{showAddToCartButton: true, productId: '141' }" 6788 :class="{'': showAddToCartButton, '': !showAddToCartButton}" 6789 @list-configurable-selection-changed.window="if(productId === $event.detail.productId) showAddToCartButton = $event.detail.saleable"> 6790 <div x-cloak x-show="!showAddToCartButton"> 6791 <a class="btn bg-gray w-full shadow rounded" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-frasco-212g"> 6792 <span>No está disponible</span> 6793 </a> 6794 </div> 6795 <button class="btn btn-dark-fill shadow w-full" 6796 x-show="showAddToCartButton" 6797 aria-label="Añadir al carrito"> 6798 <span class="">Añadir al carrito</span> 6799 </button> 6800 </div> 6801 </div> 6802 </div> 6803 </div> 6804 6805 </form> 6806 <form method="post" 6807 action="https://www.serrats.com/es_es/checkout/cart/add/uenc/%25uenc%25/product/140/" 6808 class="item product product-item product_addtocart_form bg-product-bg-color border-product-bg-border attribute_set_id_4 group/card flex flex-1 flex-col transition-shadow duration-300 ease-in shadow-[0px_0px_20px_rgba(0,0,0,0.05)] hover:shadow-[0px_0px_20px_rgba(0,0,0,0.1)]" 6809 x-data="{activeItem: false, activeDetails: false}" 6810 @mouseenter="activeItem = true" 6811 @mouseleave="activeItem = false" 6812 :class="{'bg-product-bg-hover-color border-product-bg-hover-border no-hover': activeItem }" 6813> 6814 <div x-data="{ formKey: '' }" x-init="formKey = hyva.getFormKey()"> 6815 <input name="form_key" type="hidden" :value="formKey"/> 6816</div> 6817 <input type="hidden" name="product" value="140"/> 6818 <div class="container-card flex flex-col h-full"> 6819 <div class="relative"> 6820 6821<div class="relative"> 6822<div class="grid grid-cols-2 gap-2 p-2 absolute right-0 left-0 bottom-0 top-0 pointer-events-none"> 6823 </div> 6824 6825<a class="relative product photo product-item-photo block overflow-hidden" href="https://www.serrats.com/es_es/bonito-norte-al-natural" 6826 mcclane-data="category-item"> 6827 <img x-data="showHoverImage()" 6828 @update-gallery-140.window="$root.src = $event.detail" 6829 class="h-full object-contain w-full md:group-hover/card:scale-[1.05] transition-all" 6830 @mouseover="onHover()" 6831 @mouseleave="onLeave()" 6832 loading="lazy" 6833 alt="Bonito del Norte al natural. Frasco 190g." 6834 title="Bonito del Norte al natural. Frasco 190g." 6835 src="https://www.serrats.com/media/catalog/product/m/i/miniatura_rt212_bnn_1.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 6836 src-hover="" 6837 src-leave="https://www.serrats.com/media/catalog/product/m/i/miniatura_rt212_bnn_1.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 6838 width="420" 6839 height="420" 6840/> 6841 6842 6843</a> 6844</div> 6845 </div> 6846 <div class="flex flex-col pt-3 p-2.5 lg:p-4 gap-2 h-full"> 6847 <div class="flex flex-col gap-2 lg:gap-3.5"> 6848 </div> 6849 <div class="flex justify-between"> 6850 <div class="flex"> 6851 6852<a class="product-item-link" href="https://www.serrats.com/es_es/bonito-norte-al-natural" 6853 > 6854 <span class="product-card-title md:product-card-title-desktop text-product-card-title line-clamp-3 min-h-[3.5em]"> 6855 Bonito del Norte al natural. Frasco 190g.</span> 6856</a> 6857 </div> 6858 <div class="flex"> 6859 </div> 6860 </div> 6861 <div class="flex flex-col gap-3 h-full"> 6862 6863 <span class="line-clamp-1 text-sm text-gray-dark">Frasco de Cristal</span> 6864 <div class=""> 6865
6865<script> 6866 function initConfigurableSwatchOptions_140() { 6867 const configurableOptionsComponent = initConfigurableOptions( 6868 '140', 6869 {"attributes":{"182":{"id":"182","code":"uds_caja","label":"Uds Caja","options":[{"id":"41","label":"6","products":["157"],"type":"0","value":"6"},{"id":"43","label":"12","products":["70"],"type":"0","value":"12"}],"position":"0"}},"template":"<%- data.price %>\u00a0\u20ac","currencyFormat":"%s\u00a0\u20ac","optionPrices":{"157":{"baseOldPrice":{"amount":31.818180818182},"oldPrice":{"amount":35},"basePrice":{"amount":31.818180818182},"finalPrice":{"amount":35},"tierPrices":[],"msrpPrice":{"amount":0}},"70":{"baseOldPrice":{"amount":62.727271727273},"oldPrice":{"amount":69},"basePrice":{"amount":62.727271727273},"finalPrice":{"amount":69},"tierPrices":[],"msrpPrice":{"amount":0}}},"priceFormat":{"pattern":"%s\u00a0\u20ac","precision":2,"requiredPrecision":2,"decimalSymbol":",","groupSymbol":".","groupLength":3,"integerRequired":false},"prices":{"baseOldPrice":{"amount":31.818180818182},"oldPrice":{"amount":35},"basePrice":{"amount":31.818180818182},"finalPrice":{"amount":35}},"productId":"140","chooseText":"Elegir una opci\u00f3n...","images":[],"index":{"157":{"182":"41"},"70":{"182":"43"}},"salable":[],"canDisplayShowOutOfStockStatus":false,"saleable":{"157":true,"70":true},"preselect_sku_child":"SERRATS_RT212_BNN_6","childProducts":{"SERRATS_RT212_BNN_6":"157","SERRATS_RT212_BNN_12":"70"}} ); 6870 const swatchOptionsComponent = initSwatchOptions({"182":{"41":{"type":"0","value":"6","label":"6"},"43":{"type":"0","value":"12","label":"12"},"additional_data":"{\"swatch_input_type\":\"text\",\"update_product_preview_image\":\"0\",\"use_product_image_for_swatch\":0}"}}); 6871 6872 if (typeof window.configurableOptionsInitialized === "undefined") { 6873 window.configurableOptionsInitialized = []; 6874 } 6875 6876 return Object.assign( 6877 configurableOptionsComponent, 6878 swatchOptionsComponent, 6879 { 6880 mediaCallback: "https\u003A\u002F\u002Fwww.serrats.com\u002Fes_es\u002Fswatches\u002Fajax\u002Fmedia\u002F", 6881 changeOption(optionId, value, skipUpdateGallery) { 6882 this.selectedValues[optionId] = value; 6883 this.findSimpleIndex(); 6884 this.findAllowedAttributeOptions(); 6885 this.updatePrices(); 6886 !skipUpdateGallery && this.updateGallery(); 6887 6888 window.dispatchEvent( 6889 new CustomEvent( 6890 'list-configurable-selection-changed', 6891 { 6892 detail: { 6893 productId: this.productId, 6894 optionId, 6895 value, 6896 productIndex: this.productIndex, 6897 selectedValues: this.selectedValues, 6898 saleable: this.optionConfig.saleable[this.productIndex] 6899 } 6900 } 6901 ) 6902 ); 6903 }, 6904 syncConfigurableSwatchOptions(event) { 6905 let product = event.detail; 6906 if (product.productId !== this.productId) return; 6907 if (product.productIndex !== this.productIndex) this.productIndex = product.productIndex 6908 if (product.selectedValues !== this.selectedValues) this.selectedValues = product.selectedValues 6909 }, 6910 resetSwatches() { 6911 let featured = []; 6912 this.selectedValues = featured; 6913 }, 6914 updateGallery() { 6915 let configSkipGalleryUpdate = 0; 6916 6917 if (!this.productIndex || configSkipGalleryUpdate ) { 6918 return; 6919 } 6920 6921 fetch(`${this.mediaCallback}?product_id=${this.productIndex}`, { 6922 method: 'GET', 6923 headers: { 6924 'Content-Type': 'application/json', 6925 'X-Requested-With': 'XMLHttpRequest' 6926 } 6927 } 6928 ).then(response => { 6929 return response.json() 6930 } 6931 ).then(data => { 6932 if (data.errors) { 6933 // non critical failure only console logged 6934 console.warn(data.errors); 6935 } else { 6936 const image = data && data.medium; 6937 6938 image && window.dispatchEvent( 6939 new CustomEvent( 6940 "update-gallery-140", 6941 {detail: image} 6942 ) 6943 ); 6944 } 6945 }).catch(error => { 6946 console.warn(error) 6947 }); 6948 }, 6949 preselectQuerystringItems() { 6950 // pre-select option like ?size=167 6951 const urlQueryParams = new URLSearchParams(window.location.search.replace('?', '')); 6952 Object.values(this.optionConfig.attributes).map(attribute => { 6953 // Don't update images on load, since PLPs already set the main image to the selected options 6954 const skipUpdateGallery = true; 6955 urlQueryParams.get(attribute.code) && 6956 this.changeOption(attribute.id, urlQueryParams.get(attribute.code), skipUpdateGallery); 6957 }); 6958 }, 6959 mouseDown: false, 6960 startX: 0, 6961 maxScroll: 0, 6962 scrollLeft: null, 6963 slider: null, 6964 attributeIdFeatured: null, 6965 items: [], 6966 limitToScroll: 0, 6967 limitToScrollMobile: 3, 6968 limitToScrollDesktop: 5, 6969 scrollEvents: { 6970 ['@mousedown'](e) { 6971 this.slider = e.target.closest('.snap'); 6972 if (!this.slider) { 6973 return; 6974 } 6975 this.maxScroll = this.slider.scrollWidth - this.slider.offsetWidth; 6976 this.startX = e.pageX - this.slider.offsetLeft; 6977 this.scrollLeft = this.slider.scrollLeft; 6978 this.mouseDown = true; 6979 }, 6980 ['@mouseout.self']() { 6981 this.mouseDown = false;
6982 }, 6983 ['@mouseup']() { 6984 this.mouseDown = false; 6985 }, 6986 ['@mousemove'](e) { 6987 e.preventDefault(); 6988 if (!this.mouseDown) { 6989 return; 6990 } 6991 const x = e.pageX - this.slider.offsetLeft; 6992 const scroll = x - this.startX; 6993 const scrollLeft = this.scrollLeft - scroll; 6994 6995 if (scrollLeft > this.maxScroll) { 6996 this.slider.scrollLeft = this.maxScroll; 6997 return 6998 } 6999 this.slider.scrollLeft = this.scrollLeft - scroll; 7000 }, 7001 ['@onselectstart']() { 7002 return false; 7003 }, 7004 ['@resize.window']() { 7005 this.initShowScrollSwatches(); 7006 }, 7007 ['@tabchange.window']() { 7008 this.initShowScrollSwatches(); 7009 } 7010 }, 7011 clickLeftEvent() { 7012 this.slider = this.$root.querySelector('.snap'); 7013 this.slider.scrollLeft -= this.slider.offsetWidth; 7014 }, 7015 clickRightEvent() { 7016 this.slider = this.$root.querySelector('.snap'); 7017 this.slider.scrollLeft += this.slider.offsetWidth; 7018 }, 7019 setLimitScroll() { 7020 this.limitToScroll = window.innerWidth > 767 ? this.limitToScrollDesktop : this.limitToScrollMobile; 7021 }, 7022 initShowScrollSwatches() { 7023 this.$nextTick(() => { 7024 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
7024der => { 7025 this.items = slider.querySelectorAll(':scope > div:not(.hidden)'); 7026 this.setLimitScroll(); 7027 7028 if (this.limitToScroll > this.items.length) { 7029 this.limitToScroll = this.items.length; 7030 } 7031 7032 let itemLimit = this.items[this.limitToScroll - 1]; 7033 let marginOffset = parseFloat(getComputedStyle(slider.parentElement).marginLeft) + parseFloat(getComputedStyle(slider.parentElement).marginRight); 7034 7035 let widthMax = this.$root.offsetWidth - marginOffset; 7036 let width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 7037 7038 slider.style.width = width + 'px'; 7039 slider.scrollLeft = 0; 7040 7041 while (width > widthMax && this.limitToScroll > 1) { 7042 this.limitToScroll--; 7043 itemLimit = this.items[this.limitToScroll - 1]; 7044 width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 7045 slider.style.width = width + 'px'; 7046 slider.scrollLeft = 0; 7047 } 7048 }); 7049 }); 7050 }, 7051 resizeEvent() { 7052 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
7052der => { 7053 slider.scrollLeft = 0; 7054 }) 7055 }, 7056 contentLoaded(eventData) { 7057 if (typeof window.configurableOptionsInitialized[this.productId] !== "undefined") { 7058 return; 7059 } 7060 7061 this.onGetCartData(eventData); 7062 window.configurableOptionsInitialized[this.productId] = true; 7063 } 7064 } 7065 ); 7066 } 7067</script>
7067 7068 7069 7070<div x-data="initConfigurableSwatchOptions_140()" 7071 x-init="findAllowedAttributeOptions(); initShowSwatchesIntersect();" 7072 @list-configurable-selection-changed.window="syncConfigurableSwatchOptions($event)" 7073 @list-swatches-reset-140.window="resetSwatches()" 7074 @private-content-loaded.window="contentLoaded($event.detail.data)" 7075 @resize.window="resizeEvent()" 7076> 7077 <div class="flex flex-col flex-nowrap gap-y-3"> 7078 7079 7080<div class="flex flex-col swatch-attribute"> 7081 <div class="flex mx-0 serrats-table-header uppercase border-b border-[#d9ddd7]"> 7082 <div class="w-1/3 px-0">Unidades caja</div> 7083 <div class="w-1/3 px-0 text-center">Precio unidad</div> 7084 <div class="w-1/3 px-0 text-center font-semibold"><span>Precio caja</span></div> 7085 </div> 7086 <template x-for="(item, index) in optionConfig.attributes[182].options" :key="item.id"> 7087 <div class="py-2"> 7088 <template x-if="optionIsEnabled(182, item.id)"> 7089 <label 7090 :for="'attribute-option-140-'+item.id" 7091 :mcclane-data="'product-configurable-custom-option-'+item.id" 7092 @touchend.passive="selectedValues[182] ? '' : changeOption(182, item.id)" 7093 class="flex items-center gap-2" 7094 > 7095 <input 7096 :id="'attribute-option-140-'+item.id" 7097 :value="item.id" 7098 name="super_attribute[182]" 7099 type="radio" 7100 class="border-0 focus:border-0 focus:ring-0 inline-block p-0 opacity-0 product-option-value-input absolute" 7101 style="z-index:-1" 7102 x-on:focus="focusLabel(item.id)" 7103 x-on:blur="blurLabel()" 7104 x-on:change="changeOption(182, $event.target.value)" 7105 @list-configurable-selection-changed.window="findAllowedAttributeOptions();" 7106 x-model="selectedValues[182]" 7107 :required="getAllowedAttributeOptions(182).filter(attributeOption => selectedValues[attributeOption]).length === 0" 7108 /> 7109 <div class="flex flex-grow items-center mx-0 cursor-pointer" x-data="{prices: optionConfig.optionPrices[item.availableProductsId[0]]}"> 7110 <div class="w-1/3"> 7111 <span class="inline-block lowercase text-sm serrats-custom-swatch-container flex items-center" :class="{'selected': selectedValues[182] === item.id}" x-text="getSwatchText(182, item.id) + ' uds.'"></span> 7112 </div> 7113 <div class="w-1/3 px-0 text-center"> 7114 <span class="inline-block font-medium text-sm line-through text-gray-medium" x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" x-text="hyva.formatPrice(prices.oldPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 7115 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 7116 </div> 7117 <div class="w-1/3 px-0 text-center"> 7118 <span x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" class="line-through text-gray-medium inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.oldPrice.amount, false, optionConfig.priceFormat)"></span> 7119 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount, false, optionConfig.priceFormat)"></span> 7120 </div> 7121 </div> 7122 </label> 7123 </template> 7124</div> 7125 </template> 7126</div> 7127 </div> 7128 <template x-if="isTooltipVisible()"> 7129 <div class="absolute" :style="getTooltipPosition()"> 7130 <div class="whitespace-nowrap shadow-lg absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-full z-10 p-1.5 -mt-1.5 text-xs text-white bg-black shadow-lg text-center"> 7131 <template x-if="isVisualSwatch(activeTooltipItem.attribute, activeTooltipItem.item)"> 7132 <div class="hidden border shadow-sm border-container" 7133 :style="getTooltipImageStyle(activeTooltipItem.attribute, activeTooltipItem.item)" 7134 ></div> 7135 </template>
7136 <span x-html="getTooltipLabel()"></span> 7137 </div> 7138 <svg xmlns="http://www.w3.org/2000/svg" 7139 viewBox="0 0 9 4.5" 7140 width="9" 7141 height="9" 7142 class="shadow-lg absolute left-1/2 transform -translate-x-1/2 -translate-y-full"> 7143 <path d="M-.025 0L4.5-4.525 9.025 0 4.5 4.525z"/> 7144 </svg> 7145 </div> 7146</template> 7147 </div> 7148 </div> 7149 7150 <div 7151 class="mt-auto" 7152 x-data="{showAddToCartButton: true, productId: '140' }" 7153 :class="{'': showAddToCartButton, '': !showAddToCartButton}" 7154 @list-configurable-selection-changed.window="if(productId === $event.detail.productId) showAddToCartButton = $event.detail.saleable"> 7155 <div x-cloak x-show="!showAddToCartButton"> 7156 <a class="btn bg-gray w-full shadow rounded" href="https://www.serrats.com/es_es/bonito-norte-al-natural"> 7157 <span>No está disponible</span> 7158 </a> 7159 </div> 7160 <button class="btn btn-dark-fill shadow w-full" 7161 x-show="showAddToCartButton" 7162 aria-label="Añadir al carrito"> 7163 <span class="">Añadir al carrito</span> 7164 </button> 7165 </div> 7166 </div> 7167 </div> 7168 </div> 7169 7170 </form> 7171 <form method="post" 7172 action="https://www.serrats.com/es_es/checkout/cart/add/uenc/%25uenc%25/product/142/" 7173 class="item product product-item product_addtocart_form bg-product-bg-color border-product-bg-border attribute_set_id_4 group/card flex flex-1 flex-col transition-shadow duration-300 ease-in shadow-[0px_0px_20px_rgba(0,0,0,0.05)] hover:shadow-[0px_0px_20px_rgba(0,0,0,0.1)]" 7174 x-data="{activeItem: false, activeDetails: false}" 7175 @mouseenter="activeItem = true" 7176 @mouseleave="activeItem = false" 7177 :class="{'bg-product-bg-hover-color border-product-bg-hover-border no-hover': activeItem }" 7178> 7179 <div x-data="{ formKey: '' }" x-init="formKey = hyva.getFormKey()"> 7180 <input name="form_key" type="hidden" :value="formKey"/> 7181</div> 7182 <input type="hidden" name="product" value="142"/> 7183 <div class="container-card flex flex-col h-full"> 7184 <div class="relative"> 7185 7186<div class="relative"> 7187<div class="grid grid-cols-2 gap-2 p-2 absolute right-0 left-0 bottom-0 top-0 pointer-events-none"> 7188 </div> 7189 7190<a class="relative product photo product-item-photo block overflow-hidden" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-virgen-extra-ecologico-212g" 7191 mcclane-data="category-item"> 7192 <img x-data="showHoverImage()" 7193 @update-gallery-142.window="$root.src = $event.detail" 7194 class="h-full object-contain w-full md:group-hover/card:scale-[1.05] transition-all" 7195 @mouseover="onHover()" 7196 @mouseleave="onLeave()" 7197 loading="lazy" 7198 alt="Bonito del Norte en aceite de oliva virgen ECOLÓGICO. Frasco 190g." 7199 title="Bonito del Norte en aceite de oliva virgen ECOLÓGICO. Frasco 190g." 7200 src="https://www.serrats.com/media/catalog/product/m/i/miniatura_rt212_bn_eco.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 7201 src-hover="" 7202 src-leave="https://www.serrats.com/media/catalog/product/m/i/miniatura_rt212_bn_eco.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 7203 width="420" 7204 height="420" 7205/> 7206 7207 7208</a> 7209</div> 7210 </div> 7211 <div class="flex flex-col pt-3 p-2.5 lg:p-4 gap-2 h-full"> 7212 <div class="flex flex-col gap-2 lg:gap-3.5"> 7213 </div> 7214 <div class="flex justify-between"> 7215 <div class="flex"> 7216 7217<a class="product-item-link" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-virgen-extra-ecologico-212g" 7218 > 7219 <span class="product-card-title md:product-card-title-desktop text-product-card-title line-clamp-3 min-h-[3.5em]"> 7220 Bonito del Norte en aceite de oliva virgen ECOLÃGICO. Frasco 190g.</span> 7221</a> 7222 </div> 7223 <div class="flex"> 7224 </div> 7225 </div> 7226 <div class="flex flex-col gap-3 h-full"> 7227 7228 <span class="line-clamp-1 text-sm text-gray-dark">Frasco de Cristal</span> 7229 <div class=""> 7230
7230<script> 7231 function initConfigurableSwatchOptions_142() { 7232 const configurableOptionsComponent = initConfigurableOptions( 7233 '142', 7234 {"attributes":{"182":{"id":"182","code":"uds_caja","label":"Uds Caja","options":[{"id":"41","label":"6","products":["75"],"type":"0","value":"6"},{"id":"43","label":"12","products":["74"],"type":"0","value":"12"}],"position":"0"}},"template":"<%- data.price %>\u00a0\u20ac","currencyFormat":"%s\u00a0\u20ac","optionPrices":{"75":{"baseOldPrice":{"amount":35.454544454545},"oldPrice":{"amount":39},"basePrice":{"amount":35.454544454545},"finalPrice":{"amount":39},"tierPrices":[],"msrpPrice":{"amount":0}},"74":{"baseOldPrice":{"amount":69.090908090909},"oldPrice":{"amount":76},"basePrice":{"amount":69.090908090909},"finalPrice":{"amount":76},"tierPrices":[],"msrpPrice":{"amount":0}}},"priceFormat":{"pattern":"%s\u00a0\u20ac","precision":2,"requiredPrecision":2,"decimalSymbol":",","groupSymbol":".","groupLength":3,"integerRequired":false},"prices":{"baseOldPrice":{"amount":35.454544454545},"oldPrice":{"amount":39},"basePrice":{"amount":35.454544454545},"finalPrice":{"amount":39}},"productId":"142","chooseText":"Elegir una opci\u00f3n...","images":[],"index":{"75":{"182":"41"},"74":{"182":"43"}},"salable":[],"canDisplayShowOutOfStockStatus":false,"saleable":{"75":true,"74":true},"preselect_sku_child":"SERRATS_RT212_BNO_ECO_6","childProducts":{"SERRATS_RT212_BNO_ECO_6":"75","SERRATS_RT212_BNO_ECO_12":"74"}} ); 7235 const swatchOptionsComponent = initSwatchOptions({"182":{"41":{"type":"0","value":"6","label":"6"},"43":{"type":"0","value":"12","label":"12"},"additional_data":"{\"swatch_input_type\":\"text\",\"update_product_preview_image\":\"0\",\"use_product_image_for_swatch\":0}"}}); 7236 7237 if (typeof window.configurableOptionsInitialized === "undefined") { 7238 window.configurableOptionsInitialized = []; 7239 } 7240 7241 return Object.assign( 7242 configurableOptionsComponent, 7243 swatchOptionsComponent, 7244 { 7245 mediaCallback: "https\u003A\u002F\u002Fwww.serrats.com\u002Fes_es\u002Fswatches\u002Fajax\u002Fmedia\u002F", 7246 changeOption(optionId, value, skipUpdateGallery) { 7247 this.selectedValues[optionId] = value; 7248 this.findSimpleIndex(); 7249 this.findAllowedAttributeOptions(); 7250 this.updatePrices(); 7251 !skipUpdateGallery && this.updateGallery(); 7252 7253 window.dispatchEvent( 7254 new CustomEvent( 7255 'list-configurable-selection-changed', 7256 { 7257 detail: { 7258 productId: this.productId, 7259 optionId, 7260 value, 7261 productIndex: this.productIndex, 7262 selectedValues: this.selectedValues, 7263 saleable: this.optionConfig.saleable[this.productIndex] 7264 } 7265 } 7266 ) 7267 ); 7268 }, 7269 syncConfigurableSwatchOptions(event) { 7270 let product = event.detail; 7271 if (product.productId !== this.productId) return; 7272 if (product.productIndex !== this.productIndex) this.productIndex = product.productIndex 7273 if (product.selectedValues !== this.selectedValues) this.selectedValues = product.selectedValues 7274 }, 7275 resetSwatches() { 7276 let featured = []; 7277 this.selectedValues = featured; 7278 }, 7279 updateGallery() { 7280 let configSkipGalleryUpdate = 0; 7281 7282 if (!this.productIndex || configSkipGalleryUpdate ) { 7283 return; 7284 } 7285 7286 fetch(`${this.mediaCallback}?product_id=${this.productIndex}`, { 7287 method: 'GET', 7288 headers: { 7289 'Content-Type': 'application/json', 7290 'X-Requested-With': 'XMLHttpRequest' 7291 } 7292 } 7293 ).then(response => { 7294 return response.json() 7295 } 7296 ).then(data => { 7297 if (data.errors) { 7298 // non critical failure only console logged 7299 console.warn(data.errors); 7300 } else { 7301 const image = data && data.medium; 7302 7303 image && window.dispatchEvent( 7304 new CustomEvent( 7305 "update-gallery-142", 7306 {detail: image} 7307 ) 7308 ); 7309 } 7310 }).catch(error => { 7311 console.warn(error) 7312 }); 7313 }, 7314 preselectQuerystringItems() { 7315 // pre-select option like ?size=167 7316 const urlQueryParams = new URLSearchParams(window.location.search.replace('?', '')); 7317 Object.values(this.optionConfig.attributes).map(attribute => { 7318 // Don't update images on load, since PLPs already set the main image to the selected options 7319 const skipUpdateGallery = true; 7320 urlQueryParams.get(attribute.code) && 7321 this.changeOption(attribute.id, urlQueryParams.get(attribute.code), skipUpdateGallery); 7322 }); 7323 }, 7324 mouseDown: false, 7325 startX: 0, 7326 maxScroll: 0, 7327 scrollLeft: null, 7328 slider: null, 7329 attributeIdFeatured: null, 7330 items: [], 7331 limitToScroll: 0, 7332 limitToScrollMobile: 3, 7333 limitToScrollDesktop: 5, 7334 scrollEvents: { 7335 ['@mousedown'](e) { 7336 this.slider = e.target.closest('.snap'); 7337 if (!this.slider) { 7338 return; 7339 } 7340 this.maxScroll = this.slider.scrollWidth - this.slider.offsetWidth; 7341 this.startX = e.pageX - this.slider.offsetLeft; 7342 this.scrollLeft = this.slider.scrollLeft; 7343 this.mouseDown = true; 7344 }, 7345 ['@mouseout.self']() { 7346 this.mouseDown = false;
7347 }, 7348 ['@mouseup']() { 7349 this.mouseDown = false; 7350 }, 7351 ['@mousemove'](e) { 7352 e.preventDefault(); 7353 if (!this.mouseDown) { 7354 return; 7355 } 7356 const x = e.pageX - this.slider.offsetLeft; 7357 const scroll = x - this.startX; 7358 const scrollLeft = this.scrollLeft - scroll; 7359 7360 if (scrollLeft > this.maxScroll) { 7361 this.slider.scrollLeft = this.maxScroll; 7362 return 7363 } 7364 this.slider.scrollLeft = this.scrollLeft - scroll; 7365 }, 7366 ['@onselectstart']() { 7367 return false; 7368 }, 7369 ['@resize.window']() { 7370 this.initShowScrollSwatches(); 7371 }, 7372 ['@tabchange.window']() { 7373 this.initShowScrollSwatches(); 7374 } 7375 }, 7376 clickLeftEvent() { 7377 this.slider = this.$root.querySelector('.snap'); 7378 this.slider.scrollLeft -= this.slider.offsetWidth; 7379 }, 7380 clickRightEvent() { 7381 this.slider = this.$root.querySelector('.snap'); 7382 this.slider.scrollLeft += this.slider.offsetWidth; 7383 }, 7384 setLimitScroll() { 7385 this.limitToScroll = window.innerWidth > 767 ? this.limitToScrollDesktop : this.limitToScrollMobile; 7386 }, 7387 initShowScrollSwatches() { 7388 this.$nextTick(() => { 7389 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
7389der => { 7390 this.items = slider.querySelectorAll(':scope > div:not(.hidden)'); 7391 this.setLimitScroll(); 7392 7393 if (this.limitToScroll > this.items.length) { 7394 this.limitToScroll = this.items.length; 7395 } 7396 7397 let itemLimit = this.items[this.limitToScroll - 1]; 7398 let marginOffset = parseFloat(getComputedStyle(slider.parentElement).marginLeft) + parseFloat(getComputedStyle(slider.parentElement).marginRight); 7399 7400 let widthMax = this.$root.offsetWidth - marginOffset; 7401 let width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 7402 7403 slider.style.width = width + 'px'; 7404 slider.scrollLeft = 0; 7405 7406 while (width > widthMax && this.limitToScroll > 1) { 7407 this.limitToScroll--; 7408 itemLimit = this.items[this.limitToScroll - 1]; 7409 width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 7410 slider.style.width = width + 'px'; 7411 slider.scrollLeft = 0; 7412 } 7413 }); 7414 }); 7415 }, 7416 resizeEvent() { 7417 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
7417der => { 7418 slider.scrollLeft = 0; 7419 }) 7420 }, 7421 contentLoaded(eventData) { 7422 if (typeof window.configurableOptionsInitialized[this.productId] !== "undefined") { 7423 return; 7424 } 7425 7426 this.onGetCartData(eventData); 7427 window.configurableOptionsInitialized[this.productId] = true; 7428 } 7429 } 7430 ); 7431 } 7432</script>
7432 7433 7434 7435<div x-data="initConfigurableSwatchOptions_142()" 7436 x-init="findAllowedAttributeOptions(); initShowSwatchesIntersect();" 7437 @list-configurable-selection-changed.window="syncConfigurableSwatchOptions($event)" 7438 @list-swatches-reset-142.window="resetSwatches()" 7439 @private-content-loaded.window="contentLoaded($event.detail.data)" 7440 @resize.window="resizeEvent()" 7441> 7442 <div class="flex flex-col flex-nowrap gap-y-3"> 7443 7444 7445<div class="flex flex-col swatch-attribute"> 7446 <div class="flex mx-0 serrats-table-header uppercase border-b border-[#d9ddd7]"> 7447 <div class="w-1/3 px-0">Unidades caja</div> 7448 <div class="w-1/3 px-0 text-center">Precio unidad</div> 7449 <div class="w-1/3 px-0 text-center font-semibold"><span>Precio caja</span></div> 7450 </div> 7451 <template x-for="(item, index) in optionConfig.attributes[182].options" :key="item.id"> 7452 <div class="py-2"> 7453 <template x-if="optionIsEnabled(182, item.id)"> 7454 <label 7455 :for="'attribute-option-142-'+item.id" 7456 :mcclane-data="'product-configurable-custom-option-'+item.id" 7457 @touchend.passive="selectedValues[182] ? '' : changeOption(182, item.id)" 7458 class="flex items-center gap-2" 7459 > 7460 <input 7461 :id="'attribute-option-142-'+item.id" 7462 :value="item.id" 7463 name="super_attribute[182]" 7464 type="radio" 7465 class="border-0 focus:border-0 focus:ring-0 inline-block p-0 opacity-0 product-option-value-input absolute" 7466 style="z-index:-1" 7467 x-on:focus="focusLabel(item.id)" 7468 x-on:blur="blurLabel()" 7469 x-on:change="changeOption(182, $event.target.value)" 7470 @list-configurable-selection-changed.window="findAllowedAttributeOptions();" 7471 x-model="selectedValues[182]" 7472 :required="getAllowedAttributeOptions(182).filter(attributeOption => selectedValues[attributeOption]).length === 0" 7473 /> 7474 <div class="flex flex-grow items-center mx-0 cursor-pointer" x-data="{prices: optionConfig.optionPrices[item.availableProductsId[0]]}"> 7475 <div class="w-1/3"> 7476 <span class="inline-block lowercase text-sm serrats-custom-swatch-container flex items-center" :class="{'selected': selectedValues[182] === item.id}" x-text="getSwatchText(182, item.id) + ' uds.'"></span> 7477 </div> 7478 <div class="w-1/3 px-0 text-center"> 7479 <span class="inline-block font-medium text-sm line-through text-gray-medium" x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" x-text="hyva.formatPrice(prices.oldPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 7480 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 7481 </div> 7482 <div class="w-1/3 px-0 text-center"> 7483 <span x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" class="line-through text-gray-medium inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.oldPrice.amount, false, optionConfig.priceFormat)"></span> 7484 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount, false, optionConfig.priceFormat)"></span> 7485 </div> 7486 </div> 7487 </label> 7488 </template> 7489</div> 7490 </template> 7491</div> 7492 </div> 7493 <template x-if="isTooltipVisible()"> 7494 <div class="absolute" :style="getTooltipPosition()"> 7495 <div class="whitespace-nowrap shadow-lg absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-full z-10 p-1.5 -mt-1.5 text-xs text-white bg-black shadow-lg text-center"> 7496 <template x-if="isVisualSwatch(activeTooltipItem.attribute, activeTooltipItem.item)"> 7497 <div class="hidden border shadow-sm border-container" 7498 :style="getTooltipImageStyle(activeTooltipItem.attribute, activeTooltipItem.item)" 7499 ></div> 7500 </template>
7501 <span x-html="getTooltipLabel()"></span> 7502 </div> 7503 <svg xmlns="http://www.w3.org/2000/svg" 7504 viewBox="0 0 9 4.5" 7505 width="9" 7506 height="9" 7507 class="shadow-lg absolute left-1/2 transform -translate-x-1/2 -translate-y-full"> 7508 <path d="M-.025 0L4.5-4.525 9.025 0 4.5 4.525z"/> 7509 </svg> 7510 </div> 7511</template> 7512 </div> 7513 </div> 7514 7515 <div 7516 class="mt-auto" 7517 x-data="{showAddToCartButton: true, productId: '142' }" 7518 :class="{'': showAddToCartButton, '': !showAddToCartButton}" 7519 @list-configurable-selection-changed.window="if(productId === $event.detail.productId) showAddToCartButton = $event.detail.saleable"> 7520 <div x-cloak x-show="!showAddToCartButton"> 7521 <a class="btn bg-gray w-full shadow rounded" href="https://www.serrats.com/es_es/bonito-del-norte-oliva-virgen-extra-ecologico-212g"> 7522 <span>No está disponible</span> 7523 </a> 7524 </div> 7525 <button class="btn btn-dark-fill shadow w-full" 7526 x-show="showAddToCartButton" 7527 aria-label="Añadir al carrito"> 7528 <span class="">Añadir al carrito</span> 7529 </button> 7530 </div> 7531 </div> 7532 </div> 7533 </div> 7534 7535 </form> 7536 <form method="post" 7537 action="https://www.serrats.com/es_es/checkout/cart/add/uenc/%25uenc%25/product/143/" 7538 class="item product product-item product_addtocart_form bg-product-bg-color border-product-bg-border attribute_set_id_4 group/card flex flex-1 flex-col transition-shadow duration-300 ease-in shadow-[0px_0px_20px_rgba(0,0,0,0.05)] hover:shadow-[0px_0px_20px_rgba(0,0,0,0.1)]" 7539 x-data="{activeItem: false, activeDetails: false}" 7540 @mouseenter="activeItem = true" 7541 @mouseleave="activeItem = false" 7542 :class="{'bg-product-bg-hover-color border-product-bg-hover-border no-hover': activeItem }" 7543> 7544 <div x-data="{ formKey: '' }" x-init="formKey = hyva.getFormKey()"> 7545 <input name="form_key" type="hidden" :value="formKey"/> 7546</div> 7547 <input type="hidden" name="product" value="143"/> 7548 <div class="container-card flex flex-col h-full"> 7549 <div class="relative"> 7550 7551<div class="relative"> 7552<div class="grid grid-cols-2 gap-2 p-2 absolute right-0 left-0 bottom-0 top-0 pointer-events-none"> 7553 </div> 7554 7555<a class="relative product photo product-item-photo block overflow-hidden" href="https://www.serrats.com/es_es/bonito-del-norte-aceite-de-oliva-y-pimenton-de-espelette" 7556 mcclane-data="category-item"> 7557 <img x-data="showHoverImage()" 7558 @update-gallery-143.window="$root.src = $event.detail" 7559 class="h-full object-contain w-full md:group-hover/card:scale-[1.05] transition-all" 7560 @mouseover="onHover()" 7561 @mouseleave="onLeave()" 7562 loading="lazy" 7563 alt="Bonito del Norte en aceite de oliva con pimentón de Espelette. Frasco 190g." 7564 title="Bonito del Norte en aceite de oliva con pimentón de Espelette. Frasco 190g." 7565 src="https://www.serrats.com/media/catalog/product/m/i/miniatura_rt212_bnesplt.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 7566 src-hover="" 7567 src-leave="https://www.serrats.com/media/catalog/product/m/i/miniatura_rt212_bnesplt.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 7568 width="420" 7569 height="420" 7570/> 7571 7572 7573</a> 7574</div> 7575 </div> 7576 <div class="flex flex-col pt-3 p-2.5 lg:p-4 gap-2 h-full"> 7577 <div class="flex flex-col gap-2 lg:gap-3.5"> 7578 </div> 7579 <div class="flex justify-between"> 7580 <div class="flex"> 7581 7582<a class="product-item-link" href="https://www.serrats.com/es_es/bonito-del-norte-aceite-de-oliva-y-pimenton-de-espelette" 7583 > 7584 <span class="product-card-title md:product-card-title-desktop text-product-card-title line-clamp-3 min-h-[3.5em]"> 7585 Bonito del Norte en aceite de oliva con pimentón de Espelette. Frasco 190g.</span> 7586</a> 7587 </div> 7588 <div class="flex"> 7589 </div> 7590 </div> 7591 <div class="flex flex-col gap-3 h-full"> 7592 7593 <span class="line-clamp-1 text-sm text-gray-dark">Frasco de Cristal</span> 7594 <div class=""> 7595
7595<script> 7596 function initConfigurableSwatchOptions_143() { 7597 const configurableOptionsComponent = initConfigurableOptions( 7598 '143', 7599 {"attributes":{"182":{"id":"182","code":"uds_caja","label":"Uds Caja","options":[{"id":"41","label":"6","products":["77"],"type":"0","value":"6"},{"id":"43","label":"12","products":["76"],"type":"0","value":"12"}],"position":"0"}},"template":"<%- data.price %>\u00a0\u20ac","currencyFormat":"%s\u00a0\u20ac","optionPrices":{"77":{"baseOldPrice":{"amount":31.818180818182},"oldPrice":{"amount":35},"basePrice":{"amount":31.818180818182},"finalPrice":{"amount":35},"tierPrices":[],"msrpPrice":{"amount":0}},"76":{"baseOldPrice":{"amount":62.727271727273},"oldPrice":{"amount":69},"basePrice":{"amount":62.727271727273},"finalPrice":{"amount":69},"tierPrices":[],"msrpPrice":{"amount":0}}},"priceFormat":{"pattern":"%s\u00a0\u20ac","precision":2,"requiredPrecision":2,"decimalSymbol":",","groupSymbol":".","groupLength":3,"integerRequired":false},"prices":{"baseOldPrice":{"amount":31.818180818182},"oldPrice":{"amount":35},"basePrice":{"amount":31.818180818182},"finalPrice":{"amount":35}},"productId":"143","chooseText":"Elegir una opci\u00f3n...","images":[],"index":{"77":{"182":"41"},"76":{"182":"43"}},"salable":[],"canDisplayShowOutOfStockStatus":false,"saleable":{"77":true,"76":true},"preselect_sku_child":"SERRATS_RT212_BNO_Esp_6","childProducts":{"SERRATS_RT212_BNO_Esp_6":"77","SERRATS_RT212_BNO_Esp_12":"76"}} ); 7600 const swatchOptionsComponent = initSwatchOptions({"182":{"41":{"type":"0","value":"6","label":"6"},"43":{"type":"0","value":"12","label":"12"},"additional_data":"{\"swatch_input_type\":\"text\",\"update_product_preview_image\":\"0\",\"use_product_image_for_swatch\":0}"}}); 7601 7602 if (typeof window.configurableOptionsInitialized === "undefined") { 7603 window.configurableOptionsInitialized = []; 7604 } 7605 7606 return Object.assign( 7607 configurableOptionsComponent, 7608 swatchOptionsComponent, 7609 { 7610 mediaCallback: "https\u003A\u002F\u002Fwww.serrats.com\u002Fes_es\u002Fswatches\u002Fajax\u002Fmedia\u002F", 7611 changeOption(optionId, value, skipUpdateGallery) { 7612 this.selectedValues[optionId] = value; 7613 this.findSimpleIndex(); 7614 this.findAllowedAttributeOptions(); 7615 this.updatePrices(); 7616 !skipUpdateGallery && this.updateGallery(); 7617 7618 window.dispatchEvent( 7619 new CustomEvent( 7620 'list-configurable-selection-changed', 7621 { 7622 detail: { 7623 productId: this.productId, 7624 optionId, 7625 value, 7626 productIndex: this.productIndex, 7627 selectedValues: this.selectedValues, 7628 saleable: this.optionConfig.saleable[this.productIndex] 7629 } 7630 } 7631 ) 7632 ); 7633 }, 7634 syncConfigurableSwatchOptions(event) { 7635 let product = event.detail; 7636 if (product.productId !== this.productId) return; 7637 if (product.productIndex !== this.productIndex) this.productIndex = product.productIndex 7638 if (product.selectedValues !== this.selectedValues) this.selectedValues = product.selectedValues 7639 }, 7640 resetSwatches() { 7641 let featured = []; 7642 this.selectedValues = featured; 7643 }, 7644 updateGallery() { 7645 let configSkipGalleryUpdate = 0; 7646 7647 if (!this.productIndex || configSkipGalleryUpdate ) { 7648 return; 7649 } 7650 7651 fetch(`${this.mediaCallback}?product_id=${this.productIndex}`, { 7652 method: 'GET', 7653 headers: { 7654 'Content-Type': 'application/json', 7655 'X-Requested-With': 'XMLHttpRequest' 7656 } 7657 } 7658 ).then(response => { 7659 return response.json() 7660 } 7661 ).then(data => { 7662 if (data.errors) { 7663 // non critical failure only console logged 7664 console.warn(data.errors); 7665 } else { 7666 const image = data && data.medium; 7667 7668 image && window.dispatchEvent( 7669 new CustomEvent( 7670 "update-gallery-143", 7671 {detail: image} 7672 ) 7673 ); 7674 } 7675 }).catch(error => { 7676 console.warn(error) 7677 }); 7678 }, 7679 preselectQuerystringItems() { 7680 // pre-select option like ?size=167 7681 const urlQueryParams = new URLSearchParams(window.location.search.replace('?', '')); 7682 Object.values(this.optionConfig.attributes).map(attribute => { 7683 // Don't update images on load, since PLPs already set the main image to the selected options 7684 const skipUpdateGallery = true; 7685 urlQueryParams.get(attribute.code) && 7686 this.changeOption(attribute.id, urlQueryParams.get(attribute.code), skipUpdateGallery); 7687 }); 7688 }, 7689 mouseDown: false, 7690 startX: 0, 7691 maxScroll: 0, 7692 scrollLeft: null, 7693 slider: null, 7694 attributeIdFeatured: null, 7695 items: [], 7696 limitToScroll: 0, 7697 limitToScrollMobile: 3, 7698 limitToScrollDesktop: 5, 7699 scrollEvents: { 7700 ['@mousedown'](e) { 7701 this.slider = e.target.closest('.snap'); 7702 if (!this.slider) { 7703 return; 7704 } 7705 this.maxScroll = this.slider.scrollWidth - this.slider.offsetWidth; 7706 this.startX = e.pageX - this.slider.offsetLeft; 7707 this.scrollLeft = this.slider.scrollLeft; 7708 this.mouseDown = true; 7709 }, 7710 ['@mouseout.self']() { 7711 this.mouseDown = false;
7712 }, 7713 ['@mouseup']() { 7714 this.mouseDown = false; 7715 }, 7716 ['@mousemove'](e) { 7717 e.preventDefault(); 7718 if (!this.mouseDown) { 7719 return; 7720 } 7721 const x = e.pageX - this.slider.offsetLeft; 7722 const scroll = x - this.startX; 7723 const scrollLeft = this.scrollLeft - scroll; 7724 7725 if (scrollLeft > this.maxScroll) { 7726 this.slider.scrollLeft = this.maxScroll; 7727 return 7728 } 7729 this.slider.scrollLeft = this.scrollLeft - scroll; 7730 }, 7731 ['@onselectstart']() { 7732 return false; 7733 }, 7734 ['@resize.window']() { 7735 this.initShowScrollSwatches(); 7736 }, 7737 ['@tabchange.window']() { 7738 this.initShowScrollSwatches(); 7739 } 7740 }, 7741 clickLeftEvent() { 7742 this.slider = this.$root.querySelector('.snap'); 7743 this.slider.scrollLeft -= this.slider.offsetWidth; 7744 }, 7745 clickRightEvent() { 7746 this.slider = this.$root.querySelector('.snap'); 7747 this.slider.scrollLeft += this.slider.offsetWidth; 7748 }, 7749 setLimitScroll() { 7750 this.limitToScroll = window.innerWidth > 767 ? this.limitToScrollDesktop : this.limitToScrollMobile; 7751 }, 7752 initShowScrollSwatches() { 7753 this.$nextTick(() => { 7754 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
7754der => { 7755 this.items = slider.querySelectorAll(':scope > div:not(.hidden)'); 7756 this.setLimitScroll(); 7757 7758 if (this.limitToScroll > this.items.length) { 7759 this.limitToScroll = this.items.length; 7760 } 7761 7762 let itemLimit = this.items[this.limitToScroll - 1]; 7763 let marginOffset = parseFloat(getComputedStyle(slider.parentElement).marginLeft) + parseFloat(getComputedStyle(slider.parentElement).marginRight); 7764 7765 let widthMax = this.$root.offsetWidth - marginOffset; 7766 let width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 7767 7768 slider.style.width = width + 'px'; 7769 slider.scrollLeft = 0; 7770 7771 while (width > widthMax && this.limitToScroll > 1) { 7772 this.limitToScroll--; 7773 itemLimit = this.items[this.limitToScroll - 1]; 7774 width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 7775 slider.style.width = width + 'px'; 7776 slider.scrollLeft = 0; 7777 } 7778 }); 7779 }); 7780 }, 7781 resizeEvent() { 7782 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
7782der => { 7783 slider.scrollLeft = 0; 7784 }) 7785 }, 7786 contentLoaded(eventData) { 7787 if (typeof window.configurableOptionsInitialized[this.productId] !== "undefined") { 7788 return; 7789 } 7790 7791 this.onGetCartData(eventData); 7792 window.configurableOptionsInitialized[this.productId] = true; 7793 } 7794 } 7795 ); 7796 } 7797</script>
7797 7798 7799 7800<div x-data="initConfigurableSwatchOptions_143()" 7801 x-init="findAllowedAttributeOptions(); initShowSwatchesIntersect();" 7802 @list-configurable-selection-changed.window="syncConfigurableSwatchOptions($event)" 7803 @list-swatches-reset-143.window="resetSwatches()" 7804 @private-content-loaded.window="contentLoaded($event.detail.data)" 7805 @resize.window="resizeEvent()" 7806> 7807 <div class="flex flex-col flex-nowrap gap-y-3"> 7808 7809 7810<div class="flex flex-col swatch-attribute"> 7811 <div class="flex mx-0 serrats-table-header uppercase border-b border-[#d9ddd7]"> 7812 <div class="w-1/3 px-0">Unidades caja</div> 7813 <div class="w-1/3 px-0 text-center">Precio unidad</div> 7814 <div class="w-1/3 px-0 text-center font-semibold"><span>Precio caja</span></div> 7815 </div> 7816 <template x-for="(item, index) in optionConfig.attributes[182].options" :key="item.id"> 7817 <div class="py-2"> 7818 <template x-if="optionIsEnabled(182, item.id)"> 7819 <label 7820 :for="'attribute-option-143-'+item.id" 7821 :mcclane-data="'product-configurable-custom-option-'+item.id" 7822 @touchend.passive="selectedValues[182] ? '' : changeOption(182, item.id)" 7823 class="flex items-center gap-2" 7824 > 7825 <input 7826 :id="'attribute-option-143-'+item.id" 7827 :value="item.id" 7828 name="super_attribute[182]" 7829 type="radio" 7830 class="border-0 focus:border-0 focus:ring-0 inline-block p-0 opacity-0 product-option-value-input absolute" 7831 style="z-index:-1" 7832 x-on:focus="focusLabel(item.id)" 7833 x-on:blur="blurLabel()" 7834 x-on:change="changeOption(182, $event.target.value)" 7835 @list-configurable-selection-changed.window="findAllowedAttributeOptions();" 7836 x-model="selectedValues[182]" 7837 :required="getAllowedAttributeOptions(182).filter(attributeOption => selectedValues[attributeOption]).length === 0" 7838 /> 7839 <div class="flex flex-grow items-center mx-0 cursor-pointer" x-data="{prices: optionConfig.optionPrices[item.availableProductsId[0]]}"> 7840 <div class="w-1/3"> 7841 <span class="inline-block lowercase text-sm serrats-custom-swatch-container flex items-center" :class="{'selected': selectedValues[182] === item.id}" x-text="getSwatchText(182, item.id) + ' uds.'"></span> 7842 </div> 7843 <div class="w-1/3 px-0 text-center"> 7844 <span class="inline-block font-medium text-sm line-through text-gray-medium" x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" x-text="hyva.formatPrice(prices.oldPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 7845 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 7846 </div> 7847 <div class="w-1/3 px-0 text-center"> 7848 <span x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" class="line-through text-gray-medium inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.oldPrice.amount, false, optionConfig.priceFormat)"></span> 7849 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount, false, optionConfig.priceFormat)"></span> 7850 </div> 7851 </div> 7852 </label> 7853 </template> 7854</div> 7855 </template> 7856</div> 7857 </div> 7858 <template x-if="isTooltipVisible()"> 7859 <div class="absolute" :style="getTooltipPosition()"> 7860 <div class="whitespace-nowrap shadow-lg absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-full z-10 p-1.5 -mt-1.5 text-xs text-white bg-black shadow-lg text-center"> 7861 <template x-if="isVisualSwatch(activeTooltipItem.attribute, activeTooltipItem.item)"> 7862 <div class="hidden border shadow-sm border-container" 7863 :style="getTooltipImageStyle(activeTooltipItem.attribute, activeTooltipItem.item)" 7864 ></div> 7865 </template>
7866 <span x-html="getTooltipLabel()"></span> 7867 </div> 7868 <svg xmlns="http://www.w3.org/2000/svg" 7869 viewBox="0 0 9 4.5" 7870 width="9" 7871 height="9" 7872 class="shadow-lg absolute left-1/2 transform -translate-x-1/2 -translate-y-full"> 7873 <path d="M-.025 0L4.5-4.525 9.025 0 4.5 4.525z"/> 7874 </svg> 7875 </div> 7876</template> 7877 </div> 7878 </div> 7879 7880 <div 7881 class="mt-auto" 7882 x-data="{showAddToCartButton: true, productId: '143' }" 7883 :class="{'': showAddToCartButton, '': !showAddToCartButton}" 7884 @list-configurable-selection-changed.window="if(productId === $event.detail.productId) showAddToCartButton = $event.detail.saleable"> 7885 <div x-cloak x-show="!showAddToCartButton"> 7886 <a class="btn bg-gray w-full shadow rounded" href="https://www.serrats.com/es_es/bonito-del-norte-aceite-de-oliva-y-pimenton-de-espelette"> 7887 <span>No está disponible</span> 7888 </a> 7889 </div> 7890 <button class="btn btn-dark-fill shadow w-full" 7891 x-show="showAddToCartButton" 7892 aria-label="Añadir al carrito"> 7893 <span class="">Añadir al carrito</span> 7894 </button> 7895 </div> 7896 </div> 7897 </div> 7898 </div> 7899 7900 </form> 7901 <form method="post" 7902 action="https://www.serrats.com/es_es/checkout/cart/add/uenc/%25uenc%25/product/158/" 7903 class="item product product-item product_addtocart_form bg-product-bg-color border-product-bg-border attribute_set_id_4 group/card flex flex-1 flex-col transition-shadow duration-300 ease-in shadow-[0px_0px_20px_rgba(0,0,0,0.05)] hover:shadow-[0px_0px_20px_rgba(0,0,0,0.1)]" 7904 x-data="{activeItem: false, activeDetails: false}" 7905 @mouseenter="activeItem = true" 7906 @mouseleave="activeItem = false" 7907 :class="{'bg-product-bg-hover-color border-product-bg-hover-border no-hover': activeItem }" 7908> 7909 <div x-data="{ formKey: '' }" x-init="formKey = hyva.getFormKey()"> 7910 <input name="form_key" type="hidden" :value="formKey"/> 7911</div> 7912 <input type="hidden" name="product" value="158"/> 7913 <div class="container-card flex flex-col h-full"> 7914 <div class="relative"> 7915 7916<div class="relative"> 7917<div class="grid grid-cols-2 gap-2 p-2 absolute right-0 left-0 bottom-0 top-0 pointer-events-none"> 7918 </div> 7919 7920<a class="relative product photo product-item-photo block overflow-hidden" href="https://www.serrats.com/es_es/bonito-norte-escabeche" 7921 mcclane-data="category-item"> 7922 <img x-data="showHoverImage()" 7923 @update-gallery-158.window="$root.src = $event.detail" 7924 class="h-full object-contain w-full md:group-hover/card:scale-[1.05] transition-all" 7925 @mouseover="onHover()" 7926 @mouseleave="onLeave()" 7927 loading="lazy" 7928 alt="Bonito del Norte en Escabeche. Frasco 190g." 7929 title="Bonito del Norte en Escabeche. Frasco 190g." 7930 src="https://www.serrats.com/media/catalog/product/m/i/miniatura_rt212_bne.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 7931 src-hover="" 7932 src-leave="https://www.serrats.com/media/catalog/product/m/i/miniatura_rt212_bne.jpg?quality=100&bg-color=255,255,255&fit=bounds&height=420&width=420&canvas=420:420" 7933 width="420" 7934 height="420" 7935/> 7936 7937 7938</a> 7939</div> 7940 </div> 7941 <div class="flex flex-col pt-3 p-2.5 lg:p-4 gap-2 h-full"> 7942 <div class="flex flex-col gap-2 lg:gap-3.5"> 7943 </div> 7944 <div class="flex justify-between"> 7945 <div class="flex"> 7946 7947<a class="product-item-link" href="https://www.serrats.com/es_es/bonito-norte-escabeche" 7948 > 7949 <span class="product-card-title md:product-card-title-desktop text-product-card-title line-clamp-3 min-h-[3.5em]"> 7950 Bonito del Norte en Escabeche. Frasco 190g.</span> 7951</a> 7952 </div> 7953 <div class="flex"> 7954 </div> 7955 </div> 7956 <div class="flex flex-col gap-3 h-full"> 7957 7958 <span class="line-clamp-1 text-sm text-gray-dark">Frasco de Cristal</span> 7959 <div class=""> 7960
7960<script> 7961 function initConfigurableSwatchOptions_158() { 7962 const configurableOptionsComponent = initConfigurableOptions( 7963 '158', 7964 {"attributes":{"182":{"id":"182","code":"uds_caja","label":"Uds Caja","options":[{"id":"41","label":"6","products":["69"],"type":"0","value":"6"},{"id":"43","label":"12","products":["68"],"type":"0","value":"12"}],"position":"0"}},"template":"<%- data.price %>\u00a0\u20ac","currencyFormat":"%s\u00a0\u20ac","optionPrices":{"69":{"baseOldPrice":{"amount":31.818180818182},"oldPrice":{"amount":35},"basePrice":{"amount":31.818180818182},"finalPrice":{"amount":35},"tierPrices":[],"msrpPrice":{"amount":0}},"68":{"baseOldPrice":{"amount":62.727271727273},"oldPrice":{"amount":69},"basePrice":{"amount":62.727271727273},"finalPrice":{"amount":69},"tierPrices":[],"msrpPrice":{"amount":0}}},"priceFormat":{"pattern":"%s\u00a0\u20ac","precision":2,"requiredPrecision":2,"decimalSymbol":",","groupSymbol":".","groupLength":3,"integerRequired":false},"prices":{"baseOldPrice":{"amount":31.818180818182},"oldPrice":{"amount":35},"basePrice":{"amount":31.818180818182},"finalPrice":{"amount":35}},"productId":"158","chooseText":"Elegir una opci\u00f3n...","images":[],"index":{"69":{"182":"41"},"68":{"182":"43"}},"salable":[],"canDisplayShowOutOfStockStatus":false,"saleable":{"69":false,"68":true},"preselect_sku_child":"SERRATS_RT212_BNE_12","childProducts":{"SERRATS_RT212_BNE_6":"69","SERRATS_RT212_BNE_12":"68"}} ); 7965 const swatchOptionsComponent = initSwatchOptions({"182":{"41":{"type":"0","value":"6","label":"6"},"43":{"type":"0","value":"12","label":"12"},"additional_data":"{\"swatch_input_type\":\"text\",\"update_product_preview_image\":\"0\",\"use_product_image_for_swatch\":0}"}}); 7966 7967 if (typeof window.configurableOptionsInitialized === "undefined") { 7968 window.configurableOptionsInitialized = []; 7969 } 7970 7971 return Object.assign( 7972 configurableOptionsComponent, 7973 swatchOptionsComponent, 7974 { 7975 mediaCallback: "https\u003A\u002F\u002Fwww.serrats.com\u002Fes_es\u002Fswatches\u002Fajax\u002Fmedia\u002F", 7976 changeOption(optionId, value, skipUpdateGallery) { 7977 this.selectedValues[optionId] = value; 7978 this.findSimpleIndex(); 7979 this.findAllowedAttributeOptions(); 7980 this.updatePrices(); 7981 !skipUpdateGallery && this.updateGallery(); 7982 7983 window.dispatchEvent( 7984 new CustomEvent( 7985 'list-configurable-selection-changed', 7986 { 7987 detail: { 7988 productId: this.productId, 7989 optionId, 7990 value, 7991 productIndex: this.productIndex, 7992 selectedValues: this.selectedValues, 7993 saleable: this.optionConfig.saleable[this.productIndex] 7994 } 7995 } 7996 ) 7997 ); 7998 }, 7999 syncConfigurableSwatchOptions(event) { 8000 let product = event.detail; 8001 if (product.productId !== this.productId) return; 8002 if (product.productIndex !== this.productIndex) this.productIndex = product.productIndex 8003 if (product.selectedValues !== this.selectedValues) this.selectedValues = product.selectedValues 8004 }, 8005 resetSwatches() { 8006 let featured = []; 8007 this.selectedValues = featured; 8008 }, 8009 updateGallery() { 8010 let configSkipGalleryUpdate = 0; 8011 8012 if (!this.productIndex || configSkipGalleryUpdate ) { 8013 return; 8014 } 8015 8016 fetch(`${this.mediaCallback}?product_id=${this.productIndex}`, { 8017 method: 'GET', 8018 headers: { 8019 'Content-Type': 'application/json', 8020 'X-Requested-With': 'XMLHttpRequest' 8021 } 8022 } 8023 ).then(response => { 8024 return response.json() 8025 } 8026 ).then(data => { 8027 if (data.errors) { 8028 // non critical failure only console logged 8029 console.warn(data.errors); 8030 } else { 8031 const image = data && data.medium; 8032 8033 image && window.dispatchEvent( 8034 new CustomEvent( 8035 "update-gallery-158", 8036 {detail: image} 8037 ) 8038 ); 8039 } 8040 }).catch(error => { 8041 console.warn(error) 8042 }); 8043 }, 8044 preselectQuerystringItems() { 8045 // pre-select option like ?size=167 8046 const urlQueryParams = new URLSearchParams(window.location.search.replace('?', '')); 8047 Object.values(this.optionConfig.attributes).map(attribute => { 8048 // Don't update images on load, since PLPs already set the main image to the selected options 8049 const skipUpdateGallery = true; 8050 urlQueryParams.get(attribute.code) && 8051 this.changeOption(attribute.id, urlQueryParams.get(attribute.code), skipUpdateGallery); 8052 }); 8053 }, 8054 mouseDown: false, 8055 startX: 0, 8056 maxScroll: 0, 8057 scrollLeft: null, 8058 slider: null, 8059 attributeIdFeatured: null, 8060 items: [], 8061 limitToScroll: 0, 8062 limitToScrollMobile: 3, 8063 limitToScrollDesktop: 5, 8064 scrollEvents: { 8065 ['@mousedown'](e) { 8066 this.slider = e.target.closest('.snap'); 8067 if (!this.slider) { 8068 return; 8069 } 8070 this.maxScroll = this.slider.scrollWidth - this.slider.offsetWidth; 8071 this.startX = e.pageX - this.slider.offsetLeft; 8072 this.scrollLeft = this.slider.scrollLeft; 8073 this.mouseDown = true; 8074 }, 8075 ['@mouseout.self']() { 8076 this.mouseDown = false;
8077 }, 8078 ['@mouseup']() { 8079 this.mouseDown = false; 8080 }, 8081 ['@mousemove'](e) { 8082 e.preventDefault(); 8083 if (!this.mouseDown) { 8084 return; 8085 } 8086 const x = e.pageX - this.slider.offsetLeft; 8087 const scroll = x - this.startX; 8088 const scrollLeft = this.scrollLeft - scroll; 8089 8090 if (scrollLeft > this.maxScroll) { 8091 this.slider.scrollLeft = this.maxScroll; 8092 return 8093 } 8094 this.slider.scrollLeft = this.scrollLeft - scroll; 8095 }, 8096 ['@onselectstart']() { 8097 return false; 8098 }, 8099 ['@resize.window']() { 8100 this.initShowScrollSwatches(); 8101 }, 8102 ['@tabchange.window']() { 8103 this.initShowScrollSwatches(); 8104 } 8105 }, 8106 clickLeftEvent() { 8107 this.slider = this.$root.querySelector('.snap'); 8108 this.slider.scrollLeft -= this.slider.offsetWidth; 8109 }, 8110 clickRightEvent() { 8111 this.slider = this.$root.querySelector('.snap'); 8112 this.slider.scrollLeft += this.slider.offsetWidth; 8113 }, 8114 setLimitScroll() { 8115 this.limitToScroll = window.innerWidth > 767 ? this.limitToScrollDesktop : this.limitToScrollMobile; 8116 }, 8117 initShowScrollSwatches() { 8118 this.$nextTick(() => { 8119 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
8119der => { 8120 this.items = slider.querySelectorAll(':scope > div:not(.hidden)'); 8121 this.setLimitScroll(); 8122 8123 if (this.limitToScroll > this.items.length) { 8124 this.limitToScroll = this.items.length; 8125 } 8126 8127 let itemLimit = this.items[this.limitToScroll - 1]; 8128 let marginOffset = parseFloat(getComputedStyle(slider.parentElement).marginLeft) + parseFloat(getComputedStyle(slider.parentElement).marginRight); 8129 8130 let widthMax = this.$root.offsetWidth - marginOffset; 8131 let width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 8132 8133 slider.style.width = width + 'px'; 8134 slider.scrollLeft = 0; 8135 8136 while (width > widthMax && this.limitToScroll > 1) { 8137 this.limitToScroll--; 8138 itemLimit = this.items[this.limitToScroll - 1]; 8139 width = (this.limitToScroll * itemLimit.offsetWidth) + (parseFloat(getComputedStyle(slider).columnGap.replace(/[^\d.-]/g, '')) * (this.limitToScroll - 1)); 8140 slider.style.width = width + 'px'; 8141 slider.scrollLeft = 0; 8142 } 8143 }); 8144 }); 8145 }, 8146 resizeEvent() { 8147 Array.from(this.$root.querySelectorAll('.snap')).forEach(sli
8147der => { 8148 slider.scrollLeft = 0; 8149 }) 8150 }, 8151 contentLoaded(eventData) { 8152 if (typeof window.configurableOptionsInitialized[this.productId] !== "undefined") { 8153 return; 8154 } 8155 8156 this.onGetCartData(eventData); 8157 window.configurableOptionsInitialized[this.productId] = true; 8158 } 8159 } 8160 ); 8161 } 8162</script>
8162 8163 8164 8165<div x-data="initConfigurableSwatchOptions_158()" 8166 x-init="findAllowedAttributeOptions(); initShowSwatchesIntersect();" 8167 @list-configurable-selection-changed.window="syncConfigurableSwatchOptions($event)" 8168 @list-swatches-reset-158.window="resetSwatches()" 8169 @private-content-loaded.window="contentLoaded($event.detail.data)" 8170 @resize.window="resizeEvent()" 8171> 8172 <div class="flex flex-col flex-nowrap gap-y-3"> 8173 8174 8175<div class="flex flex-col swatch-attribute"> 8176 <div class="flex mx-0 serrats-table-header uppercase border-b border-[#d9ddd7]"> 8177 <div class="w-1/3 px-0">Unidades caja</div> 8178 <div class="w-1/3 px-0 text-center">Precio unidad</div> 8179 <div class="w-1/3 px-0 text-center font-semibold"><span>Precio caja</span></div> 8180 </div> 8181 <template x-for="(item, index) in optionConfig.attributes[182].options" :key="item.id"> 8182 <div class="py-2"> 8183 <template x-if="optionIsEnabled(182, item.id)"> 8184 <label 8185 :for="'attribute-option-158-'+item.id" 8186 :mcclane-data="'product-configurable-custom-option-'+item.id" 8187 @touchend.passive="selectedValues[182] ? '' : changeOption(182, item.id)" 8188 class="flex items-center gap-2" 8189 > 8190 <input 8191 :id="'attribute-option-158-'+item.id" 8192 :value="item.id" 8193 name="super_attribute[182]" 8194 type="radio" 8195 class="border-0 focus:border-0 focus:ring-0 inline-block p-0 opacity-0 product-option-value-input absolute" 8196 style="z-index:-1" 8197 x-on:focus="focusLabel(item.id)" 8198 x-on:blur="blurLabel()" 8199 x-on:change="changeOption(182, $event.target.value)" 8200 @list-configurable-selection-changed.window="findAllowedAttributeOptions();" 8201 x-model="selectedValues[182]" 8202 :required="getAllowedAttributeOptions(182).filter(attributeOption => selectedValues[attributeOption]).length === 0" 8203 /> 8204 <div class="flex flex-grow items-center mx-0 cursor-pointer" x-data="{prices: optionConfig.optionPrices[item.availableProductsId[0]]}"> 8205 <div class="w-1/3"> 8206 <span class="inline-block lowercase text-sm serrats-custom-swatch-container flex items-center" :class="{'selected': selectedValues[182] === item.id}" x-text="getSwatchText(182, item.id) + ' uds.'"></span> 8207 </div> 8208 <div class="w-1/3 px-0 text-center"> 8209 <span class="inline-block font-medium text-sm line-through text-gray-medium" x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" x-text="hyva.formatPrice(prices.oldPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 8210 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount / getSwatchText(182, item.id), false, optionConfig.priceFormat)"></span> 8211 </div> 8212 <div class="w-1/3 px-0 text-center"> 8213 <span x-cloak x-show="prices.finalPrice.amount !== prices.oldPrice.amount" class="line-through text-gray-medium inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.oldPrice.amount, false, optionConfig.priceFormat)"></span> 8214 <span class="inline-block font-medium text-sm text-[#151515]" x-text="hyva.formatPrice(prices.finalPrice.amount, false, optionConfig.priceFormat)"></span> 8215 </div> 8216 </div> 8217 </label> 8218 </template> 8219</div> 8220 </template> 8221</div> 8222 </div> 8223 <template x-if="isTooltipVisible()"> 8224 <div class="absolute" :style="getTooltipPosition()"> 8225 <div class="whitespace-nowrap shadow-lg absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-full z-10 p-1.5 -mt-1.5 text-xs text-white bg-black shadow-lg text-center"> 8226 <template x-if="isVisualSwatch(activeTooltipItem.attribute, activeTooltipItem.item)"> 8227 <div class="hidden border shadow-sm border-container" 8228 :style="getTooltipImageStyle(activeTooltipItem.attribute, activeTooltipItem.item)" 8229 ></div> 8230 </template>
8231 <span x-html="getTooltipLabel()"></span> 8232 </div> 8233 <svg xmlns="http://www.w3.org/2000/svg" 8234 viewBox="0 0 9 4.5" 8235 width="9" 8236 height="9" 8237 class="shadow-lg absolute left-1/2 transform -translate-x-1/2 -translate-y-full"> 8238 <path d="M-.025 0L4.5-4.525 9.025 0 4.5 4.525z"/> 8239 </svg> 8240 </div> 8241</template> 8242 </div> 8243 </div> 8244 8245 <div 8246 class="mt-auto" 8247 x-data="{showAddToCartButton: true, productId: '158' }" 8248 :class="{'': showAddToCartButton, '': !showAddToCartButton}" 8249 @list-configurable-selection-changed.window="if(productId === $event.detail.productId) showAddToCartButton = $event.detail.saleable"> 8250 <div x-cloak x-show="!showAddToCartButton"> 8251 <a class="btn bg-gray w-full shadow rounded" href="https://www.serrats.com/es_es/bonito-norte-escabeche"> 8252 <span>No está disponible</span> 8253 </a> 8254 </div> 8255 <button class="btn btn-dark-fill shadow w-full" 8256 x-show="showAddToCartButton" 8257 aria-label="Añadir al carrito"> 8258 <span class="">Añadir al carrito</span> 8259 </button> 8260 </div> 8261 </div> 8262 </div> 8263 </div> 8264 8265 </form> 8266 </div> 8267 <div class="hidden" id="datalayer_items_6ab591821caf1"> 8268
8268<script> 8269 window.dataLayerProducts_6ab591821caf1 = []; 8270 function productListDataLayerManager(eventData) { 8271 return { 8272 impressionItemIndex: 1, 8273 dataLayerProducts: [], 8274 /** 8275 * Track Data Layer Event. 8276 * @param event 8277 */ 8278 trackDatalayerEvent(event) { 8279 window.dispatchEvent( 8280 new CustomEvent('datalayer-event', { detail: { 8281 ecommerce: null 8282 } 8283 }) 8284 ); 8285 8286 window.dispatchEvent( 8287 new CustomEvent('datalayer-event', { detail: event }) 8288 ); 8289 }, 8290 /** 8291 * Track Product Impressions. 8292 */ 8293 trackProductImpressions(impressions) { 8294 let container = document.getElementById('datalayer_items_6ab591821caf1').closest('.products'); 8295 8296 const observer = new IntersectionObserver((entries, observer) => { 8297 entries.forEach(entry => { 8298 if (entry.isIntersecting) { 8299 this.trackDatalayerEvent({ 8300 event: 'view_item_list', 8301 ecommerce: { 8302 ...eventData, 8303 items: impressions 8304 } 8305 }); 8306 observer.unobserve(entry.target); 8307 } 8308 }); 8309 }, { 8310 threshold: 0.0 }); 8311 8312 observer.observe(container); 8313 }, 8314 /** 8315 * Track Product Click. 8316 */ 8317 trackProductClick(product) { 8318 this.trackDatalayerEvent({ 8319 event: 'select_item', 8320 ecommerce: { 8321 ...eventData, 8322 items: [ product ] 8323 } 8324 }); 8325 }, 8326 addProductsToDatalayer(dataLayerProducts, forward = true) { 8327 let impressions = []; 8328 const self = this; 8329 8330 Array.from(dataLayerProducts).forEach((dataLayerProduct) => { 8331 dataLayerProduct.index = self.impressionItemIndex; 8332 impressions.push(dataLayerProduct); 8333 self.impressionItemIndex++; 8334 }); 8335 this.trackProductImpressions(impressions); 8336 8337 if (forward) { 8338 this.dataLayerProducts = this.dataLayerProducts.concat(impressions); 8339 } else { 8340 this.dataLayerProducts = impressions.concat(this.dataLayerProducts); 8341 } 8342 }, 8343 setProductClickEvents() { 8344 /** 8345 * TODO: Move to Magento_Catalog/templates/product/list/item.phtml 8346 */ 8347 let productLinks = []; 8348 try { 8349 productLinks = document.getElementById('datalayer_items_6ab591821caf1').closest('.products').querySelectorAll('.product-item a'); 8350 } catch (e) { 8351 console.log(e); 8352 } 8353 8354 let self = this; 8355 8356 productLinks.forEach(function(productLink) { 8357 //Remove previous event listeners before assign new 8358 let productLinkClone = productLink.cloneNode(true); 8359 productLink.replaceWith(productLinkClone); 8360 productLinkClone.addEventListener('click', self.productClickEvent.bind(self)); 8361 }); 8362 }, 8363 productClickEvent(event) { 8364 let product = event.target.closest('.product-item'); 8365 if (!product) return; 8366 let products = document.getElementById('datalayer_items_6ab591821caf1').closest('.products').querySelectorAll('.product-item'); 8367 let index = Array.from(products).indexOf(product); 8368 if (index === undefined) return; 8369 8370 let dataLayerProduct = this.dataLayerProducts[index]; 8371 dataLayerProduct && this.trackProductClick(dataLayerProduct); 8372 } 8373 } 8374 } 8375 8376 if (typeof window.productListDataLayer_6ab591821caf1 === 'undefined') { 8377 window.productListDataLayer_6ab591821caf1 = productListDataLayerManager( 8378 {"item_list_name":"Category list comprar-bonito-del-norte","item_list_id":"category_list_comprar_bonito_del_norte"} ); 8379 } 8380 8381 window.addEventListener('ecommerce-datalayer-ready', () => { 8382 window.productListDataLayer_6ab591821caf1.addProductsToDatalayer(window.dataLayerProducts_6ab591821caf1); 8383 window.productListDataLayer_6ab591821caf1.setProductClickEvents(); 8384 }); 8385 8386 window.addEventListener('infinite-scroll-page-loaded', (event) => { 8387 if (typeof event.detail.doc == "undefined" || 8388 typeof event.detail.forward == "undefined") { 8389 return; 8390 } 8391 8392 let loadedDoc = event.detail.doc; 8393 let forward = event.detail.forward; 8394 8395 let dataLayerScripts = loadedDoc.querySelectorAll("#dataLayerProducts script"); 8396 if (dataLayerScripts.length === 0) { 8397 return; 8398 } 8399
8400 Array.from(dataLayerScripts).forEach((dataLayerScript) => { 8401 let scriptElement = document.createElement('SCRIPT'); 8402 let uniqueId = dataLayerScript.getAttribute('data-uniqueid'); 8403 scriptElement.type = 'text/javascript'; 8404 scriptElement.innerHTML = dataLayerScript.innerHTML; 8405 document.head.appendChild(scriptElement); 8406 window.productListDataLayer_6ab591821caf1.addProductsToDatalayer(window['dataLayerProducts_' + uniqueId], forward); 8407 window.productListDataLayer_6ab591821caf1.setProductClickEvents(); 8408 }); 8409 }); 8410 </script>
8410 8411 <div id="dataLayerProducts"> 8412
8412<script data-uniqueid="6ab591821caf1"> 8413 window.dataLayerProducts_6ab591821caf1 = [{"index":1,"item_list_name":"Category list comprar-bonito-del-norte","item_list_id":"category_list_comprar_bonito_del_norte","item_name":"bonito_del_norte_en_aceite_de_oliva_la_mas_tipica_lata_115g","item_id":"SERRATS_RO120_BNO","price":89,"item_category":"comprar-bonito-del-norte","item_category2":"comprar-bonito-del-norte-tarro-cristal","item_category3":"comprar-bonito-del-norte-en-aceite-de-oliva","quantity":1,"discount":0},{"index":2,"item_list_name":"Category list comprar-bonito-del-norte","item_list_id":"category_list_comprar_bonito_del_norte","item_name":"bonito_del_norte_al_natural_lata_115g","item_id":"SERRATS_RO120_BNN","price":87,"item_category":"comprar-conservas-al-natural","quantity":1,"discount":0},{"index":3,"item_list_name":"Category list comprar-bonito-del-norte","item_list_id":"category_list_comprar_bonito_del_norte","item_name":"bonito_del_norte_en_aceite_de_oliva_lata_112g","item_id":"SERRATS_OL120_BNO","price":44,"item_category":"comprar-bonito-del-norte","item_category2":"comprar-bonito-del-norte-tarro-cristal","item_category3":"comprar-bonito-del-norte-en-aceite-de-oliva","quantity":1,"discount":0},{"index":4,"item_list_name":"Category list comprar-bonito-del-norte","item_list_id":"category_list_comprar_bonito_del_norte","item_name":"bonito_del_norte_en_aceite_de_oliva_virgen_ecologico_lata_112g","item_id":"SERRATS_OL120_BNO_ECO","price":46,"item_category":"comprar-bonito-del-norte","item_category2":"comprar-bonito-del-norte-tarro-cristal","item_category3":"comprar-bonito-del-norte-en-aceite-de-oliva","quantity":1,"discount":0},{"index":5,"item_list_name":"Category list comprar-bonito-del-norte","item_list_id":"category_list_comprar_bonito_del_norte","item_name":"bonito_del_norte_en_aceite_de_oliva_bajo_en_sal_lata_112g","item_id":"SERRATS_OL120_BNO_BajoSal","price":44,"item_category":"comprar-bonito-del-norte","item_category2":"comprar-bonito-del-norte-tarro-cristal","item_category3":"comprar-bonito-del-norte-en-aceite-de-oliva","quantity":1,"discount":0},{"index":6,"item_list_name":"Category list comprar-bonito-del-norte","item_list_id":"category_list_comprar_bonito_del_norte","item_name":"bonito_del_norte_en_escabeche_lata_112g","item_id":"SERRATS_OL120_BNE","price":44,"item_category":"comprar-bonito-del-norte","item_category2":"comprar-bonito-del-norte-en-escabeche","quantity":1,"discount":0},{"index":7,"item_list_name":"Category list comprar-bonito-del-norte","item_list_id":"category_list_comprar_bonito_del_norte","item_name":"bonito_del_norte_en_salsa_lata_112g","item_id":"SERRATS_OL120_BNS","price":44,"item_category":"comprar-bonito-del-norte","item_category2":"comprar-bonito-del-norte-en-salsa","quantity":1,"discount":0},{"index":8,"item_list_name":"Category list comprar-bonito-del-norte","item_list_id":"category_list_comprar_bonito_del_norte","item_name":"bonito_del_norte_en_aceite_de_oliva_frasco_190g","item_id":"SERRATS_RT212_BNO","price":35,"item_category":"comprar-bonito-del-norte","item_category2":"comprar-bonito-del-norte-tarro-cristal","quantity":1,"discount":0},{"index":9,"item_list_name":"Category list comprar-bonito-del-norte","item_list_id":"category_list_comprar_bonito_del_norte","item_name":"bonito_del_norte_al_natural_frasco_190g","item_id":"SERRATS_RT212_BNN","price":35,"item_category":"comprar-conservas-al-natural","quantity":1,"discount":0},{"index":10,"item_list_name":"Category list comprar-bonito-del-norte","item_list_id":"category_list_comprar_bonito_del_norte","item_name":"bonito_del_norte_en_aceite_de_oliva_virgen_ecologico_frasco_190g","item_id":"SERRATS_RT212_BNO_ECO","price":39,"item_category":"comprar-bonito-del-norte","item_category2":"comprar-bonito-del-norte-tarro-cristal","quantity":1,"discount":0},{"index":11,"item_list_name":"Category list comprar-bonito-del-norte","item_list_id":"category_list_comprar_bonito_del_norte","item_name":"bonito_del_norte_en_aceite_de_oliva_con_pimenton_de_espelette_frasco_190g","item_id":"SERRATS_RT212_BNO_Esp","price":35,"item_category":"comprar-bonito-del-norte","item_category2":"comprar-bonito-del-norte-tarro-cristal","quantity":1,"discount":0},{"index":12,"item_list_name":"Category list comprar-bonito-del-norte","item_list_id":"category_list_comprar_bonito_del_norte","item_name":"bonito_del_norte_en_escabeche_frasco_190g","
8413item_id":"SERRATS_RT212_BNE","price":35,"item_category":"comprar-bonito-del-norte","item_category2":"comprar-bonito-del-norte-tarro-cristal","quantity":1,"discount":0}]; 8414 </script>
8414 8415 </div> 8416</div> 8417 </div> 8418
8418<script type="application/ld+json" id="itemlist-schema"> 8419 {"@context":"https://schema.org","@type":"ItemList","itemListElement":[{"@type":"ListItem","position":1,"name":"Bonito del Norte en aceite de oliva. ¡La más TÃPICA! Lata 115g.","url":"https://www.serrats.com/es_es/bonito-del-norte-aceite-oliva-tipica-120g"},{"@type":"ListItem","position":2,"name":"Bonito del Norte al natural. Lata 115g.","url":"https://www.serrats.com/es_es/bonito-norte-al-natural-lata-115g"},{"@type":"ListItem","position":3,"name":"Bonito del Norte en aceite de oliva. Lata 112g.","url":"https://www.serrats.com/es_es/bonito-del-norte-oliva-120g-25u"},{"@type":"ListItem","position":4,"name":"Bonito del Norte en aceite de oliva virgen ECOLÃGICO. Lata 112g.","url":"https://www.serrats.com/es_es/bonito-del-norte-oliva-virgen-ecologico-120g"},{"@type":"ListItem","position":5,"name":"Bonito del Norte en aceite de oliva BAJO EN SAL. Lata 112g.","url":"https://www.serrats.com/es_es/bonito-del-norte-oliva-bajo-en-sal-lata-120g"},{"@type":"ListItem","position":6,"name":"Bonito del Norte en Escabeche. Lata 112g.","url":"https://www.serrats.com/es_es/bonito-del-norte-escabeche-lata-120g"},{"@type":"ListItem","position":7,"name":"Bonito del Norte en Salsa. Lata 112g.","url":"https://www.serrats.com/es_es/bonito-del-norte-salsa-lata-120g"},{"@type":"ListItem","position":8,"name":"Bonito del Norte en aceite de oliva. Frasco 190g.","url":"https://www.serrats.com/es_es/bonito-del-norte-oliva-frasco-212g"},{"@type":"ListItem","position":9,"name":"Bonito del Norte al natural. Frasco 190g.","url":"https://www.serrats.com/es_es/bonito-norte-al-natural"},{"@type":"ListItem","position":10,"name":"Bonito del Norte en aceite de oliva virgen ECOLÃGICO. Frasco 190g.","url":"https://www.serrats.com/es_es/bonito-del-norte-oliva-virgen-extra-ecologico-212g"},{"@type":"ListItem","position":11,"name":"Bonito del Norte en aceite de oliva con pimentón de Espelette. Frasco 190g.","url":"https://www.serrats.com/es_es/bonito-del-norte-aceite-de-oliva-y-pimenton-de-espelette"},{"@type":"ListItem","position":12,"name":"Bonito del Norte en Escabeche. Frasco 190g.","url":"https://www.serrats.com/es_es/bonito-norte-escabeche"}],"name":"Bonito del Norte"} </script>
8419 8420
8420<script> 8421 (function () { 8422 'use strict'; 8423 window.addEventListener('infinite-scroll-page-loaded', function () { 8424 var schemaEl = document.getElementById('itemlist-schema'); 8425 if (!schemaEl) return; 8426 var container = document.querySelector('.products.wrapper'); 8427 if (!container) return; 8428 var links = container.querySelectorAll('.product-item-link'); 8429 if (!links.length) return; 8430 try { 8431 var existing = JSON.parse(schemaEl.textContent); 8432 var items = []; 8433 links.forEach(function (link, i) { 8434 items.push({ 8435 '@type': 'ListItem', 8436 'position': i + 1, 8437 'name': link.textContent.trim(), 8438 'url': link.href 8439 }); 8440 }); 8441 existing.itemListElement = items; 8442 schemaEl.textContent = JSON.stringify(existing); 8443 } catch (e) { 8444 // Leave existing schema intact 8445 } 8446 }); 8447 }()); 8448 </script>
8448 8449 8450 <div class="mb-4 md:mb-8"> 8451 8452 <div class="pages mt-5"> 8453 <strong class="sr-only label pages-label">Página</strong> 8454 <ul class="flex flex-row justify-center items-center gap-1.5" aria-label="Página"> 8455 <li class="mr-auto relative text-sm text-black item pages-item-previous w-6 md:w-24"> 8456 </li> 8457 8458 8459 <li> 8460 <ul class="flex flex-row flex-no-wrap gap-1.5"> 8461 <li class="relative item focus:outline-none pager-step pager-step-active"> 8462 <strong class="cursor-default page"> 8463 <span class="sr-only label"> 8464 Actualmente estás leyendo página </span> 8465 <span>1</span> 8466 </strong> 8467 </li> 8468 <li class="relative pager-step"> 8469 <a href="https://www.serrats.com/es_es/comprar-bonito-del-norte?p=2" 8470 mcclane-data="pagination-buttton" 8471 class="page"> 8472 <span class="sr-only label">Página</span> 8473 <span>2</span> 8474 </a> 8475 </li> 8476 <li class="relative pager-step"> 8477 <a href="https://www.serrats.com/es_es/comprar-bonito-del-norte?p=3" 8478 mcclane-data="pagination-buttton" 8479 class="page"> 8480 <span class="sr-only label">Página</span> 8481 <span>3</span> 8482 </a> 8483 </li> 8484 </ul> 8485 </li> 8486 8487 8488 <li class="ml-auto text-sm leading-5 text-black item pages-item-next w-6 md:w-24"> 8489 <a class="action next" 8490 href="https://www.serrats.com/es_es/comprar-bonito-del-norte?p=2" 8491 title="Siguiente"> 8492 <span class="sr-only label">Siguiente</span> 8493 <span> 8494 <span class="flex justify-center items-start"> 8495 <span 8496 class="mr-3 font-bold text-sm hidden md:block">Siguiente</span> 8497 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-4 h-4" width="24" height="24" role="img"><path d="M221.66,133.66l-72,72a8,8,0,0,1-11.32-11.32L196.69,136H40a8,8,0,0,1,0-16H196.69L138.34,61.66a8,8,0,0,1,11.32-11.32l72,72A8,8,0,0,1,221.66,133.66Z"/><title>arrow-right</title></svg> 8498 </span> 8499 </span> 8500 </a> 8501 </li> 8502 </ul> 8503 8504 </div> 8505 </div> 8506 <div id="infinite-scroll-previous" 8507 x-data="loadPrevious()" 8508 x-on:update-infinitescroll-content.window="updatePreviousContent($event.detail)" 8509 x-cloak> 8510 <template x-if="!firstPageReached"> 8511 <div class="md:w-1/2 lg:w-1/3 m-auto md:mt-4 mb-4 md:mb-8 h-auto flex items-center justify-center" 8512 x-show="!isLoading && !firstPageReached"> 8513 <button class="btn btn-secondary flex-1" 8514 @click="onClickLoadPrevious($dispatch)">
8515 <span x-text="previous.text"></span> 8516 </button> 8517 </div> 8518 </template> 8519 <div class="h-auto w-full flex items-center justify-center" x-show="isLoading"> 8520 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="animate-spin -ml-1 mr-3 h-5 w-5" width="24" height="24" role="img"><path d="M232,128a104,104,0,0,1-208,0c0-41,23.81-78.36,60.66-95.27a8,8,0,0,1,6.68,14.54C60.15,61.59,40,93.27,40,128a88,88,0,0,0,176,0c0-34.73-20.15-66.41-51.34-80.73a8,8,0,0,1,6.68-14.54C208.19,49.64,232,87,232,128Z"/><title>circle-notch</title></svg> 8521 <span x-text="previous.loading"></span> 8522 8523 </div> 8524</div>
8525<script> 8526 function loadPrevious() { 8527 return { 8528 previous: { 8529 element: null, 8530 selector: '#infinite-scroll-previous', 8531 text: 'Cargar\u0020art\u00EDculos\u0020anteriores', 8532 loading: 'Cargando productos...' 8533 }, 8534 content: { 8535 element: null, 8536 selector: '.page-products .products' 8537 }, 8538 pagination: { 8539 prev_selector: '.pages .previous', 8540 }, 8541 isLoading: false, 8542 firstPageReached: false, 8543 lastPageReached: false, 8544 init() { 8545 this.previous.element = this.getPreviousElement() 8546 this.content.element = this.getContentElement() 8547 8548 if (this.content.element) { 8549 this.content.element.parentNode.insertBefore(this.previous.element, this.content.element) 8550 } 8551 8552 this.firstPageReached = !(document.querySelector(this.pagination.prev_selector)); 8553 }, 8554 getPreviousElement() { 8555 return window.document.querySelector(this.previous.selector) 8556 }, 8557 getContentElement() { 8558 return window.document.querySelector(this.content.selector) 8559 }, 8560 updatePreviousContent(detail) { 8561 this.isLoading = detail.isLoading 8562 this.firstPageReached = detail.firstPageReached 8563 }, 8564 onClickLoadPrevious($dispatch) { 8565 this.isLoading = true 8566 $dispatch('get-previous-items') 8567 } 8568 } 8569 } 8570</script>
8570 8571 8572<div id="infinite-scroll-trigger" 8573 x-data="infiniteScroll()" 8574 x-on:get-previous-items.window="getItems(false)" 8575 class="mb-4 md:mb-8" 8576 x-cloak> 8577 <div class="md:w-1/2 lg:w-1/3 m-auto"> 8578 <div class="flex mb-2 items-center justify-center"> 8579 <span x-text="getProgressBarText()" 8580 class="text-sm inline-block py-1 px-2 rounded-full"></span> 8581 </div> 8582 <div class="overflow-hidden h-2 mb-4 text-xs flex rounded bg-gray-light"> 8583 <div :style="getProgressBarWidth()" 8584 class="shadow-none flex flex-col text-center whitespace-nowrap text-white justify-center bg-primary"></div> 8585 </div> 8586 </div> 8587 <template x-if="toolbar.enable"> 8588 <div class="h-auto md:w-1/2 lg:w-1/3 m-auto flex items-center justify-center" 8589 x-show="!isLoading && !lastPageReached"> 8590 <button class="btn btn-secondary flex-1" 8591 @click="onToolbarClick()"> 8592 <span x-text="toolbar.text"></span> 8593 </button> 8594 </div> 8595 </template> 8596 <div class="h-auto w-full flex items-center justify-center" x-show="isLoading"> 8597 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="animate-spin -ml-1 mr-3 h-5 w-5" width="24" height="24" role="img"><path d="M232,128a104,104,0,0,1-208,0c0-41,23.81-78.36,60.66-95.27a8,8,0,0,1,6.68,14.54C60.15,61.59,40,93.27,40,128a88,88,0,0,0,176,0c0-34.73-20.15-66.41-51.34-80.73a8,8,0,0,1,6.68-14.54C208.19,49.64,232,87,232,128Z"/><title>circle-notch</title></svg> 8598 <span x-text="trigger.text"></span> 8599 </div> 8600</div>
8601<script> 8602 function infiniteScroll() { 8603 return { 8604 itemsCount: 25, 8605 itemsLoaded: 0, 8606 observer: null, 8607 isPosibleGetItems: true, 8608 isLoading: false, 8609 firstPageReached: false, 8610 lastPageReached: false, 8611 buffer: 150, 8612 lastOffsetItems: [], 8613 offset: 0, 8614 toolbar: { 8615 enable: false, 8616 text: 'Cargar\u0020m\u00E1s\u0020art\u00EDculos' 8617 }, 8618 pagination: { 8619 element: null, 8620 selector: '.pages' 8621 }, 8622 next: { 8623 element: null, 8624 selector: '.pages .next', 8625 url: null 8626 }, 8627 prev: { 8628 element: null, 8629 selector: '.pages .previous', 8630 url: null 8631 }, 8632 content: { 8633 element: null, 8634 selector: '.page-products .products>div' 8635 }, 8636 item: { 8637 selector: '.page-products .products .product-item' 8638 }, 8639 trigger: { 8640 element: null, 8641 selector: '#infinite-scroll-trigger', 8642 text: 'Cargando\u0020productos...' 8643 }, 8644 init() { 8645 this.isPosibleGetItems = true; 8646 const ctx = this 8647 this.trigger.element = this.getTriggerElement() 8648 this.content.element = this.getContentElement() 8649 this.pushLastItem(null, true) 8650 this.createHistoryEvent() 8651 this.setPagination() 8652 this.setItemsLoaded() 8653 this.backPageScroll() 8654 this.scrollToProduct() 8655 8656 if (this.pagination.element) { 8657 this.pagination.element.style.display = 'none' 8658 } 8659 8660 if (this.isLastPage() || this.toolbar.enable) { 8661 return false; 8662 } 8663 8664 if (this.isPolyfillNeeded()) { 8665 this.createPolyfill() 8666 } else { 8667 this.observer = new IntersectionObserver(function (entries) { 8668 if (entries[0].isIntersecting === true) { 8669 ctx.getItems() 8670 } 8671 }, {rootMargin: ctx.getBufferPx(), threshold: [0]}) 8672 8673 this.observer.observe(this.trigger.element) 8674 } 8675 }, 8676 getTriggerElement() { 8677 return window.document.querySelector(this.trigger.selector) 8678 }, 8679 getPaginatorElement() { 8680 return window.document.querySelector(this.pagination.selector) 8681 }, 8682 getContentElement() { 8683 return window.document.querySelector(this.content.selector) 8684 }, 8685 getNextElement(doc) { 8686 if (!doc) { 8687 doc = window.document 8688 } 8689 8690 return doc.querySelector(this.next.selector) 8691 }, 8692 getPrevElement(doc) { 8693 if (!doc) { 8694 doc = window.document 8695 } 8696 8697 return doc.querySelector(this.prev.selector) 8698 }, 8699 getBufferPx() { 8700 return this.buffer + 'px' 8701 }, 8702 isLastPage() { 8703 return !(this.next.element) 8704 }, 8705 isFirstPage() { 8706 return !(this.prev.element) 8707 }, 8708 onLoadPreviousClick() { 8709 this.getItems(false); 8710 }, 8711 onToolbarClick() { 8712 this.getItems(); 8713 }, 8714 getItems(forward = true) { 8715 if ((this.isLastPage() && forward) 8716 || this.isFirstPage() && !forward) { 8717 return false 8718 } 8719 8720 this.isLoading = true 8721 let url = new URL((forward) ? this.next.url : this.prev.url); 8722 const ctx = this 8723 8724 if (url.searchParams.get('infiniteScroll') !== '1') { 8725 url.searchParams.set('infiniteScroll', '1'); 8726 } 8727 8728 fetch(url.toString(), 8729 { 8730 method: 'GET' 8731 }) 8732 .then((response) => { 8733 return response.text() 8734 }) 8735 .then((html) => { 8736 if (!this.isPosibleGetItems) { 8737 return false;
8738 } 8739 url.searchParams.delete('infiniteScroll') 8740 8741 let parser = new DOMParser(); 8742 let doc = parser.parseFromString(html, 'text/html'); 8743 8744 8745 ctx.setHistoryUrl(url.toString()); 8746 ctx.backPageScroll(doc); 8747 ctx.populateItems(doc, forward); 8748 ctx.setItemsLoaded(); 8749 ctx.setPagination(doc, forward); 8750 ctx.launchPageLoadedEvent(doc, forward); 8751 }) 8752 .finally(() => { 8753 ctx.isLoading = false 8754 8755 if (ctx.isLastPage()) { 8756 ctx.cleanUp() 8757 } 8758 8759 ctx.updateContentData() 8760 }); 8761 }, 8762 getNextUrl() { 8763 return (this.next.element) ? this.next.element.href : '' 8764 }, 8765 getPrevUrl() { 8766 return (this.prev.element) ? this.prev.element.href : '' 8767 }, 8768 isPolyfillNeeded() { 8769 return (!('IntersectionObserver' in window) || 8770 !('IntersectionObserverEntry' in window) || 8771 !('isIntersecting' in window.IntersectionObserverEntry.prototype) || 8772 !('intersectionRatio' in window.IntersectionObserverEntry.prototype)) 8773 }, 8774 createPolyfill() { 8775 const ctx = this 8776 window.alpineInfiniteScroll = { 8777 scrollFunc() { 8778 let position = ctx.trigger.element.getBoundingClientRect() 8779 8780 if (position.top < window.innerHeight && position.bottom >= 0) { 8781 ctx.getItems() 8782 } 8783 } 8784 } 8785 8786 window.addEventListener('scroll', window.alpineInfiniteScroll.scrollFunc) 8787 }, 8788 createHistoryEvent() { 8789 const ctx = this 8790 let lastScrollTop = 0; 8791 8792 window.alpineInfiniteScroll = window.alpineInfiniteScroll || {} 8793 window.alpineInfiniteScroll.historyFunc = () => { 8794 if (ctx.lastOffsetItems.length > 1) { 8795 let scrollY = ctx.getScrollY() 8796 let downScroll = (scrollY > lastScrollTop) 8797 8798 for (let item of ctx.lastOffsetItems) { 8799 if ((downScroll) && (item.offset > scrollY) && ctx.offset <= item.offset) { 8800 ctx.offset = item.offset 8801 8802 if (item.url !== ctx.getCurrentPage()) { 8803 ctx.setHistoryUrl(item.url) 8804 } 8805 8806 break; 8807 } 8808 8809 if ((!downScroll) && (scrollY < item.offset) && (item.offset <= ctx.offset)) { 8810 ctx.offset = item.offset 8811 8812 if (item.url !== ctx.getCurrentPage()) { 8813 ctx.setHistoryUrl(item.url) 8814 } 8815 8816 break; 8817 } 8818 } 8819 lastScrollTop = scrollY <= 0 ? 0 : scrollY 8820 } 8821 } 8822 8823 document.addEventListener('scroll', window.alpineInfiniteScroll.historyFunc) 8824 }, 8825 populateItems(doc, forward) { 8826 let items = doc.querySelectorAll(this.item.selector) 8827 8828 if (!forward) { 8829 items = Array.prototype.slice.call(items, 0).reverse() 8830 } 8831 8832 for (let item of items) { 8833 this.runScripts(item.querySelectorAll("script")); 8834 8835 if (forward) { 8836 this.content.element.appendChild(item); 8837 window.setSingleAjaxCart(forward); 8838 } else { 8839 this.content.element.insertBefore(item, this.content.element.childNodes[0]); 8840 window.setSingleAjaxCart(forward); 8841 } 8842 } 8843 8844 this.itemsLoaded += items.length 8845 8846 this.pushLastItem(items, forward) 8847 }, 8848 setHistoryUrl(url) { 8849 if (!url) { 8850 return false;
8851 } 8852 8853 let title = window.document.title 8854 window.history.pushState({path: url}, title, url) 8855 }, 8856 setPagination(doc, forward) { 8857 this.pagination.element = this.getPaginatorElement() 8858 this.next.element = this.getNextElement(doc) 8859 this.prev.element = this.getPrevElement(doc) 8860 8861 if (this.isFirstPage()) { 8862 this.firstPageReached = true 8863 } 8864 8865 if (this.isLastPage()) { 8866 this.lastPageReached = true 8867 } 8868 8869 if (!doc) { 8870 this.next.url = this.getNextUrl() 8871 this.prev.url = this.getPrevUrl() 8872 } else { 8873 if (forward) { 8874 this.next.url = this.getNextUrl() 8875 } else { 8876 this.prev.url = this.getPrevUrl() 8877 } 8878 } 8879 }, 8880 pushLastItem(items, forward) { 8881 const item = this.getLastItem(items, forward) 8882 if (forward) { 8883 this.lastOffsetItems.push(item) 8884 } else { 8885 this.lastOffsetItems.unshift(item) 8886 8887 let cont = 0 8888 for(let offset of this.lastOffsetItems) { 8889 if (offset.offset !== item.offset || cont > 0) { 8890 offset.offset += item.offset 8891 } 8892 8893 cont++ 8894 } 8895 } 8896 8897 this.offset = item.offset 8898 }, 8899 getLastItem(items, forward) { 8900 if (!items) { 8901 items = window.document.querySelectorAll(this.item.selector) 8902 } 8903 8904 let lastItem = {} 8905 8906 if (items.length) { 8907 let target = items[0] 8908 8909 if (forward) { 8910 target = items[items.length - 1] 8911 } 8912 8913 lastItem.element = target 8914 lastItem.offset = lastItem.element.offsetTop 8915 lastItem.url = this.getCurrentPage() 8916 } 8917 8918 return lastItem 8919 }, 8920 getScrollY() { 8921 let scrOfY = 0; 8922 8923 if( typeof( window.pageYOffset ) == 'number' ) { 8924 scrOfY = window.pageYOffset; 8925 } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) { 8926 scrOfY = document.body.scrollTop; 8927 } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) { 8928 scrOfY = document.documentElement.scrollTop; 8929 } 8930 8931 return scrOfY; 8932 }, 8933 getCurrentPage() { 8934 return window.location.href 8935 }, 8936 cleanUp() { 8937 if (this.isPolyfillNeeded()) { 8938 window.removeEventListener('scroll', window.alpineInfiniteScroll.scrollFunc) 8939 } else if (!this.toolbar.enable) { 8940 this.observer.unobserve(this.trigger.element) 8941 } 8942 8943 this.isLoading = false 8944 }, 8945 updateContentData() { 8946 window.dispatchEvent(new CustomEvent('update-infinitescroll-content', 8947 { 8948 detail: { 8949 isLoading: this.isLoading, 8950 lastPageReached: this.lastPageReached, 8951 firstPageReached: this.firstPageReached, 8952 itemsCount: this.itemsCount, 8953 itemsLoaded: this.itemsLoaded, 8954 } 8955 })); 8956 window.dispatchEvent(new CustomEvent('reload-customer-section-data')); 8957 }, 8958 runScripts(scripts) { 8959 Array.from(scripts).forEach((script) => { 8960 let scriptElement = document.createElement('SCRIPT'); 8961 scriptElement.type = 'text/javascript'; 8962 (!script.src) ? scriptElement.innerHTML = script.innerHTML : scriptElement.src = script.src; 8963 document.head.appendChild(scriptElement); 8964 }); 8965 }, 8966 setItemsLoaded() { 8967 this.itemsLoaded = window.document.querySelectorAll(this.item.selector).length 8968 }, 8969 backPageScroll(doc) { 8970 const target = doc || document; 8971 const items = target.querySelectorAll(this.item.selector);
8972 const urlParams = new URLSearchParams(window.location.search); 8973 const page = urlParams.get('p') || 1; 8974 8975 items.forEach(item => { 8976 item.setAttribute('data-page', page); 8977 8978 item.addEventListener('click', (event) => { 8979 let target = event.target.closest('a'); 8980 if (!target || !item.contains(target)) return; 8981 8982 this.isPosibleGetItems = false; 8983 8984 const newUrlParams = new URLSearchParams(window.location.search); 8985 newUrlParams.set('p', item.getAttribute('data-page')); 8986 newUrlParams.set('productAnchor', item.querySelector('[data-product-id]').getAttribute('data-product-id')); 8987 8988 const newUrl = `${window.location.pathname}?${newUrlParams.toString()}`; 8989 window.history.pushState({ path: newUrl }, '', newUrl); 8990 }); 8991 }); 8992 }, 8993 scrollToProduct() { 8994 if ('scrollRestoration' in history) { 8995 history.scrollRestoration = 'manual'; 8996 } 8997 8998 const urlParams = new URLSearchParams(window.location.search); 8999 const page = urlParams.get('p'); 9000 const productAnchor = urlParams.get('productAnchor'); 9001 const targetElement = document.querySelector(`[data-
9001page="${page}"] [data-product-id="${productAnchor}"]`); 9002 9003 if (targetElement) { 9004 this.$nextTick(() => { 9005 targetElement.scrollIntoView({behavior: 'smooth', block: 'center'}); 9006 }); 9007 } 9008 }, 9009 getProgressBarWidth() { 9010 return 'width: ' + ((this.itemsLoaded * 100) / this.itemsCount) + '%;' 9011 }, 9012 getProgressBarText() { 9013 let text = 'Has visto %1 de %2 productos' 9014 return text 9015 .replace('%1', this.itemsLoaded) 9016 .replace('%2', this.itemsCount) 9017 }, 9018 launchPageLoadedEvent(doc, forward) { 9019 let event = new CustomEvent('infinite-scroll-page-loaded', 9020 { 9021 detail: { 9022 doc: doc, 9023 forward: forward 9024 } 9025 }); 9026 window.dispatchEvent(event); 9027 } 9028 } 9029 } 9030</script>
9030 9031 </section> 9032 9033 <a href="https://www.serrats.com/es_es/comprar-bonito-del-norte-en-lata" class="bg-gray-light m-1 py-2.5 px-4 gap-4 inline-flex text-center rounded-xl text-md font-bold inline-flex flex-col flex-nowrap items-center last-of-type:mb-7 md:p-3"> 9034 <span class="">Bonito del Norte en lata</span> 9035 </a> 9036 <a href="https://www.serrats.com/es_es/comprar-bonito-del-norte-tarro-cristal" class="bg-gray-light m-1 py-2.5 px-4 gap-4 inline-flex text-center rounded-xl text-md font-bold inline-flex flex-col flex-nowrap items-center last-of-type:mb-7 md:p-3"> 9037 <span class="">Bonito del Norte en tarro de cristal</span> 9038 </a> 9039 <a href="https://www.serrats.com/es_es/comprar-bonito-del-norte-en-salsa" class="bg-gray-light m-1 py-2.5 px-4 gap-4 inline-flex text-center rounded-xl text-md font-bold inline-flex flex-col flex-nowrap items-center last-of-type:mb-7 md:p-3"> 9040 <span class="">Bonito del Norte en salsa</span> 9041 </a> 9042 <a href="https://www.serrats.com/es_es/comprar-bonito-del-norte-en-escabeche" class="bg-gray-light m-1 py-2.5 px-4 gap-4 inline-flex text-center rounded-xl text-md font-bold inline-flex flex-col flex-nowrap items-center last-of-type:mb-7 md:p-3"> 9043 <span class="">Bonito del Norte en escabeche</span> 9044 </a> 9045 </div> 9046 <div class="sidebar sidebar-main"> 9047 <div x-data="{ open: false }" 9048 x-init="$nextTick(() => { $refs.content.innerHTML.trim().length === 0 ? $dispatch('hide-sidebar-modal-button') : '' }); $watch('open', value => value && window.innerWidth < 768 ? $dispatch('lock-screen') : $dispatch('unlock-screen'));" 9049 @sidebar-modal.window="open = !open" 9050 x-show="open" 9051 class="fixed inset-0 overflow-hidden z-[2147483647] md:relative md:z-auto md:overflow-visible md:!block" 9052 aria-labelledby="slide-over-title" 9053 x-ref="dialog" 9054 aria-modal="true" 9055 mcclane-data="sidebar" 9056 x-cloak 9057 > 9058 <div class="absolute inset-0 overflow-hidden md:relative md:overflow-visible"> 9059 <div x-show="open" 9060 x-transition:enter="ease-in-out duration-500" 9061 x-transition:enter-start="opacity-0" 9062 x-transition:enter-end="opacity-100" 9063 x-transition:leave="ease-in-out duration-500" 9064 x-transition:leave-start="opacity-100" 9065 x-transition:leave-end="opacity-0" 9066 x-description="Background overlay, show/hide based on slide-over state." 9067 class="absolute inset-0 bg-gray-500 bg-opacity-75 transition-opacity md:hidden backdrop backdrop-close" 9068 @click="open = false" 9069 aria-hidden="true" 9070 ></div> 9071 <div class="fixed inset-y-0 right-0 max-w-full flex md:relative"> 9072 <div x-show="open" 9073 x-transition:enter="transform transition ease-in-out duration-500 sm:duration-700" 9074 x-transition:enter-start="translate-x-full" 9075 x-transition:enter-end="translate-x-0" 9076 x-transition:leave="transform transition ease-in-out duration-500 sm:duration-700" 9077 x-transition:leave-start="translate-x-0" 9078 x-transition:leave-end="translate-x-full" 9079 class="w-screen max-w-md md:!block" 9080 x-description="Slide-over panel, show/hide based on slide-over state." 9081 > 9082 <div class="h-full flex flex-col pb-4 bg-white shadow-xl overflow-y-scroll md:p-0 md:shadow-none md:bg-transparent md:overflow-y-visible"> 9083 <header class="px-4 py-2 flex flex-row justify-between items-center border-b border-gray md:hidden"> 9084 <div class="text-lg font-bold">Filtros</div> 9085 <div 9086 x-show="open" 9087 x-transition:enter="ease-in-out duration-500" 9088 x-transition:enter-start="opacity-0" 9089 x-transition:enter-end="opacity-100" 9090 x-transition:leave="ease-in-out duration-500" 9091 x-transition:leave-start="opacity-100" 9092 x-transition:leave-end="opacity-0" class="flex"> 9093 <button @click="open = false" aria-label="Close panel" 9094 class="text-black transition duration-150 ease-in-out hover:text-black"> 9095 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-8 h-8 p-0.5" width="24" height="24" role="img"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/><title>x</title></svg> 9096 </button> 9097 </div> 9098 </header> 9099 <div class="mt-3 relative flex-1 px-4 sm:px-6 md:p-0 md:mt-6" x-ref="content"> 9100 9101 <div class="block filter" x-data="{}" x-init="$refs.narrowByList.innerHTML.trim().length ? '' : $root.remove();"> 9102 <div class="block-content filter-content"> 9103 <div class="filter-options space-y-3 divide-y divide-gray md:space-y-6" id="narrow-by-list" x-ref="narrowByList"> 9104 <div class="pt-3 md:pt-6" x-data="{selected: true}"> 9105 <div role="heading" 9106 @click="selected = !selected" 9107 class="filter-options-title flex flex-row flex-no-wrap items-center justify-between cursor-pointer">
9108 <span class="text-lg font-bold md:text-xl">Por envase</span> 9109 <span class="a-icon" :class="{'transform rotate-180': selected}"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-6 h-6 fill-current" width="24" height="24" role="img"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"/><title>caret-down</title></svg> 9110</span> 9111 </div> 9112 <div class="content relative transition-all" x-ref="container" x-show="selected"> 9113 <div class="pt-3 md:pt-6"><div x-data="{ enabled: false, maxFacetSize: 0, showAll: false }"> 9114 <ol class="items space-y-2"> 9115 <li class="item" x-show="enabled ? (maxFacetSize > 0 || showAll) : true" > 9116 9117 <div class="field choice cursor-pointer"> 9118 <input type="checkbox" 9119 id="filter-value-38" 9120 name="filter-value-38" 9121 class="checkbox" 9122 @change="window.location='https://www.serrats.com/es_es/comprar-bonito-del-norte?tipo_de_envase%5B0%5D=38'" 9123 value="38" 9124 gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'tipo_de_envase[0]=38'}"> 9125 <label class="label" for="filter-value-38"><span class="text-md font-light text-black leading-4" gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'tipo_de_envase[0]=38'}">Lata</span></label> 9126 </div> 9127 </li> 9128 <li class="item" x-show="enabled ? (maxFacetSize > 1 || showAll) : true" > 9129 9130 <div class="field choice cursor-pointer"> 9131 <input type="checkbox" 9132 id="filter-value-39" 9133 name="filter-value-39" 9134 class="checkbox" 9135 @change="window.location='https://www.serrats.com/es_es/comprar-bonito-del-norte?tipo_de_envase%5B0%5D=39'" 9136 value="39" 9137 gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'tipo_de_envase[0]=39'}"> 9138 <label class="label" for="filter-value-39"><span class="text-md font-light text-black leading-4" gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'tipo_de_envase[0]=39'}">Frasco de Cristal</span></label> 9139 </div> 9140 </li> 9141 </ol> 9142 </div> 9143</div> 9144 </div> 9145 </div> 9146 <div class="pt-3 md:pt-6" x-data="{selected: true}"> 9147 <div role="heading" 9148 @click="selected = !selected" 9149 class="filter-options-title flex flex-row flex-no-wrap items-center justify-between cursor-pointer"> 9150 <span class="text-lg font-bold md:text-xl">Por cobertura</span> 9151 <span class="a-icon" :class="{'transform rotate-180': selected}"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-6 h-6 fill-current" width="24" height="24" role="img"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"/><title>caret-down</title></svg> 9152</span> 9153 </div> 9154 <div class="content relative transition-all" x-ref="container" x-show="selected"> 9155 <div class="pt-3 md:pt-6"><div x-data="{ enabled: false, maxFacetSize: 0, showAll: false }"> 9156 <ol class="items space-y-2"> 9157 <li class="item" x-show="enabled ? (maxFacetSize > 0 || showAll) : true" > 9158 9159 <div class="field choice cursor-pointer"> 9160 <input type="checkbox" 9161 id="filter-value-26" 9162 name="filter-value-26" 9163 class="checkbox" 9164 @change="window.location='https://www.serrats.com/es_es/comprar-bonito-del-norte?cobertura%5B0%5D=26'" 9165 value="26" 9166 gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'cobertura[0]=26'}"> 9167 <label class="label" for="filter-value-26"><span class="text-md font-light text-black leading-4" gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'cobertura[0]=26'}">Aceite de oliva</span></label> 9168 </div> 9169 </li> 9170 <li class="item" x-show="enabled ? (maxFacetSize > 1 || showAll) : true" > 9171 9172 <div class="field choice cursor-pointer"> 9173 <input type="checkbox" 9174 id="filter-value-28" 9175 name="filter-value-28" 9176 class="checkbox" 9177 @change="window.location='https://www.serrats.com/es_es/comprar-bonito-del-norte?cobertura%5B0%5D=28'" 9178 value="28" 9179 gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'cobertura[0]=28'}"> 9180 <label class="label" for="filter-value-28"><span class="text-md font-light text-black leading-4" gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'cobertura[0]=28'}">Escabeche</span></label> 9181 </div> 9182 </li> 9183 <li class="item" x-show="enabled ? (maxFacetSize > 2 || showAll) : true" > 9184 9185 <div class="field choice cursor-pointer"> 9186 <input type="checkbox" 9187 id="filter-value-29" 9188 name="filter-value-29" 9189 class="checkbox" 9190 @change="window.location='https://www.serrats.com/es_es/comprar-bonito-del-norte?cobertura%5B0%5D=29'" 9191 value="29" 9192 gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'cobertura[0]=29'}"> 9193 <label class="label" for="filter-value-29"><span class="text-md font-light text-black leading-4" gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'cobertura[0]=29'}">Salsa</span></label> 9194 </div> 9195 </li> 9196 <li class="item" x-show="enabled ? (maxFacetSize > 3 || showAll) : true" > 9197 9198 <div class="field choice cursor-pointer"> 9199 <input type="checkbox" 9200 id="filter-value-31" 9201 name="filter-value-31" 9202 class="checkbox" 9203 @change="window.location='https://www.serrats.com/es_es/comprar-bonito-del-norte?cobertura%5B0%5D=31'" 9204 value="31" 9205 gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'cobertura[0]=31'}"> 9206 <label class="label" for="filter-value-31"><span class="text-md font-light text-black leading-4" gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'cobertura[0]=31'}">Al natural</span></label> 9207 </div> 9208 </li> 9209 <li class="item" x-show="enabled ? (maxFacetSize > 4 || showAll) : true" > 9210 9211 <div class="field choice cursor-pointer"> 9212 <input type="checkbox" 9213 id="filter-value-58" 9214 name="filter-value-58" 9215 class="checkbox" 9216 @change="window.location='https://www.serrats.com/es_es/comprar-bonito-del-norte?cobertura%5B0%5D=58'" 9217 value="58" 9218 gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'cobertura[0]=58'}"> 9219 <label class="label" for="filter-value-58"><span class="text-md font-light text-black leading-4" gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'cobertura[0]=58'}">Aceite de oliva virgen extra ecológico</span></label> 9220 </div> 9221 </li> 9222 <li class="item" x-show="enabled ? (maxFacetSize > 5 || showAll) : true" > 9223 9224 <div class="field choice cursor-pointer"> 9225 <input type="checkbox" 9226 id="filter-value-25" 9227 name="filter-value-25" 9228 class="checkbox" 9229 @change="window.location='https://www.serrats.com/es_es/comprar-bonito-del-norte?cobertura%5B0%5D=25'" 9230 value="25" 9231 gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'cobertura[0]=25'}"> 9232 <label class="label" for="filter-value-25"><span class="text-md font-light text-black leading-4" gtm-tracking="1" gtm-data="{'event': 'filter', 'filter_path':'cobertura[0]=25'}">Aceite de oliva con pimentón de Espelette</span></label> 9233 </div> 9234 </li> 9235 </ol> 9236 </div> 9237</div> 9238 </div> 9239 </div> 9240 </div> 9241 </div> 9242 </div> 9243 9244<div class="skeepers-widget-clickable hidden md:flex justify-center my-20" 9245 x-data="{ 9246 scrollToTarget() { 9247 document.getElementById('skeepers\u002Dcarousel\u002Dwidget')?.scrollIntoView({ behavior: 'smooth', block: 'center' }); 9248 }, 9249 init() { 9250 this.$el.addEventListener('click', (e) => { 9251 e.preventDefault(); 9252 e.stopPropagation(); 9253 this.scrollToTarget(); 9254 }, true); 9255 } 9256 }"> 9257 <div class="cursor-pointer w-full" 9258 role="button" 9259 tabindex="0" 9260 @keydown.enter="scrollToTarget()" 9261 aria-label="Ver opiniones de clientes"> 9262 <div id="7ec9c01c-21d6-4f1a-bafd-e84de83fbb06"></div>
9262<script defer charset="utf-8" src="https://widgets.rr.skeepers.io/generated/a10bd531-6a2b-75a4-8958-07a4f75a5e87/7ec9c01c-21d6-4f1a-bafd-e84de83fbb06.js"></script>
9262 9263 </div> 9264</div> 9265 </div> 9266 </div> 9267 </div> 9268 </div> 9269 </div> 9270 </div> 9271 </div> 9272 9273</div></div></div></div> <!-- HyväCMS cms_block --> 9274 9275<div 9276 id="smart-content-6ab591822613b" 9277 class="smart-content-wrapper cmsb17-w-full" 9278 > 9279 <div class="max-w-none" 9280 > 9281 <section class="cmsb17-py-12 cmsb17-lg:py-20 cmsb17-bg-white"> 9282 <div class="cmsb17-max-w-7xl cmsb17-mx-auto cmsb17-px-4"> 9283 <div class="cmsb17-mb-12 cmsb17-lg:mb-20"> 9284 <h2 class="font-secondary cmsb17-text-4xl cmsb17-md:text-8xl cmsb17-font-extralight cmsb17-text-center cmsb17-leading-tight"> 9285 <span>Información de interés</span> 9286 </h2> 9287 </div> 9288 9289 <div class="cmsb17-border-t cmsb17-border-b cmsb17-border-gray-200"> 9290 <div x-data="{ active: null }" class="cmsb17-max-w-2xl cmsb17-mx-auto cmsb17-divide-y cmsb17-divide-gray-200"> 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 <div class="cmsb17-py-4" data-liveview-group="item_1" data-liveview-group-name="Item 1: Descripción"> 9311 <button 9312 @click="active = (active === 1 ? null : 1)" 9313 class="cmsb17-w-full cmsb17-flex cmsb17-items-center cmsb17-justify-between cmsb17-text-left cmsb17-focus:outline-none" 9314 > 9315 <span class="font-primary cmsb17-text-md cmsb17-font-medium cmsb17-uppercase cmsb17-pr-4"> 9316 <span>¿Qué es el Bonito del Norte y por qué también se llama Atún Blanco?</span> 9317 </span> 9318 <span class="cmsb17-flex-shrink-0 cmsb17-transition-transform cmsb17-duration-300" :class="active === 1 ? 'cmsb17-rotate-180' : ''"> 9319 <template x-if="active !== 1"> 9320 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z"/><title>plus</title></svg> 9321 9322 </template> 9323 <template x-if="active === 1"> 9324 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128Z"/><title>minus</title></svg> 9325 9326 </template> 9327 </span> 9328 </button> 9329 <div 9330 x-show="active === 1" 9331 x-cloak 9332 x-transition:enter="transition ease-out duration-300" 9333 x-transition:enter-start="opacity-0 transform scale-y-95 origin-top" 9334 x-transition:enter-end="opacity-100 transform scale-y-100 origin-top" 9335 class="cmsb17-mt-6 font-primary cmsb17-text-sm cmsb17-tracking-wide cmsb17-space-y-4" 9336 > 9337 <div class="font-primary cmsb17-text-sm cmsb17-space-y-4"> 9338 <p><span>El Bonito del Norte (Thunnus Alalunga) es el pescado de mayor calidad de la familia de los atunes. Durante el verano, el Bonito del Norte se acerca en grandes grupos al Cantábrico donde se captura en la llamada 'Costera del Bonito'.<br><br>También es conocido internacionalmente como "Atún Blanco" (White Tuna o Albacore Tuna), debido al color claro de su carne, más blanca y delicada que la del resto de túnidos. En España, su denominación comercial es Bonito del Norte. </span></p> 9339 </div> 9340 </div> 9341 </div> 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 <div class="cmsb17-py-4" data-liveview-group="item_pesos_medidas" data-liveview-group-name="Item 2: Pesos y Medidas"> 9363 <button 9364 @click="active = (active === 2 ? null : 2)" 9365 class="cmsb17-w-full cmsb17-flex cmsb17-items-center cmsb17-justify-between cmsb17-text-left cmsb17-focus:outline-none" 9366 >
9367 <span class="font-primary cmsb17-text-md cmsb17-font-medium cmsb17-uppercase cmsb17-pr-4"> 9368 <span>¿Cuánto pesa y cuánto mide un Bonito del Norte?</span> 9369 </span> 9370 <span class="cmsb17-flex-shrink-0 cmsb17-transition-transform cmsb17-duration-300" :class="active === 2 ? 'cmsb17-rotate-180' : ''"> 9371 <template x-if="active !== 2"> 9372 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z"/><title>plus</title></svg> 9373 9374 </template> 9375 <template x-if="active === 2"> 9376 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128Z"/><title>minus</title></svg> 9377 9378 </template> 9379 </span> 9380 </button> 9381 <div 9382 x-show="active === 2" 9383 x-cloak 9384 x-transition:enter="transition ease-out duration-300" 9385 x-transition:enter-start="opacity-0 transform scale-y-95 origin-top" 9386 x-transition:enter-end="opacity-100 transform scale-y-100 origin-top" 9387 class="cmsb17-mt-6 font-primary cmsb17-text-sm cmsb17-tracking-wide cmsb17-space-y-4" 9388 > 9389 <div class="font-primary cmsb17-text-sm cmsb17-space-y-4"> 9390 <p><span>El cuerpo del Bonito del Norte es estilizado y está protegido por escamas. El dorso presenta un caracterÃstico color azul oscuro, con el vientre grisáceo y brillante. Se distingue por sus largas aletas pectorales. Su talla media es de 75 cm, alcanzando un peso de 10 a 15 kg.</span></p> 9391 </div> 9392 </div> 9393 </div> 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 9416 9417 9418 <div class="cmsb17-py-4" data-liveview-group="item_diferencia_atun" data-liveview-group-name="Item 3: Diferencia Bonito y Atún"> 9419 <button 9420 @click="active = (active === 3 ? null : 3)" 9421 class="cmsb17-w-full cmsb17-flex cmsb17-items-center cmsb17-justify-between cmsb17-text-left cmsb17-focus:outline-none" 9422 > 9423 <span class="font-primary cmsb17-text-md cmsb17-font-medium cmsb17-uppercase cmsb17-pr-4"> 9424 <span>¿Qué diferencia hay entre el Bonito del Norte y el Atún Claro?</span> 9425 </span> 9426 <span class="cmsb17-flex-shrink-0 cmsb17-transition-transform cmsb17-duration-300" :class="active === 3 ? 'cmsb17-rotate-180' : ''"> 9427 <template x-if="active !== 3"> 9428 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z"/><title>plus</title></svg> 9429 9430 </template> 9431 <template x-if="active === 3"> 9432 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128Z"/><title>minus</title></svg> 9433 9434 </template> 9435 </span> 9436 </button> 9437 <div 9438 x-show="active === 3"
9439 x-cloak 9440 x-transition:enter="transition ease-out duration-300" 9441 x-transition:enter-start="opacity-0 transform scale-y-95 origin-top" 9442 x-transition:enter-end="opacity-100 transform scale-y-100 origin-top" 9443 class="cmsb17-mt-6 font-primary cmsb17-text-sm cmsb17-tracking-wide cmsb17-space-y-4" 9444 > 9445 <div class="font-primary cmsb17-text-sm cmsb17-space-y-4"> 9446 <p><span>Aunque ambos pertenecen a la familia de los túnidos, son dos especies distintas y existen importantes diferencias entre ellos.</span></p> 9447 <p><span>El Bonito del Norte (Thunnus Alalunga) es la variedad más apreciada para la conserva. Tiene una carne blanca, fina y jugosa, con una textura excepcionalmente suave y un sabor más delicado. Además, presenta un menor contenido graso que el Atún Claro. Por su calidad, escasez y cualidades gastronómicas, el Bonito del Norte está considerado la gama más selecta de los atunes.</span></p> 9448 <p><span>Bajo la denominación comercial de "atún" pueden comercializarse distintas especies de túnidos algunos de menor calidad como el Atún Listado o Skipjack. En Serrats, en cambio, utilizamos exclusivamente el Atún Claro (Thunnus Albacares). Este, por su parte, tiene una carne más rosada, una textura más firme y un sabor más intenso que el Bonito del Norte. Al ser una especie más abundante y contar con una amplia distribución geográfica, es la más utilizada en la elaboración de conservas.</span></p> 9449 </div> 9450 </div> 9451 </div> 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479 <div class="cmsb17-py-4" data-liveview-group="item_2" data-liveview-group-name="Item 4: Propiedades"> 9480 <button 9481 @click="active = (active === 4 ? null : 4)" 9482 class="cmsb17-w-full cmsb17-flex cmsb17-items-center cmsb17-justify-between cmsb17-text-left cmsb17-focus:outline-none" 9483 > 9484 <span class="font-primary cmsb17-text-md cmsb17-font-medium cmsb17-uppercase cmsb17-pr-4"> 9485 <span>¿Qué propiedades y beneficios tiene el Bonito del Norte?</span> 9486 </span> 9487 <span class="cmsb17-flex-shrink-0 cmsb17-transition-transform cmsb17-duration-300" :class="active === 4 ? 'cmsb17-rotate-180' : ''"> 9488 <template x-if="active !== 4"> 9489 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z"/><title>plus</title></svg> 9490 9491 </template> 9492 <template x-if="active === 4"> 9493 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128Z"/><title>minus</title></svg> 9494 9495 </template> 9496 </span> 9497 </button> 9498 <div 9499 x-show="active === 4" 9500 x-cloak 9501 x-transition:enter="transition ease-out duration-300" 9502 x-transition:enter-start="opacity-0 transform scale-y-95 origin-top" 9503 x-transition:enter-end="opacity-100 transform scale-y-100 origin-top" 9504 class="cmsb17-mt-6 font-primary cmsb17-text-sm cmsb17-tracking-wide cmsb17-space-y-4" 9505 > 9506 <div class="font-primary cmsb17-text-sm cmsb17-space-y-4"> 9507 <p><span>El Bonito del Norte is uno de los pescados azules que más beneficios aporta a la salud. Mediante su consumo adquirimos multitud de vitaminas, proteÃnas y minerales. Las vitaminas A, B, K y D, y minerales como el calcio y el yodo, hacen del Bonito del Norte uno de los alimentos más completos y exquisitos del mercado.</span></p> 9508 <p><span>Una de las propiedades más destacables del Bonito del Norte es su alto contenido en Omega 3, el ácido graso por excelencia. El Omega 3 son grasas esenciales que nuestro cuerpo no es capaz de generar por sà mismo y que son imprescindibles en nuestra dieta diaria.</span></p> 9509 <p><span>El consumo de Bonito del Norte ayuda a disminuir los niveles de colesterol en sangre y a mantener en buen estado el cerebro. Si buscas fortalecer las articulaciones y huesos, si buscas prevenir enfermedades cardiovasculares, ¡pon Bonito del Norte en tu plato!</span></p> 9510 </div> 9511 </div> 9512 </div> 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 <div class="cmsb17-py-4" data-liveview-group="item_3" data-liveview-group-name="Item 5: Pesca"> 9525 <button 9526 @click="active = (active === 5 ? null : 5)" 9527 class="cmsb17-w-full cmsb17-flex cmsb17-items-center cmsb17-justify-between cmsb17-text-left cmsb17-focus:outline-none" 9528 >
9529 <span class="font-primary cmsb17-text-md cmsb17-font-medium cmsb17-uppercase cmsb17-pr-4"> 9530 <span>¿Cómo se pesca el Bonito del Norte de forma tradicional?</span> 9531 </span> 9532 <span class="cmsb17-flex-shrink-0 cmsb17-transition-transform cmsb17-duration-300" :class="active === 5 ? 'cmsb17-rotate-180' : ''"> 9533 <template x-if="active !== 5"> 9534 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z"/><title>plus</title></svg> 9535 9536 </template> 9537 <template x-if="active === 5"> 9538 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128Z"/><title>minus</title></svg> 9539 9540 </template> 9541 </span> 9542 </button> 9543 <div 9544 x-show="active === 5" 9545 x-cloak 9546 x-transition:enter="transition ease-out duration-300" 9547 x-transition:enter-start="opacity-0 transform scale-y-95 origin-top" 9548 x-transition:enter-end="opacity-100 transform scale-y-100 origin-top" 9549 class="cmsb17-mt-6 font-primary cmsb17-text-sm cmsb17-tracking-wide cmsb17-space-y-4" 9550 > 9551 <div class="font-primary cmsb17-text-sm cmsb17-space-y-4"> 9552 <p><span>En Conservas Serrats, exigimos pescados que se hayan capturado respetando las artes de pesca tradicionales. Las flotas del PaÃs Vasco y Cantabria pescan principalmente con la técnica del cebo vivo o la técnica de la cacea. Con ambas técnicas se pescan los ejemplares uno a uno, evitando de esta manera capturas accidentales de otras especies y siendo las más sostenibles.</span></p> 9553 <p><span>La técnica del cebo vivo se basa en pescar la anchoa o el verdel dejándolos vivos en los viveros de agua de mar para utilizarlos después como cebo. Una vez localizado el banco de bonito, el barco se sitúa sobre él, y los marineros comienzan a âmacizarâ el mar lanzando el cebo vivo junto al barco. Dirigen fuertes chorros de agua al mismo sitio para simular que el agua âhierveâ por el gran número de anchoas o verdel. Los bonitos, excitados por la comida, suben a la superficie lanzándose sobre los peces vivos o anzuelados. Asà es como se les captura, de uno en uno.</span></p> 9554 <p><span>En la técnica de la cacea o curricán, los barcos despliegan largas âperchasâ con anzuelos por ambos lados. Los Bonitos del Norte siguen la estela del cebo camuflado y muerden el anzuelo.</span></p> 9555 <p><span>La pesca del Bonito del Norte se realiza en la costera de junio a octubre, cuando el ejemplar está en su punto óptimo para ser pescado y consumido. En este periodo, las embarcaciones se dirigen al Golfo de Bizkaia, lugar donde se concentra el núcleo más importante.</span></p> 9556 </div> 9557 </div> 9558 </div> 9559 9560 9561 9562 9563 9564 9565 9566 9567 <div class="cmsb17-py-4" data-liveview-group="item_4" data-liveview-group-name="Item 6: Elaboración"> 9568 <button 9569 @click="active = (active === 6 ? null : 6)" 9570 class="cmsb17-w-full cmsb17-flex cmsb17-items-center cmsb17-justify-between cmsb17-text-left cmsb17-focus:outline-none" 9571 > 9572 <span class="font-primary cmsb17-text-md cmsb17-font-medium cmsb17-uppercase cmsb17-pr-4"> 9573 <span>Elaboración del Bonito del Norte en conserva</span> 9574 </span>
9575 <span class="cmsb17-flex-shrink-0 cmsb17-transition-transform cmsb17-duration-300" :class="active === 6 ? 'cmsb17-rotate-180' : ''"> 9576 <template x-if="active !== 6"> 9577 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z"/><title>plus</title></svg> 9578 9579 </template> 9580 <template x-if="active === 6"> 9581 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128Z"/><title>minus</title></svg> 9582 9583 </template> 9584 </span> 9585 </button> 9586 <div 9587 x-show="active === 6" 9588 x-cloak 9589 x-transition:enter="transition ease-out duration-300" 9590 x-transition:enter-start="opacity-0 transform scale-y-95 origin-top" 9591 x-transition:enter-end="opacity-100 transform scale-y-100 origin-top" 9592 class="cmsb17-mt-6 font-primary cmsb17-text-sm cmsb17-tracking-wide cmsb17-space-y-4" 9593 > 9594 <div class="font-primary cmsb17-text-sm cmsb17-space-y-4"> 9595 <p><span>Las conservas de Bonito del Norte Serrats se elaboran siguiendo un cuidadoso proceso artesanal, aprendido y mejorado a lo largo de cinco generaciones.</span></p> 9596 <p><span>La primera fase de todas es la selección a pie de puerto de los mejores ejemplares de Bonito del Norte. Los más frescos.</span></p> 9597 <p><span>Una vez en fábrica, les quitamos vÃsceras y cabeza y los cocemos en agua con sal durante aproximadamente 3h, dependerá del tamaño del bonito. Una vez se han enfriado de forma natural, comenzamos con la fase de limpieza. Esta fase, 100% manual, es fundamental. La destreza y experiencia de manos expertas logran eliminar perfectamente la piel, las espinas y zonas oscuras, consiguiendo lomos blancos e Ãntegros. Esto es, en parte, lo que hace que nuestras conservas de Bonito del Norte tengan ese aspecto excepcional de carne blanca, sabrosa y apetitosa que tantas mesas han alegrado.</span></p> 9598 <p><span>Tras la limpieza ya tenemos los lomos listos y con mucho mimo y delicadeza vamos introduciendo este delicioso producto del mar en las latas o en tarros de cristal. A continuación, le añadimos el aceite de oliva especialmente seleccionado o alguna de nuestras salsas.</span></p> 9599 <p><span>Para finalizar, se lleva a cabo una de las fases más importante del proceso, la esterilización. Esto garantiza que el Bonito del Norte se conservará en perfecto estado y mantendrá sus valores nutricionales con absoluta pureza. Desde este momento, el producto estará listo para viajar desde nuestra fábrica de Bermeo a tu mesa.</span></p> 9600 </div> 9601 </div> 9602 </div> 9603 9604 9605 9606 <div class="cmsb17-py-4" data-liveview-group="item_5" data-liveview-group-name="Item 7: Conservación"> 9607 <button 9608 @click="active = (active === 7 ? null : 7)" 9609 class="cmsb17-w-full cmsb17-flex cmsb17-items-center cmsb17-justify-between cmsb17-text-left cmsb17-focus:outline-none" 9610 > 9611 <span class="font-primary cmsb17-text-md cmsb17-font-medium cmsb17-uppercase cmsb17-pr-4"> 9612 <span>Cómo conservar el Bonito del Norte</span> 9613 </span> 9614 <span class="cmsb17-flex-shrink-0 cmsb17-transition-transform cmsb17-duration-300" :class="active === 7 ? 'cmsb17-rotate-180' : ''"> 9615 <template x-if="active !== 7"> 9616 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z"/><title>plus</title></svg> 9617 9618 </template> 9619 <template x-if="active === 7"> 9620 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128Z"/><title>minus</title></svg> 9621 9622 </template> 9623 </span> 9624 </button> 9625 <div 9626 x-show="active === 7" 9627 x-cloak 9628 x-transition:enter="transition ease-out duration-300" 9629 x-transition:enter-start="opacity-0 transform scale-y-95 origin-top" 9630 x-transition:enter-end="opacity-100 transform scale-y-100 origin-top" 9631 class="cmsb17-mt-6 font-primary cmsb17-text-sm cmsb17-tracking-wide cmsb17-space-y-4" 9632 > 9633 <div class="font-primary cmsb17-text-sm cmsb17-space-y-4"> 9634 <p><span>Las conservas de Bonito del Norte no necesitan ninguna condición especial para su mantenimiento. Puedes guardarlo en la despensa o en un armario. Eso sÃ, una vez abierta la lata o el frasco de Bonito del Norte recomendamos conservarlo en el frigorÃfico, cubierto de aceite y consumirlo en el plazo de tres o cuatro dÃas.</span></p> 9635 </div> 9636 </div> 9637 </div> 9638 9639 9640 9641 <div class="cmsb17-py-4" data-liveview-group="item_6" data-liveview-group-name="Item 8: Recetas"> 9642 <button 9643 @click="active = (active === 8 ? null : 8)" 9644 class="cmsb17-w-full cmsb17-flex cmsb17-items-center cmsb17-justify-between cmsb17-text-left cmsb17-focus:outline-none" 9645 >
9646 <span class="font-primary cmsb17-text-md cmsb17-font-medium cmsb17-uppercase cmsb17-pr-4"> 9647 <span>Recetas con Bonito del Norte</span> 9648 </span> 9649 <span class="cmsb17-flex-shrink-0 cmsb17-transition-transform cmsb17-duration-300" :class="active === 8 ? 'cmsb17-rotate-180' : ''"> 9650 <template x-if="active !== 8"> 9651 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z"/><title>plus</title></svg> 9652 9653 </template> 9654 <template x-if="active === 8"> 9655 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128Z"/><title>minus</title></svg> 9656 9657 </template> 9658 </span> 9659 </button> 9660 <div 9661 x-show="active === 8" 9662 x-cloak 9663 x-transition:enter="transition ease-out duration-300" 9664 x-transition:enter-start="opacity-0 transform scale-y-95 origin-top" 9665 x-transition:enter-end="opacity-100 transform scale-y-100 origin-top" 9666 class="cmsb17-mt-6 font-primary cmsb17-text-sm cmsb17-tracking-wide cmsb17-space-y-4" 9667 > 9668 <div class="font-primary cmsb17-text-sm cmsb17-space-y-4"> 9669 <p><span>Con las conservas de Bonito del Norte Serrats es muy fácil lucirse en la cocina. Pero si te apetece encontrar recetas nuevas y originales, te invitamos a que te des un paseo por âLa cocina de Serratsâ, un blog en el que recopilamos miles de recetas con Bonito del Norte que nos mandan los amantes de Serrats y de la buena gastronomÃa: ensaladas variadas, pintxos tradicionales o de sabores sorprendentes, tostas desde las más sencillas hasta las más sofisticadas, rellenos, platos de pasta⦠¡Encuentra tu favorita!</span></p> 9670 </div> 9671 </div> 9672 </div> 9673 9674 9675 9676 <div class="cmsb17-py-4" data-liveview-group="item_7" data-liveview-group-name="Item 9: Comprar"> 9677 <button 9678 @click="active = (active === 9 ? null : 9)" 9679 class="cmsb17-w-full cmsb17-flex cmsb17-items-center cmsb17-justify-between cmsb17-text-left cmsb17-focus:outline-none" 9680 > 9681 <span class="font-primary cmsb17-text-md cmsb17-font-medium cmsb17-uppercase cmsb17-pr-4"> 9682 <span>Comprar Bonito del Norte en conserva</span> 9683 </span> 9684 <span class="cmsb17-flex-shrink-0 cmsb17-transition-transform cmsb17-duration-300" :class="active === 9 ? 'cmsb17-rotate-180' : ''"> 9685 <template x-if="active !== 9"> 9686 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z"/><title>plus</title></svg> 9687 9688 </template> 9689 <template x-if="active === 9"> 9690 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128Z"/><title>minus</title></svg> 9691 9692 </template> 9693 </span> 9694 </button> 9695 <div 9696 x-show="active === 9" 9697 x-cloak 9698 x-transition:enter="transition ease-out duration-300" 9699 x-transition:enter-start="opacity-0 transform scale-y-95 origin-top" 9700 x-transition:enter-end="opacity-100 transform scale-y-100 origin-top" 9701 class="cmsb17-mt-6 font-primary cmsb17-text-sm cmsb17-tracking-wide cmsb17-space-y-4" 9702 > 9703 <div class="font-primary cmsb17-text-sm cmsb17-space-y-4"> 9704 <p><span>Si disfrutas del buen comer, estás en el lugar adecuado: en nuestra tienda online de conservas de pescado gourmet. Compra el mejor Bonito del Norte en conserva de forma rápida y segura. Conservas de Bonito del Norte de excelente calidad, con sabores auténticos y que mantienen la historia y tradición de cinco generaciones. Pescados frescos. Seleccionados uno a uno. Conservas artesanas, 100% naturales. Prueba nuestro Bonito del Norte en conserva y si no te convence, ¡te devolvemos el dinero!</span></p> 9705 </div> 9706 </div> 9707 </div> 9708 9709 9710 </div> 9711 </div> 9712 </div> 9713</section> </div> 9714 </div> 9715 9716<div id="skeepers-carousel-widget" class="skeepers-widget flex justify-center ml-4 mr-2 md:mx-0 mt-12 border-b">
9717 <div class="skeepers_carousel_container" data-slides-count="4"></div>
9717<script defer charset="utf-8" src="//widgets.rr.skeepers.io/carousel/a10bd531-6a2b-75a4-8958-07a4f75a5e87/6b4f099b-637c-4069-9d82-9209f1f2c39b.js"></script>
9717 9718</div> 9719</main><footer class="page-footer"><div class="footer content">
9719<script type="text/javascript"> 9720 const formIsSubmitted = new Promise((resolve) => { 9721 window.addEventListener('dynamic-form-submitted', event => { 9722 const formObject = event.detail || {}; 9723 9724 return resolve(formObject); 9725 }); 9726 }); 9727 9728 const formDatalayerIsReady = new Promise((resolve) => { 9729 window.addEventListener('datalayer-ready', () => { 9730 return resolve({}); 9731 }); 9732 }); 9733 9734 const formPromises = [formIsSubmitted, formDatalayerIsReady]; 9735 9736 try { 9737 Promise.all(formPromises).then(sendDataGTM) 9738 } catch (e) { 9739 //Promise.all is not supported browser 9740 FormPromiseAllPolyfill(formPromises).then(sendDataGTM); 9741 } 9742 9743 function sendDataGTM(result) { 9744 const formIsSubmittedEvent = result.shift(); 9745 9746 if (!formIsSubmittedEvent.name_form) { 9747 return; 9748 } 9749 9750 window.dispatchEvent( 9751 new CustomEvent('datalayer-event', 9752 { 9753 detail: { 9754 "event": "send_form", 9755 "name_form": formIsSubmittedEvent.name_form 9756 } 9757 } 9758 ) 9759 ); 9760 } 9761 9762 function FormPromiseAllPolyfill(promises) { 9763 const results = []; 9764 let completed = 0; 9765 9766 return new Promise((resolve, reject) => { 9767 promises.forEach((value, index) => { 9768 Promise.resolve(value) 9769 .then((res) => { 9770 results[index] = res; 9771 completed++; 9772 if (completed === promises.length) { 9773 resolve(results); 9774 } 9775 }).catch((err) => reject(err)); 9776 }); 9777 }); 9778 } 9779</script>
vendor: 1 bytes, line 9779
9779
9780<script type="text/javascript"> 9781 // datalayer-ready only fires when the GTM container script finishes loading. 9782 // dataLayer events themselves do not need GTM to be present â they are pushed 9783 // to a global array â so bind on whichever fires first (DOM ready or 9784 // datalayer-ready). All bind helpers below are idempotent via per-element flags. 9785 function initGtmBindings() { 9786 bindGtmClickDelegation(); 9787 bindGtmViewTriggers(); 9788 bindGtmSubmitTriggers(); 9789 } 9790 9791 if (document.readyState === 'loading') { 9792 document.addEventListener('DOMContentLoaded', initGtmBindings, { once: true }); 9793 } else { 9794 initGtmBindings(); 9795 } 9796 window.addEventListener('datalayer-ready', initGtmBindings); 9797 9798 /** 9799 * Click delegation on document â works for elements added after page load too. 9800 * Uses event.target.closest so clicks on descendants of a tagged element also fire. 9801 */ 9802 function bindGtmClickDelegation() { 9803 if (window.__gtmClickDelegationBound) { 9804 return; 9805 } 9806 window.__gtmClickDelegationBound = true; 9807 9808 document.addEventListener('click', (event) => { 9809 const node = event.target.closest('[gtm-tracking="1"]'); 9810 if (!node) { 9811 return; 9812 } 9813 const data = getGtmDataFromNode(node); 9814 const trigger = (data && data.trigger) || 'click'; 9815 if (trigger !== 'click') { 9816 return; 9817 } 9818 dispatchGtmEvent(data); 9819 }, true); 9820 } 9821 9822 /** 9823 * View triggers via IntersectionObserver â fire once per element when it enters viewport. 9824 */ 9825 function bindGtmViewTriggers() { 9826 const nodes = document.querySelectorAll('[gtm-tracking="1"]'); 9827 nodes.forEach((node) => { 9828 if (node.__gtmViewObserver) { 9829 return; 9830 } 9831 const data = getGtmDataFromNode(node); 9832 if (!data || data.trigger !== 'view') { 9833 return; 9834 } 9835 const threshold = typeof data.threshold === 'number' ? data.threshold : 0.5; 9836 const observer = new IntersectionObserver((entries, obs) => { 9837 entries.forEach((entry) => { 9838 if (entry.isIntersecting) { 9839 dispatchGtmEvent(data); 9840 obs.unobserve(entry.target); 9841 } 9842 }); 9843 }, { threshold }); 9844 node.__gtmViewObserver = observer; 9845 observer.observe(node); 9846 }); 9847 } 9848 9849 /** 9850 * Submit triggers â for forms, listen at form submit; for non-form elements 9851 * with trigger=submit, fall back to the closest form. 9852 */ 9853 function bindGtmSubmitTriggers() { 9854 const nodes = document.querySelectorAll('[gtm-tracking="1"]'); 9855 nodes.forEach((node) => { 9856 const data = getGtmDataFromNode(node); 9857 if (!data || data.trigger !== 'submit') { 9858 return; 9859 } 9860 const form = node.tagName === 'FORM' ? node : node.closest('form'); 9861 if (!form || form.__gtmSubmitBound) { 9862 if (!form) { 9863 console.warn('GTM submit trigger has no enclosing <form>', node); 9864 } 9865 return; 9866 } 9867 form.__gtmSubmitBound = true; 9868 form.addEventListener('submit', () => dispatchGtmEvent(data)); 9869 }); 9870 } 9871 9872 function dispatchGtmEvent(data) { 9873 if (typeof data !== 'object' || !data || !data.hasOwnProperty('event')) { 9874 return; 9875 } 9876 window.dispatchEvent( 9877 new CustomEvent('datalayer-event', { detail: data }) 9878 ); 9879 } 9880 9881 /** 9882 * Element should have gtm-data attribute as object value (JSON or single-quoted JSON-like). 9883 * @param element 9884 * @returns {{}} 9885 */ 9886 function getGtmDataFromNode(element) { 9887 let gtmData = {}; 9888 const gtmDataAttribute = element.getAttribute('gtm-data'); 9889 9890 if (!gtmDataAttribute) { 9891 return gtmData; 9892 } 9893 9894 try { 9895 gtmData = JSON.parse(gtmDataAttribute); 9896 } catch (e) { 9897 try { 9898 const sanitized = gtmDataAttribute.replace(/'/g, '"'); 9899 gtmData = JSON.parse(sanitized); 9900 } catch (e2) { 9901 console.error('Could not parse gtm-data', element, e2); 9902 } 9903 } 9904 9905 return gtmData; 9906 } 9907</script>
vendor: 1 bytes, line 9907
9907
9908<script> 9909 let browserStorage = hyva.getBrowserStorage(); 9910 9911 function sendEvent (event) { 9912 window.dataLayer = window.dataLayer || []; 9913 window.dataLayer.push(event); 9914 } 9915 9916 function generateHashCache (data) { 9917 const text = JSON.stringify(data); 9918 return btoa(text); 9919 } 9920 9921 function updateUserData (customer) { 9922 const customerCache = browserStorage.getItem('datalayer-cache-customer'); 9923 const customerHash = generateHashCache(customer); 9924 9925 if (customerHash === customerCache) { 9926 return false; 9927 } 9928 9929 browserStorage.setItem('datalayer-cache-customer', customerHash); 9930 } 9931 9932 function updateEvents (events) { 9933 let cacheEvents = []; 9934 const cacheStorage = browserStorage.getItem('datalayer-cache-events'); 9935 9936 try { 9937 if (cacheStorage) { 9938 cacheEvents = JSON.parse(cacheStorage); 9939 } 9940 } catch (error) { 9941 console.error(error); 9942 } 9943 9944 Object.keys(events).forEach(key => { 9945 const eventData = events[key]; 9946 9947 if (!cacheEvents.includes(eventData.identifier)) { 9948 cacheEvents.push(eventData.identifier); 9949 sendEvent(eventData.event); 9950 } 9951 }); 9952 9953 browserStorage.setItem('datalayer-cache-events', JSON.stringify(cacheEvents)); 9954 } 9955 9956 window.addEventListener('private-content-loaded', event => { 9957 const dataObject = event.detail.data['rocket_datalayer'] || {}; 9958 9959 if (dataObject['customer'] && Object.keys(dataObject['customer']).length) { 9960 updateUserData(dataObject['customer']); 9961 } 9962 }); 9963 9964 window.addEventListener('ecommerce-datalayer-ready', childEventsData => { 9965 let dataObject = {}; 9966 childEventsData.detail.forEach((childEvent) => { 9967 if (childEvent.type === 'private-content-loaded') { 9968 dataObject = childEvent.detail.data['rocket_datalayer'] || {}; 9969 } 9970 }); 9971 9972 if (dataObject['events'] && Object.keys(dataObject['events']).length) { 9973 updateEvents(dataObject['events']); 9974 } 9975 9976 window.addEventListener('private-content-loaded', eventData => { 9977 if (Object.keys(eventData.detail.data?.['rocket_datalayer']?.['events'] || []).length) { 9978 updateEvents(eventData.detail.data['rocket_datalayer']['events']); 9979 } 9980 }) 9981 }); 9982 9983 window.addEventListener('datalayer-event', event => { 9984 sendEvent(event.detail); 9985 }); 9986 9987 window.addEventListener('thirdparty-trigger', () => { 9988 sendEvent({'event':'trigger-load-thirdparty'}); 9989 }); 9990 9991 let ecommerceDatalayerReadyPromises = []; 9992 let ecommerceDatalayerReadyEvents = ['private-content-loaded', 'datalayer-ready', 'thirdparty-trigger']; 9993 9994 ecommerceDatalayerReadyEvents.forEach((eventName) => { 9995 ecommerceDatalayerReadyPromises.push( 9996 new Promise((resolve) => { 9997 window.addEventListener(eventName, event => { 9998 return resolve(event); 9999 }); 10000 }) 10001 ); 10002 }); 10003 10004 try { 10005 Promise.all(ecommerceDatalayerReadyPromises).then(childEventsData => {window.dispatchEvent(new CustomEvent('ecommerce-datalayer-ready', {detail: childEventsData}))}) 10006 } catch (e) { 10007 //Promise.all is not supported browser 10008 PromiseAllPolyfill(ecommerceDatalayerReadyPromises).then(childEventsData => {window.dispatchEvent(new CustomEvent('ecommerce-datalayer-ready', {detail: childEventsData}))}); 10009 } 10010</script>
10010 10011 <!-- HyväCMS cms_block --> 10012 <div class="klaviyo-form-VHvN7Y"></div> <div class="klaviyo-form-YktZ2N"></div> <div class="klaviyo-form-SXMAxH"></div> <div class="klaviyo-form-R48cuX"></div> 10013 10014<div 10015 id="spacer-6a4be5efdd7f6" 10016 class="spacer cmsb34-flex cmsb34-items-center cmsb34-justify-center" 10017 data-liveview-element="spacer" 10018 > 10019 <style> 10020 #spacer-6a4be5efdd7f6 { 10021 height: 1rem; 10022 } 10023 10024 @media (min-width: 640px) { 10025 #spacer-6a4be5efdd7f6 { 10026 height: 1rem; 10027 } 10028 } 10029 10030 @media (min-width: 1024px) { 10031 #spacer-6a4be5efdd7f6 { 10032 height: 5rem; 10033 10034 } 10035 </style> 10036 10037 </div> 10038 10039<div 10040 id="smart-content-6ab591823616f" 10041 class="smart-content-wrapper cmsb34-w-full" 10042 > 10043 <div class="max-w-none" 10044 > 10045 <section class="cmsb34-bg-[#D9DDD7]"> 10046 <div class="cmsb34-max-w-7xl cmsb34-mx-auto"> 10047 <div class="cmsb34-grid cmsb34-grid-cols-2 cmsb34-lg:grid-cols-4 cmsb34-py-10 cmsb34-px-4 cmsb34-lg:px-0"> 10048 10049 10050 <div class="cmsb34-p-4 cmsb34-lg:p-5 cmsb34-border-r cmsb34-border-b cmsb34-lg:border-b-0 cmsb34-border-[#BCBFBA]" data-liveview-group="char_entrega" data-liveview-group-name="CaracterÃstica: Entrega"> 10051 <div class="cmsb34-flex cmsb34-text-center cmsb34-justify-center cmsb34-items-center cmsb34-flex-col cmsb34-space-y-2 cmsb34-md:flex-row cmsb34-md:space-x-4 cmsb34-md:space-y-0 cmsb34-md:text-left cmsb34-md:justify-start cmsb34-md:items-start"> 10052 <div class="cmsb34-flex-shrink-0"> 10053 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="32" height="32" class="cmsb34-text-black"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm64-88a8,8,0,0,1-8,8H128a8,8,0,0,1-8-8V72a8,8,0,0,1,16,0v48h48A8,8,0,0,1,192,128Z"></path></svg> 10054 </div> 10055 <div> 10056 <div class="cmsb34-text-[18px] cmsb34-mb-1"> 10057 <p><span>Entrega en 48/72h</span></p> 10058 </div> 10059 <div class="cmsb34-text-[16px] cmsb34-text-gray-600"> 10060 <p><span>Para compras realizadas en España (PenÃnsula).</span></p> 10061 </div> 10062 </div> 10063 </div> 10064 </div> 10065 10066 10067 10068 10069 10070 <div class="cmsb34-p-4 cmsb34-lg:p-5 cmsb34-border-b cmsb34-lg:border-b-0 cmsb34-lg:border-r cmsb34-border-[#BCBFBA]" data-liveview-group="char_pago" data-liveview-group-name="CaracterÃstica: Pago Seguro"> 10071 <div class="cmsb34-flex cmsb34-text-center cmsb34-justify-center cmsb34-items-center cmsb34-flex-col cmsb34-space-y-2 cmsb34-md:flex-row cmsb34-md:space-x-4 cmsb34-md:space-y-0 cmsb34-md:text-left cmsb34-md:justify-start cmsb34-md:items-start"> 10072 <div class="cmsb34-flex-shrink-0"> 10073 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="32" height="32" class="cmsb34-text-black"><path d="M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Zm-68-56a12,12,0,1,1-12-12A12,12,0,0,1,140,152Z"></path></svg> 10074 </div> 10075 <div> 10076 <div class="cmsb34-text-[18px] cmsb34-mb-1"> 10077 <p><span>Pago seguro</span></p> 10078 </div> 10079 <div class="cmsb34-text-[16px] cmsb34-text-gray-600"> 10080 <p><span>Servicio seguro y confidencial de datos.</span></p> 10081 </div> 10082 </div> 10083 </div> 10084 </div> 10085 10086 10087 10088 10089 10090 10091 <div class="cmsb34-p-4 cmsb34-lg:p-5 cmsb34-border-r cmsb34-border-[#BCBFBA]" data-liveview-group="char_portes" data-liveview-group-name="C
10091aracterÃstica: Portes Gratis"> 10092 <div class="cmsb34-flex cmsb34-text-center cmsb34-justify-center cmsb34-items-center cmsb34-flex-col cmsb34-space-y-2 cmsb34-md:flex-row cmsb34-md:space-x-4 cmsb34-md:space-y-0 cmsb34-md:text-left cmsb34-md:justify-start cmsb34-md:items-start"> 10093 <div class="cmsb34-flex-shrink-0"> 10094 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="32" height="32" class="cmsb34-text-black"><path d="M255.42,117l-14-35A15.93,15.93,0,0,0,226.58,72H192V64a8,8,0,0,0-8-8H32A16,16,0,0,0,16,72V184a16,16,0,0,0,16,16H49a32,32,0,0,0,62,0h50a32,32,0,0,0,62,0h17a16,16,0,0,0,16-16V120A7.94,7.94,0,0,0,255.42,117ZM192,88h34.58l9.6,24H192ZM32,72H176v64H32ZM80,208a16,16,0,1,1,16-16A16,16,0,0,1,80,208Zm81-24H111a32,32,0,0,0-62,0H32V152H176v12.31A32.11,32.11,0,0,0,161,184Zm31,24a16,16,0,1,1,16-16A16,16,0,0,1,192,208Zm48-24H223a32.06,32.06,0,0,0-31-24V128h48Z"></path></svg> 10095 </div> 10096 <div> 10097 <div class="cmsb34-text-[18px] cmsb34-mb-1"> 10098 <p><span>Portes GRATIS a partir de 150â¬</span></p> 10099 </div> 10100 <div class="cmsb34-text-[16px] cmsb34-text-gray-600"> 10101 <p><span>Tarifa única de 4,90⬠por envÃo. Si tu pedido es superior a 150⬠los portes son GRATIS. Sólo para España (PenÃnsula).</span></p> 10102 </div> 10103 </div> 10104 </div> 10105 </div> 10106 10107 10108 10109 10110 10111 10112 <div class="cmsb34-p-4 cmsb34-lg:p-5" data-liveview-group="char_satisfaccion" data-liveview-group-name="CaracterÃstica: GarantÃa"> 10113 <div class="cmsb34-flex cmsb34-text-center cmsb34-justify-center cmsb34-items-center cmsb34-flex-col cmsb34-space-y-2 cmsb34-md:flex-row cmsb34-md:space-x-4 cmsb34-md:space-y-0 cmsb34-md:text-left cmsb34-md:justify-start cmsb34-md:items-start"> 10114 <div class="cmsb34-flex-shrink-0"> 10115 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="32" height="32" class="cmsb34-text-black"><path d="M208,40H48A16,16,0,0,0,32,56v56c0,52.72,25.52,84.67,46.93,102.19,23.06,18.86,46,25.26,47,25.53a8,8,0,0,0,4.2,0c1-.27,23.91-6.67,47-25.53C198.48,196.67,224,164.72,224,112V56A16,16,0,0,0,208,40Zm0,72c0,37.07-13.66,67.16-40.6,89.42A129.3,129.3,0,0,1,128,223.62a128.25,128.25,0,0,1-38.92-21.81C61.82,179.51,48,149.3,48,112l0-56,160,0ZM82.34,141.66a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35a8,8,0,0,1,11.32,11.32l-56,56a8,8,0,0,1-11.32,0Z"></path></svg> 10116 </div> 10117 <div> 10118 <div class="cmsb34-text-[18px] cmsb34-mb-1"> 10119 <p><span>GarantÃa de Satisfacción</span></p> 10120 </div> 10121 <div class="cmsb34-text-[16px] cmsb34-text-gray-600"> 10122 <p><span>Si en algún caso los productos no son de tu agrado, llámanos. Te los recogemos y reembolsamos su precio.</span></p> 10123 </div> 10124 </div> 10125 </div> 10126 </div> 10127 10128 10129 </div> 10130 </div> 10131</section> </div> 10132 </div> 10133 10134<div 10135 id="smart-content-6ab5918237d12" 10136 class="smart-content-wrapper cmsb34-w-full" 10137 > 10138 <div class="max-w-none" 10139 > 10140 <section class="o-footer cmsb34-relative cmsb34-text-white/80"> 10141 <style> 10142 .o-footer { 10143 --footer-left-bleeding-background: #000000; 10144 --footer-content-background: #000000; 10145 --footer-right-bleeding-background: #000000; 10146 } 10147 #rktgridlayout-main-footer { 10148 --o-grid-template-columns: 1fr; 10149 --o-grid-template-columns-tablet: 1fr; 10150 --o-grid-template-columns-desktop: 1fr 1fr 1fr 1fr; 10151 --o-grid-template-rows: auto auto auto auto auto auto auto auto auto auto auto; 10152 --o-grid-template-rows-tablet: auto auto auto auto auto auto auto auto auto auto auto; 10153 --o-grid-template-rows-desktop: 1fr 1fr auto; 10154 --o-grid-template-gap: 16px 0px; 10155 --o-grid-template-gap-tablet: 16px 0px; 10156 --o-grid-template-gap-desktop: 0px 0px; 10157 } 10158 </style> 10159 10160 <div class="cmsb34-bg-black"> 10161 <div class="cmsb34-max-w-7xl cmsb34-mx-auto cmsb34-px-4 cmsb34-lg:px-8"> 10162 <div id="rktgridlayout-main-footer" class="o-grid cmsb34-pb-5 cmsb34-pt-8 cmsb34-lg:pb-12 cmsb34-lg:pt-12 cmsb34-grid"> 10163 10164 10165 <div class="o-grid-child" style="--o-grid-area: 1 / 1 / 2 / 2; --o-grid-area-tablet: 1 / 1 / 2 / 2; --o-grid-area-desktop: 1 / 1 / 2 / 2;" data-liveview-group="footer_info" data-liveview-group-name="Info Contacto y Logo"> 10166 <div class="cmsb34-lg:pl-10 cmsb34-lg:pr-10 cmsb34-h-full"> 10167 <a href="https://www.serrats.com/es_es/" class="cmsb34-block cmsb34-mb-5 cmsb34-lg:pointer-events-none"> 10168 <img src="https://www.serrats.com/media/cms/footer/logo-svg-white.png" alt="Logo de la tienda" width="158" height="70" class="cmsb34-max-w-[150px] cmsb34-mx-auto cmsb34-lg:mx-0"> 10169 </a> 10170 <div class="cmsb34-pt-5 cmsb34-pb-5 cmsb34-lg:pt-8 cmsb34-lg:pb-8 cmsb34-text-base cmsb34-text-center cmsb34-lg:text-left cmsb34-text-white/70"> 10171 <p><span>PolÃgono Landabaso 3B,</span></p> 10172 <p><span>48370 Bermeo, Bizkaia (Spain)</span></p> 10173 </div> 10174 <div class="cmsb34-space-y-2 cmsb34-text-white/80"> 10175 <div class="cmsb34-flex cmsb34-items-center cmsb34-justify-center cmsb34-lg:justify-start cmsb34-gap-2 cmsb34-text-base"> 10176 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="18" height="18" role="img"><path d="M222.37,158.46l-47.11-21.11-.13-.06a16,16,0,0,0-15.17,1.4,8.12,8.12,0,0,0-.75.56L134.87,160c-15.42-7.49-31.34-23.29-38.83-38.51l20.78-24.71c.2-.25.39-.5.57-.77a16,16,0,0,0,1.32
10176-15.06l0-.12L97.54,33.64a16,16,0,0,0-16.62-9.52A56.26,56.26,0,0,0,32,80c0,79.4,64.6,144,144,144a56.26,56.26,0,0,0,55.88-48.92A16,16,0,0,0,222.37,158.46ZM176,208A128.14,128.14,0,0,1,48,80,40.2,40.2,0,0,1,82.87,40a.61.61,0,0,0,0,.12l21,47L83.2,111.86a6.13,6.13,0,0,0-.57.77,16,16,0,0,0-1,15.7c9.06,18.53,27.73,37.06,46.46,46.11a16,16,0,0,0,15.75-1.14,8.44,8.44,0,0,0,.74-.56L168.89,152l47,21.05h0s.08,0,.11,0A40.21,40.21,0,0,1,176,208Z"/><title>phone</title></svg> 10177 10178 <a href="tel:https://www.serrats.com/es_es/946187280/" class="cmsb34-hover:underline"><span>946 187 280</span></a> 10179 </div> 10180 <div class="cmsb34-flex cmsb34-items-center cmsb34-justify-center cmsb34-lg:justify-start cmsb34-gap-2 cmsb34-text-base"> 10181 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" width="18" height="18" role="img"><path d="M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48Zm-96,85.15L52.57,64H203.43ZM98.71,128,40,181.81V74.19Zm11.84,10.85,12,11.05a8,8,0,0,0,10.82,0l12-11.05,58,53.15H52.57ZM157.29,128,216,74.18V181.82Z"/><title>envelope</title></svg> 10182 10183 <a href="mailto:https://www.serrats.com/es_es/[email protected]/" class="cmsb34-hover:underline"><span>[email protected]</span></a> 10184 </div> 10185 </div> 10186</div> 10187 </div> 10188 10189 10190 <div class="o-grid-child" style="--o-grid-area-display: none; --o-grid-area-display-tablet: none; --o-grid-area-desktop: 2 / 1 / 3 / 2;" data-liveview-group="footer_skeepers" data-liveview-group-name="Skeepers Verified Reviews"> 10191 <div class="cmsb34-lg:pl-10 cmsb34-lg:pr-10 cmsb34-mt-8 cmsb34-hidden cmsb34-lg:block cmsb34-text-center cmsb34-lg:text-left"> 10192 <div id="816a69bf-5385-4038-bc6e-af042b55adee"></div> 10193 </div> 10194 </div> 10195 10196 10197 10198 10199 10200 <div class="o-grid-child" style="--o-grid-area: 2 / 1 / 3 / 2; --o-grid-area-tablet: 2 / 1 / 3 / 2; --o-grid-area-desktop: 1 / 2 / 2 / 3;" data-liveview-group="footer_nav_serrats" data-liveview-group-name="Navegación: Serrats"> 10201 <div class="cmsb34-lg:pl-10 cmsb34-lg:pr-10 cmsb34-h-full cmsb34-lg:border-l cmsb34-border-white/10" x-data="{ open: false }"> 10202 <div class="cmsb34-flex cmsb34-flex-col cmsb34-gap-4"> 10203 <button @click="open = !open" class="cmsb34-flex cmsb34-items-center cmsb34-justify-between cmsb34-w-full cmsb34-text-left cmsb34-lg:pointer-events-none group"> 10204 <span class="cmsb34-font-bold cmsb34-text-white cmsb34-uppercase cmsb34-text-lg"><span>SERRATS</span></span> 10205 <span class="cmsb34-lg:hidden cmsb34-transition-transform cmsb34-duration-200" :class="open ? 'cmsb34-rotate-180' : ''"> 10206 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="cmsb34-text-white" width="20" height="20" role="img"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"/><title>caret-down</title></svg> 10207 10208 </span> 10209 </button> 10210 <ul class="cmsb34-space-y-2 cmsb34-text-base cmsb34-text-white/70" :class="open ? 'cmsb34-block' : 'cmsb34-hidden cmsb34-lg:block'" x-transition> 10211 <li><a href="https://www.serrats.com/es_es/bermeo-nuestro-origen" class="cmsb34-hover:underline"><span>Conócenos</span></a></li> 10212 <li><a href="https://www.serrats.com/es_es/tienda-conservas" class="cmsb34-hover:underline"><span>Tienda de conservas</span></a></li> 10213 <li><a href="https://www.serrats.com/recetas/" class="cmsb34-hover:underline"><span>Recetas y mas</span></a></li> 10214 <li><a href="https://www.serrats.com/es_es/distribuir-conservas-de-pescado" class="cmsb34-hover:underline"><span>Distribuidores</span></a></li> 10215 <li><a href="https://www.serrats.com/es_es/somos-sostenibles" class="cmsb34-hover:underline"><span>Nuestro compromiso con el medio ambiente</span></a></li> 10216 <li><a href="https://www.serrats.com/es_es/club-serrats" class="cmsb34-hover:underline"><span>Club Serrats</span></a></li> 10217 <li><a href="https://www.serrats.com/es_es/certificados-reconocimientos" class="cmsb34-hover:underline"><span>Certificados y reconocimientos</span></a></li> 10218 </ul> 10219 </div> 10220 </div> 10221 </div> 10222 10223 10224 10225 10226 10227 <div class="o-grid-child" style="--o-grid-area: 3 / 1 / 4 / 2; --o-grid-area-tablet: 3 / 1 / 4 / 2; --o-grid-area-desktop: 1 / 3 / 2 / 4;" data-liveview-group="footer_nav_ayuda" data-liveview-group-name="Navegación: Ayuda"> 10228 <div class="cmsb34-lg:pl-10 cmsb34-lg:pr-10 cmsb34-h-full cmsb34-lg:border-l cmsb34-border-white/10" x-data="{ open: false }"> 10229 <div class="cmsb34-flex cmsb34-flex-col cmsb34-gap-4"> 10230 <button @click="open = !open" class="cmsb34-flex cmsb34-items-center cmsb34-justify-between cmsb34-w-full cmsb34-text-left cmsb34-lg:pointer-events-none group"> 10231 <span class="cmsb34-font-bold cmsb34-text-white cmsb34-uppercase cmsb34-text-lg"><span>AYUDA</span></span> 10232 <span class="cmsb34-lg:hidden cmsb34-transition-transform cmsb34-duration-200" :class="open ? 'cmsb34-rotate-180' : ''"> 10233 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="cmsb34-text-white" width="20" height="20" role="img"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"/><title>caret-down</title></svg> 10234 10235 </span> 10236 </button> 10237 <ul class="cmsb34-space-y-2 cmsb34-text-base cmsb34-text-white/70" :class="open ? 'cmsb34-block' : 'cmsb34-hidden cmsb34-lg:block'" x-transition> 10238 <li><a href="https://www.serrats.com/es_es/customer/account/" class="cmsb34-hover:underline"><span>Mi cuenta</span></a></li> 10239 <li><a href="https://www.serrats.com/es_es/condiciones-de-uso#shipping" class="cmsb34-hover:underline"><span>EnvÃos y entrega</span></a></li> 10240 <li><a href="https://www.serrats.com/es_es/es-posible-devolver-un-pedido" class="cmsb34-hover:underline"><span>Devoluciones</span></a></li> 10241 <li><a href="https://www.serrats.com/es_es/que-formas-de-pago-puedo-utilizar" class="cmsb34-hover:underline"><span>Formas de pago</span></a></li> 10242 <li><a href="https://www.serrats.com/es_es/garantia-de-satisfaccion" class="cmsb34-hover:underline"><span>Garantia de satisfacción</span></a></li> 10243 <li><a href="https://www.serrats.com/es_es/contacto" class="cmsb34-hover:underline"><span>Contacto</span></a></li> 10244 </ul> 10245 </div> 10246 </div> 10247 </div> 10248 10249 10250 10251 10252 <div class="o-grid-child" style="--o-grid-area: 4 / 1 / 5 / 2; --o-grid-area-tablet: 4 / 1 / 5 / 2; --o-grid-area-desktop: 1 / 4 / 2 / 5;" data-liveview-group="footer_nav_actualidad" data-liveview-group-name="Navegación: Actualidad"> 10253 <div class="cmsb34-lg:pl-10 cmsb34-lg:pr-10 cmsb34-h-full cmsb34-lg:border-l cmsb34-border-white/10" x-data="{ open: false }"> 10254 <div class="cmsb34-flex cmsb34-flex-col cmsb34-gap-4"> 10255 <button @click="open = !open" class="cmsb34-flex cmsb34-items-center cmsb34-justify-between cmsb34-w-full cmsb34-text-left cmsb34-lg:pointer-events-none group"> 10256 <span class="cmsb34-font-bold cmsb34-text-white cmsb34-uppercase cmsb34-text-lg"><span>ACTUALIDAD</span></span> 10257 <span class="cmsb34-lg:hidden cmsb34-transition-transform cmsb34-duration-200" :class="open ? 'cmsb34-rotate-180' : ''"> 10258 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="cmsb34-text-white" width="20" height="20" role="img"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"/><title>caret-down</title></svg> 10259 10260 </span> 10261 </button> 10262 <ul class="cmsb34-space-y-2 cmsb34-text-base cmsb34-text-white/70" :class="open ? 'cmsb34-block' : 'cmsb34-hidden cmsb34-lg:block'" x-transition> 10263 <li><a href="https://www.serrats.com/recetas/" class="cmsb34-hover:underline"><span>Recetas</span></a></li> 10264 <li><a href="https://www.serrats.com/es_es/faq" class="cmsb34-hover:underline"><span>¿SabÃas...?</span></a></li> 10265 <li><a href="https://www.serrats.com/recetas/nutricion/" class="cmsb34-hover:underline"><span>Nutrición y salud</span></a></li> 10266 <li><a href="https://www.serrats.com/es_es/proyecto-subvencionado" class="cmsb34-hover:underline"><span>Proyecto subvencionado</span></a></li> 10267 </ul> 10268 </div> 10269 </div> 10270 </div> 10271 10272 10273 10274 10275 10276 10277 10278 10279 <div class="o-grid-child" style="--o-grid-area: 5 / 1 / 6 / 2; --o-grid-area-tablet: 5 / 1 / 6 / 2; --o-grid-area-desktop: 2 / 2 / 3 / 3;" data-liveview-group="footer_legal_rrss" data-liveview-group-name="Legal y RRSS"> 10280 <div class="cmsb34-lg:pt-12 cmsb34-lg:pl-10 cmsb34-lg:pr-10 cmsb34-h-full cmsb34-lg:border-l cmsb34-border-white/10" x-data="{ open: false }"> 10281 <div class="cmsb34-flex cmsb34-flex-col cmsb34-gap-4"> 10282 <button @click="open = !open" class="cmsb34-flex cmsb34-items-center cmsb34-justify-between cmsb34-w-full cmsb34-text-left cmsb34-lg:pointer-events-none group"> 10283 <span class="cmsb34-font-bold cmsb34-text-white cmsb34-uppercase cmsb34-text-lg"><span>LEGAL</span></span> 10284 <span class="cmsb34-lg:hidden cmsb34-transition-transform cmsb34-duration-200" :class="open ? 'cmsb34-rotate-180' : ''"> 10285 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="cmsb34-text-white" width="20" height="20" role="img"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"/><title>caret-down</title></svg> 10286 10287 </span> 10288 </button> 10289 <ul class="cmsb34-space-y-2 cmsb34-text-base cmsb34-text-white/70" :class="open ? 'cmsb34-block' : 'cmsb34-hidden cmsb34-lg:block'" x-transition> 10290 <li><a href="https://www.serrats.com/es_es/aviso-legal" class="cmsb34-hover:underline"><span>Aviso legal</span></a></li> 10291 <li><a href="https://www.serrats.com/es_es/politica-privacidad" class="cmsb34-hover:underline"><span>PolÃtica de privacidad</span></a></li> 10292 <li>
10292<a href="https://www.serrats.com/es_es/cookies" class="cmsb34-hover:underline"><span>PolÃtica de cookies</span></a></li> 10293 <li><button @click="$el.dispatchEvent(new CustomEvent('toggle-cookiesconsent-config', { bubbles: true }))" class="cmsb34-hover:underline cmsb34-text-left"><span>Configuración de cookies</span></button></li> 10294 </ul> 10295 </div> 10296 </div> 10297 </div> 10298 10299 <div class="o-grid-child" style="--o-grid-area: 6 / 1 / 7 / 2; --o-grid-area-tablet: 6 / 1 / 7 / 2; --o-grid-area-desktop: 2 / 3 / 3 / 4;"> 10300 <div class="cmsb34-lg:pt-12 cmsb34-lg:pl-10 cmsb34-lg:pr-10 cmsb34-h-full cmsb34-lg:border-l cmsb34-border-white/10"> 10301 <span class="cmsb34-font-bold cmsb34-text-white cmsb34-uppercase cmsb34-block cmsb34-mb-4 cmsb34-text-lg"><span>FORMAS DE PAGO</span></span> 10302 <div class="cmsb34-flex cmsb34-gap-4 cmsb34-flex-wrap cmsb34-justify-start"> 10303 <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 34 24" fill="none" class="cmsb34-text-white" role="img"> 10304<path fill-rule="evenodd" clip-rule="evenodd" d="M10.7278 15.4682H8.74508L7.25826 9.6291C7.18769 9.3605 7.03785 9.12304 6.81744 9.01113C6.26737 8.72987 5.66124 8.50604 5 8.39315V8.16834H8.19405C8.63487 8.16834 8.96549 8.50604 9.0206 8.89824L9.79204 13.1102L11.7738 8.16834H13.7015L10.7278 15.4682ZM14.8035 15.4682H12.9309L14.4729 8.16834H16.3454L14.8035 15.4682ZM18.768 10.1906C18.8231 9.79748 19.1537 9.57267 19.5394 9.57267C20.1456 9.51623 20.8059 9.62912 21.3569 9.90939L21.6875 8.3377C21.1365 8.11289 20.5303 8 19.9803 8C18.1628 8 16.8404 9.01114 16.8404 10.4145C16.8404 11.4821 17.7771 12.0426 18.4383 12.3803C19.1537 12.717 19.4292 12.9418 19.3741 13.2786C19.3741 13.7837 18.8231 14.0085 18.273 14.0085C17.6118 14.0085 16.9506 13.8401 16.3454 13.5588L16.0148 15.1315C16.676 15.4118 17.3914 15.5247 18.0526 15.5247C20.0905 15.5802 21.3569 14.57 21.3569 13.0538C21.3569 11.1444 18.768 11.0325 18.768 10.1906ZM27.91 15.4683L26.4232 8.16837H24.8261C24.4955 8.16837 24.1649 8.39317 24.0547 8.7299L21.3015 15.4683H23.2291L23.6139 14.4016H25.9823L26.2028 15.4683H27.91ZM25.102 10.1343L25.652 12.8855H24.1101L25.102 10.1343Z" fill="white"/> 10305<rect x="0.5" y="0.5" width="33" height="23" rx="3.5" stroke="white"/> 10306<title>payment/visa-color-false-bg-negative</title></svg> 10307 10308 <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 34 24" fill="none" class="cmsb34-text-white" role="img"> 10309<path fill-rule="evenodd" clip-rule="evenodd" d="M17.179 16.8294C15.9949 17.8275 14.459 18.43 12.7807 18.43C9.03582 18.43 6 15.4303 6 11.73C6 8.02966 9.03582 5.02997 12.7807 5.02997C14.459 5.02997 15.9949 5.63247 17.179 6.63051C18.363 5.63247 19.8989 5.02997 21.5773 5.02997C25.3221 5.02997 28.358 8.02966 28.358 11.73C28.358 15.4303 25.3221 18.43 21.5773 18.43C19.8989 18.43 18.363 17.8275 17.179 16.8294Z" fill="white"/> 10310<path fill-rule="evenodd" clip-rule="evenodd" d="M17.179 16.8294C18.6369 15.6005 19.5614 13.7719 19.5614 11.73C19.5614 9.68801 18.6369 7.85941 17.179 6.63051C18.363 5.63247 19.8989 5.02997 21.5772 5.02997C25.3221 5.02997 28.3579 8.02966 28.3579 11.73C28.3579 15.4303 25.3221 18.43 21.5772 18.43C19.8989 18.43 18.363 17.8275 17.179 16.8294Z" fill="white"/> 10311<mask id="path-4-outside-1_2357_213" maskUnits="userSpaceOnUse" x="13.7966" y="5.63054" width="7" height="12" fill="black"> 10312<rect fill="white" x="13.7966" y="5.63054" width="7" height="12"/> 10313<path fill-rule="evenodd" clip-rule="evenodd" d="M17.179 16.8294C18.6369 15.6005 19.5614 13.7719 19.5614 11.73C19.5614 9.68801 18.6369 7.85942 17.179 6.63052C15.7211 7.85942 14.7966 9.68801 14.7966 11.73C14.7966 13.7719 15.7211 15.6005 17.179 16.8294Z"/> 10314</mask> 10315<path fill-rule="evenodd" clip-rule="evenodd" d="M17.179 16.8294C18.6369 15.6005 19.5614 13.7719 19.5614 11.73C19.5614 9.68801 18.6369 7.85942 17.179 6.63052C15.7211 7.85942 14.7966 9.68801 14.7966 11.73C14.7966 13.7719 15.7211 15.6005 17.179 16.8294Z" fill="white"/> 10316<path d="M17.179 16.8294L16.8568 17.2117L17.179 17.4833L17.5013 17.2117L17.179 16.8294ZM17.179 6.63052L17.5013 6.24821L17.179 5.97658L16.8568 6.24821L17.179 6.63052ZM19.0614 11.73C19.0614 13.6171 18.2077 15.3083 16.8568 16.4471L17.5013 17.2117C19.0661 15.8926 20.0614 13.9267 20.0614 11.73H19.0614ZM16.8568 7.01282C18.2077 8.15157 19.0614 9.84277 19.0614 11.73H20.0614C20.0614 9.53325 19.0661 7.56727 17.5013 6.24821L16.8568 7.01282ZM15.2966 11.73C15.2966 9.84277 16.1503 8.15157 17.5013 7.01282L16.8568 6.24821C15.2919 7.56727 14.2966 9.53325 14.2966 11.73H15.2966ZM17.5013 16.4471C16.1503 15.3083 15.2966 13.6171 15.2966 11.73H14.2966C14.2966 13.9267 15.2919 15.8926 16.8568 17.2117L17.5013 16.4471Z" fill="black" mask="url(#path-4-outside-1_2357_213)"/> 10317<rect x="0.5" y="0.5" width="33" height="23" rx="3.5" stroke="white"/> 10318<title>payment/mastercard-color-false-bg-negative</title></svg> 10319 10320 <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 34 24" fill="none" class="cmsb34-text-white" role="img"> 10321<path fill-rule="evenodd" clip-rule="evenodd" d="M14.6143 18.4483L14.835 16.9992L14.3433 16.9873H11.9954L13.6271 6.29368C13.6322 6.2613 13.6486 6.23124 13.6726 6.20986C13.6967 6.18847 13.7275 6.17674 13.7596 6.17674H17.7186C19.033 6.17674 19.94 6.45938 20.4135 7.01732C20.6356 7.27906 20.7769 7.55265 20.8454 7.85362C20.9172 8.16949 20.9183 8.54683 20.8484 9.00714L20.8433 9.04062V9.3356L21.0653 9.46561C21.2522 9.56813 21.4008 9.68544 21.5148 9.81973C21.7047 10.0436 21.8275 10.3281 21.8794
1032110.6652C21.9331 11.012 21.9153 11.4248 21.8275 11.892C21.7262 12.4294 21.5624 12.8976 21.3412 13.2805C21.1379 13.6334 20.8787 13.9262 20.571 14.153C20.2772 14.3686 19.9282 14.5322 19.5336 14.6369C19.1511 14.7398 18.7151 14.7917 18.2369 14.7917H17.9288C17.7086 14.7917 17.4946 14.8737 17.3266 15.0207C17.1581 15.1708 17.0467 15.3758 17.0126 15.6L16.9893 15.7305L16.5993 18.2848L16.5816 18.3785C16.5769 18.4082 16.5689 18.423 16.557 18.433C16.5465 18.4422 16.5314 18.4483 16.5166 18.4483H14.6143Z" fill="white"/> 10322<path fill-rule="evenodd" clip-rule="evenodd" d="M21.2757 9.07468C21.264 9.15276 21.2504 9.23255 21.2353 9.31454C20.7132 12.0852 18.9269 13.0423 16.6457 13.0423H15.4841C15.2051 13.0423 14.97 13.2517 14.9266 13.5361L14.1634 18.5394C14.1352 18.7262 14.2745 18.8945 14.4568 18.8945H16.5169C16.7608 18.8945 16.9681 18.7113 17.0065 18.4626L17.0267 18.3545L17.4146 15.8103L17.4396 15.6707C17.4775 15.4212 17.6852 15.2379 17.9291 15.2379H18.2372C20.2332 15.2379 21.7958 14.4004 22.2525 11.9766C22.4432 10.9641 22.3445 10.1186 21.8396 9.52399C21.6869 9.34473 21.4974 9.19589 21.2757 9.07468Z" fill="white"/> 10323<path d="M21.2757 9.07468C21.264 9.15276 21.2504 9.23255 21.2353 9.31454C20.7132 12.0852 18.9269 13.0423 16.6457 13.0423H15.4841C15.2051 13.0423 14.97 13.2517 14.9266 13.5361L14.1634 18.5394C14.1352 18.7262 14.2745 18.8945 14.4568 18.8945H16.5169C16.7608 18.8945 16.9681 18.7113 17.0065 18.4626L17.0267 18.3545L17.4146 15.8103L17.4396 15.6707C17.4775 15.4212 17.6852 15.2379 17.9291 15.2379H18.2372C20.2332 15.2379 21.7958 14.4004 22.2525 11.9766C22.4432 10.9641 22.3445 10.1186 21.8396 9.52399C21.6869 9.34473 21.4974 9.19589 21.2757 9.07468" stroke="black" stroke-width="0.5"/> 10324<path fill-rule="evenodd" clip-rule="evenodd" d="M20.7292 8.84962C20.6494 8.82555 20.5671 8.8038 20.4827 8.78413C20.3978 8.76494 20.3109 8.74796 20.2214 8.73305C19.9082 8.68075 19.565 8.65594 19.1975 8.65594H16.0944C16.0179 8.65594 15.9454 8.67379 15.8805 8.70604C15.7373 8.77716 15.631 8.9172 15.6052 9.08864L14.9451 13.4102L14.9261 13.5362C14.9695 13.2517 15.2047 13.0424 15.4837 13.0424H16.6452C18.9265 13.0424 20.7128 12.0847 21.2348 9.31457C21.2504 9.23258 21.2636 9.15279 21.2753 9.07471C21.1432 9.00224 21.0002 8.94029 20.8461 8.8875C20.808 8.87443 20.7688 8.86184 20.7292 8.84962Z" fill="white"/> 10325<path fill-rule="evenodd" clip-rule="evenodd" d="M15.6055 9.08865C15.6313 8.91721 15.7376 8.77718 15.8807 8.70655C15.9461 8.67417 16.0182 8.65633 16.0947 8.65633H19.1978C19.5653 8.65633 19.9085 8.68126 20.2217 8.73356C20.3112 8.74834 20.3981 8.76545 20.483 8.78463C20.5674 8.80418 20.6497 8.82606 20.7295 8.85001C20.7691 8.86223 20.8083 8.87493 20.8468 8.88752C21.0008 8.94031 21.144 9.00275 21.276 9.07472C21.4314 8.05085 21.2747 7.35373 20.7392 6.72248C20.1486 6.02743 19.083 5.73001 17.7192 5.73001H13.7601C13.4816 5.73001 13.244 5.93933 13.2009 6.22429L11.5519 17.0279C11.5194 17.2416 11.6789 17.4344 11.8875 17.4344H14.3316L15.6055 9.08865Z" fill="white"/> 10326<rect x="0.5" y="0.5" width="33" height="23" rx="3.5" stroke="white"/> 10327<title>payment/paypal-color-false-bg-negative</title></svg> 10328 10329 <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 34 24" fill="none" class="cmsb34-text-white" role="img"> 10330<path fill-rule="evenodd" clip-rule="evenodd" d="M17.3502 10.8603C17.1195 10.8603 16.9331 11.0467 16.9331 11.2686V14.3488C16.9331 14.5795 17.1195 14.7659 17.3502 14.7659C17.581 14.7659 17.7674 14.5795 17.7674 14.3488V11.2686C17.7674 11.0467 17.581 10.8603 17.3502 10.8603ZM17.3502 9.32473C17.0929 9.32473 16.8799 9.53776 16.8799 9.79518C16.8799 10.0526 17.0929 10.2745 17.3502 10.2745C17.6076 10.2745 17.8206 10.0615 17.8206 9.79518C17.8206 9.53776 17.6076 9.32473 17.3502 9.32473ZM21.415 11.2686C21.415 11.0112 21.2109 10.9136 21.0245 10.9136H18.9566C18.7525 10.9136 18.5928 11.0733 18.5928 11.2686C18.5928 11.4728 18.7525 11.6326 18.9566 11.6326H20.3145L18.5572 14.0825C18.504 14.1535 18.4774 14.2511 18.4774 14.331C18.4774 14.5884 18.6815 14.7304 18.859 14.7304H21.0512C21.2553 14.7304 21.415 14.5707 21.415 14.3665C21.415 14.1624 21.2553 14.0026 21.0512 14.0026H19.5779L21.2996 11.6059C21.3884 11.4817 21.415 11.3752 21.415 11.2686ZM15.3267 13.2037C15.3267 13.7097 15.1048 14.0204 14.599 14.0204C14.0931 14.0204 13.8801 13.7097 13.8801 13.2037V11.6326H14.6345C15.2468 11.6326 15.3267 11.9699 15.3267 12.3427V13.2037ZM16.161 12.325C16.161 11.4639 15.7083 10.9047 14.6522 10.9047H13.889V9.74192C13.889 9.51114 13.7026 9.32473 13.4807 9.32473C13.25 9.32473 13.0636 9.51114 13.0636 9.74192V13.2037C13.0636 14.0647 13.5251 14.766 14.6167 14.766C15.6995 14.766 16.1698 14.0559 16.1698 13.2037V12.3427V12.325H16.161ZM24.6722 10.8603C24.4414 10.8603 24.255 11.0467 24.255 11.2775V13.2037C24.255 13.7097 24.0332 14.0203 23.5273 14.0203C23.0214 14.0203 22.8084 13.7097 22.8084 13.2037V11.2775C22.8084 11.0467 22.622 10.8603 22.4002 10.8603C22.1694 10.8603 21.983 11.0467 21.983 11.2775V13.2037C21.983 14.0647 22.4445 14.7659 23.5362 14.7659C24.6189 14.7659 25.0893 14.0558 25.0893 13.2037V11.2775C25.0804 11.0467 24.894 10.8603 24.6722 10.8603ZM31 12.4315C31 11.5705 30.6008 10.8692 29.5181 10.8692C29.0299 10.8692 28.6838 11.0113 28.444 11.2509C28.2045 11.0201 27.8584 10.8692 27.3702 10.8692C26.2874 10.8692 25.888 11.5793 25.888 12.4315V14.3577C25.888 14.5884 26.0744 14.7749 26.2963
1033014.7749C26.527 14.7749 26.7134 14.5884 26.7134 14.3577V12.4315C26.7134 11.9255 26.8731 11.6149 27.3702 11.6149C27.876 11.6149 28.027 11.9255 28.027 12.4315V14.3577C28.027 14.5884 28.2134 14.7749 28.4351 14.7749C28.6659 14.7749 28.8524 14.5884 28.8524 14.3577V12.4315C28.8524 11.9255 29.012 11.6149 29.5091 11.6149C30.0149 11.6149 30.1659 11.9255 30.1659 12.4315V14.3577C30.1659 14.5884 30.3521 14.7749 30.574 14.7749C30.8049 14.7749 30.9913 14.5884 30.9913 14.3577L31 12.4315ZM5.47539 10.8692C5.76827 11.0822 6.17653 11.0201 6.38952 10.7272L7.15279 9.67089C7.36579 9.37797 7.30366 8.96965 7.01079 8.75662C6.71791 8.54359 6.30966 8.60572 6.09665 8.89864L5.32452 9.95494C5.12039 10.2479 5.18252 10.6562 5.47539 10.8692ZM8.97217 9.37797C8.67928 9.16494 8.27103 9.22707 8.05803 9.51999L4.98725 13.7452C4.77425 14.0381 4.83638 14.4464 5.12926 14.6594C5.42213 14.8725 5.83039 14.8103 6.04339 14.5174L9.11416 10.2922C9.33604 9.99932 9.26503 9.591 8.97217 9.37797ZM5.18252 9.04067C5.39552 8.74775 5.33339 8.33943 5.04051 8.1264C4.74764 7.91337 4.33938 7.9755 4.12638 8.26842C3.91338 8.56134 3.9755 8.96966 4.26838 9.18269C4.56126 9.39573 4.96951 9.33359 5.18252 9.04067ZM9.84193 14.8459C9.54906 14.6328 9.14081 14.695 8.92781 14.9879C8.71481 15.2808 8.77692 15.6891 9.0698 15.9021C9.36269 16.1152 9.77094 16.053 9.98394 15.7601C10.1969 15.4672 10.1348 15.0589 9.84193 14.8459ZM8.6438 13.1682C8.35094 12.9552 7.94268 13.0173 7.72968 13.3102L6.95754 14.3665C6.74454 14.6594 6.80667 15.0678 7.09953 15.2808C7.39242 15.4938 7.80067 15.4317 8.01367 15.1388L8.78582 14.0825C8.99882 13.7896 8.93669 13.3812 8.6438 13.1682Z" fill="white"/> 10331<rect x="0.5" y="0.5" width="33" height="23" rx="3.5" stroke="white"/> 10332<title>payment/bizum-color-false-bg-negative</title></svg> 10333 10334 <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 34 24" fill="none" class="cmsb34-text-white" role="img"> 10335<path fill-rule="evenodd" clip-rule="evenodd" d="M9.44928 8.34316C9.1639 8.69506 8.70729 8.97261 8.25068 8.93296C8.1936 8.45715 8.41715 7.95161 8.67875 7.63936C8.96413 7.27755 9.46355 7.01983 9.86784 7C9.91541 7.49563 9.72991 7.98135 9.44928 8.34316ZM9.86297 9.02712C9.46071 9.003 9.09366 9.15319 8.79718 9.2745C8.60639 9.35256 8.44483 9.41867 8.32191 9.41867C8.18397 9.41867 8.01574 9.34903 7.82685 9.27084C7.57935 9.16838 7.29638 9.05124 6.99964 9.05686C6.31948 9.06677 5.68688 9.46823 5.33967 10.1076C4.62621 11.3863 5.15417 13.2796 5.84384 14.3204C6.18155 14.8359 6.58584 15.4009 7.11855 15.3811C7.35291 15.3719 7.5215 15.2973 7.69597 15.2202C7.89683 15.1314 8.10549 15.0391 8.43131 15.0391C8.74582 15.0391 8.94536 15.129 9.1369 15.2152C9.31903 15.2972 9.49393 15.376 9.75358 15.3712C10.3053 15.3613 10.6525 14.8557 10.9902 14.3403C11.3547 13.7871 11.5148 13.2471 11.5391 13.1652L11.542 13.1557C11.5414 13.1551 11.5369 13.153 11.5289 13.1492C11.4071 13.0911 10.476 12.6469 10.467 11.4557C10.4581 10.4559 11.2056 9.94935 11.3233 9.86961C11.3304 9.86477 11.3353 9.86149 11.3375 9.85978C10.8618 9.12625 10.1198 9.04695 9.86297 9.02712ZM13.6824 7.5898V15.3167H14.8334V12.675H16.4268C17.8822 12.675 18.9049 11.6341 18.9049 10.1274C18.9049 8.62071 17.9013 7.5898 16.4648 7.5898H13.6824ZM14.8333 8.60088H16.1603C17.1591 8.60088 17.7299 9.15599 17.7299 10.1324C17.7299 11.1088 17.1591 11.6688 16.1555 11.6688H14.8333V8.60088ZM21.0071 15.3761C21.7301 15.3761 22.4007 14.9945 22.7051 14.3898H22.7289V15.3167H23.7943V11.4706C23.7943 10.3554 22.9382 9.63675 21.6207 9.63675C20.3983 9.63675 19.4946 10.3653 19.4613 11.3665H20.4982C20.5838 10.8907 21.0071 10.5784 21.5874 10.5784C22.2913
1033510.5784 22.6861 10.9204 22.6861 11.5499V11.9761L21.2497 12.0653C19.9132 12.1496 19.1902 12.7196 19.1902 13.7108C19.1902 14.712 19.9369 15.3761 21.0071 15.3761ZM21.3163 14.4592C20.7028 14.4592 20.3127 14.1519 20.3127 13.6811C20.3127 13.1954 20.6885 12.9129 21.4067 12.8683L22.6862 12.784V13.2202C22.6862 13.9438 22.0964 14.4592 21.3163 14.4592ZM25.2165 17.4181C26.339 17.4181 26.867 16.9721 27.3283 15.619L29.3498 9.7111H28.1797L26.8242 14.2758H26.8004L25.4448 9.7111H24.2415L26.1916 15.3365L26.0869 15.6785C25.9109 16.2584 25.6256 16.4814 25.1166 16.4814C25.0263 16.4814 24.8503 16.4715 24.7789 16.4616V17.3884C24.8455 17.4082 25.1309 17.4181 25.2165 17.4181Z" fill="white"/> 10336<rect x="0.5" y="0.5" width="33" height="23" rx="3.5" stroke="white"/> 10337<title>payment/apple-pay-color-false-bg-negative</title></svg> 10338 10339 <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 34 24" fill="none" class="cmsb34-text-white" role="img"> 10340<path fill-rule="evenodd" clip-rule="evenodd" d="M16.0579 15.528V12.5933H17.5725C18.1931 12.5933 18.717 12.3854 19.1441 11.9752L19.2466 11.8712C20.0266 11.022 19.9754 9.69913 19.1441 8.91347C18.7284 8.49754 18.159 8.27224 17.5725 8.28379H15.1411V15.528H16.0579ZM16.0579 11.7036V9.17337H17.5955C17.9258 9.17337 18.239 9.30046 18.4725 9.53154C18.968 10.0168 18.9794 10.8256 18.501 11.3281C18.2675 11.5765 17.9372 11.7152 17.5955 11.7036H16.0579ZM23.5228 10.9585C23.1299 10.5945 22.5947 10.4097 21.9171 10.4097C21.0459 10.4097 20.3911 10.7332 19.9583 11.3744L20.7669 11.8885C21.063 11.4495 21.4673 11.23 21.9797 11.23C22.3043 11.23 22.6175 11.3513 22.8623 11.5708C23.1015 11.7788 23.2381 12.0792 23.2381 12.3969V12.6106C22.8851 12.4142 22.441 12.3103 21.8943 12.3103C21.2566 12.3103 20.7441 12.4604 20.3626 12.7666C19.9811 13.0728 19.7875 13.4772 19.7875 13.9913C19.7761 14.4592 19.9754 14.9041 20.3285 15.2045C20.6872 15.528 21.1427 15.6897 21.6779 15.6897C22.31 15.6897 22.8111 15.4067 23.1926 14.8405H23.2324V15.528H24.1093V12.472C24.1093 11.8308 23.9157 11.3224 23.5228 10.9585ZM21.0347 14.6152C20.8467 14.4766 20.7328 14.2513 20.7328 14.0087C20.7328 13.7372 20.8581 13.5119 21.103 13.3328C21.3536 13.1537 21.6668 13.0613 22.037 13.0613C22.5495 13.0555 22.9482 13.171 23.2329 13.4021C23.2329 13.7949 23.0792 14.1358 22.7773 14.4246C22.504 14.7019 22.1338 14.8579 21.7465 14.8579C21.4903 14.8636 21.2397 14.777 21.0347 14.6152ZM26.0796 17.7058L29.143 10.5714H28.1466L26.7287 14.13H26.7116L25.2596 10.5714H24.2632L26.2732 15.2102L25.1344 17.7058H26.0796Z" fill="white"/> 10341<path d="M12.893 11.9579C12.893 11.6748 12.8702 11.3918 12.8247 11.1145H8.95837V12.7147H11.1734C11.0823 13.2288 10.7862 13.691 10.3534 13.9798V15.0196H11.6745C12.4488 14.2975 12.893 13.2288 12.893 11.9579Z" fill="white"/> 10342<path d="M8.95854 16.0248C10.0632 16.0248 10.997 15.6551 11.6746 15.0197L10.3536 13.9798C9.98347 14.234 9.51086 14.3784 8.95854 14.3784C7.88805 14.3784 6.98269 13.6448 6.65813 12.6627H5.29724V13.7372C5.99192 15.141 7.40975 16.0248 8.95854 16.0248Z" fill="white"/> 10343<path d="M6.65822 12.6627C6.48737 12.1486 6.48737 11.5882 6.65822 11.0683V9.99956H5.29712C4.71053 11.1723 4.71053 12.5587 5.29712 13.7314L6.65822 12.6627Z" fill="white"/> 10344<path d="M8.95854 9.35253C9.54503 9.34098 10.1087 9.56628 10.5301 9.97643L11.7031 8.7864C10.9572 8.08162 9.97778 7.69457 8.95854 7.70612C7.40975 7.70612 5.99192 8.59576 5.29724 9.99954L6.65813 11.074C6.98269 10.0862 7.88805 9.35253 8.95854 9.35253Z" fill="white"/> 10345<rect x="0.5" y="0.5" width="33" height="23" rx="3.5" stroke="white"/> 10346<title>payment/google-pay-color-false-bg-negative</title></svg> 10347 10348 <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 34 24" fill="none" class="cmsb34-text-white" role="img"> 10349<path fill-rule="evenodd" clip-rule="evenodd" d="M21.5276 9.86208H10.7241C10.5321 9.86208 10.3479 9.78579 10.2121 9.64999C10.0763 9.51418 10 9.33 10 9.13794C10 8.94589 10.0763 8.7617 10.2121 8.6259C10.3479 8.4901 10.5321 8.41381 10.7241 8.41381H21.5276L20.35 7.23621C20.2142 7.1004 20.1379 6.91621 20.1379 6.72416C20.1379 6.5321 20.2142 6.34791 20.35 6.2121C20.4858 6.07629 20.67 6 20.862 6C21.0541 6 21.2383 6.07629 21.3741 6.2121L23.7879 8.62589C23.8551 8.69313 23.9085 8.77296 23.9449 8.86082C23.9813 8.94868 24 9.04285 24 9.13794C24 9.23304 23.9813 9.32721 23.9449 9.41507C23.9085 9.50293 23.8551 9.58276 23.7879 9.65L21.3741 12.0638C21.2383 12.1996 21.0541 12.2759 20.862 12.2759C20.67 12.2759 20.4858 12.1996 20.35 12.0638C20.2142 11.928 20.1379 11.7438 20.1379 11.5517C20.1379 11.3597 20.2142 11.1755 20.35 11.0397L21.5276 9.86208ZM12.4724 13.7241H23.2759C23.4679 13.7241 23.6521 13.8004 23.7879 13.9362C23.9237 14.072 24
1034914.2562 24 14.4483C24 14.6403 23.9237 14.8245 23.7879 14.9603C23.6521 15.0961 23.4679 15.1724 23.2759 15.1724H12.4724L13.65 16.35C13.7858 16.4858 13.8621 16.67 13.8621 16.8621C13.8621 17.0541 13.7858 17.2383 13.65 17.3741C13.5142 17.5099 13.33 17.5862 13.138 17.5862C12.9459 17.5862 12.7617 17.5099 12.6259 17.3741L10.2121 14.9603C10.1449 14.8931 10.0915 14.8133 10.0551 14.7254C10.0187 14.6375 10 14.5434 10 14.4483C10 14.3532 10.0187 14.259 10.0551 14.1712C10.0915 14.0833 10.1449 14.0035 10.2121 13.9362L12.6259 11.5224C12.7617 11.3866 12.9459 11.3103 13.138 11.3103C13.33 11.3103 13.5142 11.3866 13.65 11.5224C13.7858 11.6582 13.8621 11.8424 13.8621 12.0345C13.8621 12.2265 13.7858 12.4107 13.65 12.5465L12.4724 13.7241Z" fill="white"/> 10350<rect x="0.5" y="0.5" width="33" height="23" rx="3.5" stroke="white"/> 10351<title>payment/transferencia-color-false-bg-negative</title></svg> 10352 10353 </div> 10354 </div> 10355 </div> 10356 10357 <div class="o-grid-child" style="--o-grid-area: 7 / 1 / 8 / 2; --o-grid-area-tablet: 7 / 1 / 8 / 2; --o-grid-area-desktop: 2 / 4 / 3 / 5;"> 10358 <div class="cmsb34-lg:pt-12 cmsb34-lg:pl-10 cmsb34-lg:pr-10 cmsb34-h-full cmsb34-lg:border-l cmsb34-border-white/10"> 10359 <span class="cmsb34-font-bold cmsb34-text-white cmsb34-uppercase cmsb34-block cmsb34-mb-4 cmsb34-text-lg"><span>SÃGUENOS</span></span> 10360 <div class="cmsb34-flex cmsb34-flex-nowrap cmsb34-gap-4 cmsb34-text-white cmsb34-justify-start"> 10361 <a href="https://www.instagram.com/serratsconservas/" class="cmsb34-hover:opacity-80 cmsb34-transition-opacity" aria-label="Instagram"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 101 100" fill="none" role="img"> 10362<path fill-rule="evenodd" clip-rule="evenodd" d="M50.6272 27.0833C44.4033 27.0833 43.6222 27.1105 41.1778 27.2217C38.7381 27.3335 37.0728 27.7197 35.6157 28.2864C34.1084 28.8718 32.8298 29.6548 31.556 30.929C30.2813 32.2028 29.4983 33.4814 28.911 34.9882C28.3429 36.4458 27.9562 38.1115 27.8464 40.5503C27.737 42.9948 27.7084 43.7763 27.7084 50.0002C27.7084 56.224 27.7361 57.0027 27.8468 59.4472C27.959 61.887 28.3453 63.552 28.9115 65.0094C29.4973 66.5165 30.2803 67.7952 31.5546 69.0688C32.8279 70.3436 34.1065 71.1285 35.6128 71.7139C37.0709 72.2808 38.7367 72.6668 41.1759 72.7785C43.6203 72.8898 44.4009 72.9171 50.6243 72.9171C56.8486 72.9171 57.6273 72.8898 60.0718 72.7785C62.5116 72.6668 64.1788 72.2808 65.6369 71.7139C67.1437 71.1285 68.4202 70.3436 69.6935 69.0688C70.9682 67.7952 71.7513 66.5165 72.3386 65.0097C72.9018 63.552 73.2885 61.8863 73.4031 59.4477C73.5131 57.0032 73.5417 56.224 73.5417 50.0002C73.5417 43.7763 73.5131 42.9953 73.4031 40.5508C73.2885 38.1111 72.9018 36.4458 72.3386 34.9886C71.7513 33.4814 70.9682 32.2028 69.6935 30.929C68.4188 29.6543 67.144 28.8713 65.6355 28.2864C64.1745 27.7197 62.5081 27.3335 60.0685 27.2217C57.624 27.1105 56.8458 27.0833 50.62 27.0833H50.6272ZM49.8627 31.2129L50.627 31.2131C56.7458 31.2131 57.471 31.235 59.8873 31.3449C62.1217 31.447 63.3345 31.8204 64.1423 32.1341C65.2119 32.5494 65.9742 33.046 66.7759 33.848C67.578 34.6501 68.0743 35.414 68.4907 36.4835C68.8044 37.2904 69.1782 38.5031 69.2799 40.7374C69.3899 43.1533 69.4135 43.879 69.4135 49.9949C69.4135 56.1109 69.3899 56.8366 69.2799 59.2524C69.1779 61.4866 68.8044 62.6994 68.4907 63.5062C68.0754 64.5757 67.578 65.3374 66.7759 66.1391C65.9738 66.9412 65.2122 67.4375 64.1423 67.8528C63.3352 68.1679 62.1217 68.5403 59.8873 68.6427C57.4715 68.7523 56.7458 68.7763 50.627 68.7763C44.5077 68.7763 43.7825 68.7523 41.3667 68.6427C39.1323 68.5396 37.9196 68.1661 37.1113 67.8525C36.0418 67.4371 35.2779 66.9405 34.4759 66.1384C33.6737 65.3363 33.1772 64.5743 32.7609 63.5044C32.4472 62.6977 32.0734 61.4849 31.9717 59.2505C31.8619 56.8347 31.8399 56.109 31.8399 49.9892C31.8399 43.8694 31.8619 43.1476 31.9717 40.7317C32.0739 38.4973 32.4472 37.2846 32.7609 36.4768C33.1763 35.4073 33.6737 34.6435 34.4759 33.8414C35.2779 33.0393 36.0418 32.5427 37.1113 32.1264C37.9191 31.8113 39.1323 31.4389 41.3667 31.3363C43.4803 31.2408 44.2996 31.2121 48.5682 31.2074C48.5698 31.2074 48.5712 31.2086 48.5712 31.2102V31.2102C48.5712 31.2118 48.5724 31.2131 48.574 31.2131C48.9723 31.2125 49.4005 31.2127 49.8627 31.2129ZM60.1098 37.7673C60.1098 36.2486 61.3416 35.0183 62.8597 35.0183C64.3779 35.0183 65.61 36.2491 65.61 37.7673C65.61 39.2856 64.3779 40.5174 62.8597 40.5174C61.3416 40.5174 60.1098 39.2856 60.1098 37.7673ZM50.6267 38.2314C44.1276 38.2316 38.8584 43.501 38.8584 50.0002C38.8584 56.4995 44.1279 61.7667 50.6272 61.7667C57.1265 61.7667 62.3942 56.4995 62.3942 50.0002C62.3942 43.5009 57.1261 38.2314 50.6267 38.2314ZM58.2663 50.0002C58.2663 45.7811 54.8459 42.3612 50.6273 42.3612C46.4082 42.3612 42.9883 45.7811 42.9883 50.0002C42.9883 54.2188 46.4082 57.6392 50.6273 57.6392C54.8459 57.6392 58.2663 54.2188 58.2663 50.0002Z" fill="currentColor"/> 10363<title>rrss/instagram</title></svg> 10364</a> 10365 <a href="https://www.linkedin.com/company/conservas-serrats/" class="cmsb34-hover:opacity-80 cmsb34-transition-opacity" aria-label="LinkedIn"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 101 100" fill="none" role="img"> 10366<path d="M68.9998 56.2292V70.6808H60.6212V57.1977C60.6212 53.8123 59.4115 51.5003 56.3778 51.5003C54.0627 51.5003 52.6874 53.0568 52.0801 54.564C51.8595 55.1026 51.8026 55.8506 51.8026 56.606V70.6802H43.4233C43.4233 70.6802 43.5358 47.8443 43.4233 45.4805H51.8032V49.0515C51.7864 49.0797 51.7626 49.1071 51.7476 49.134H51.8032V49.0515C52.9167 47.3382 54.9025 44.8888 59.3546 44.8888C64.8671 44.8888 68.9998 48.4904 68.9998 56.2292ZM34.6579 33.3333C31.7917 33.3333 29.9165 35.2148 29.9165 37.6867C29.9165 40.1061 31.7373 42.0419 34.5479 42.0419H34.6023C37.5247 42.0419 39.3418 40.1061 39.3418 37.6867C39.2862 35.2148 37.5247 33.3333 34.6579 33.3333ZM30.4145 70.6808H38.7907V45.4805H30.4145V70.6808Z" fill="currentColor"/> 10367<title>rrss/linkedin</title></svg> 10368</a> 10369 <a href="https://www.youtube.com/user/serratsconservas/" class="cmsb34-hover:opacity-80 cmsb34-transition-opacity" aria-label="YouTube"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 101 100" fill="none" role="img"> 10370<path fill-rule="evenodd" clip-rule="evenodd" d="M70.2841 34.4062C72.4357 34.9966 74.1298 36.7361 74.7048 38.9451C75.7498 42.9486 75.7498 51.3021 75.7498 51.3021C75.7498 51.3021 75.7498 59.6552 74.7048 63.6591C74.1298 65.8681 72.4357 67.6076 70.2841 68.1982C66.3853 69.2708 50.7498 69.2708 50.7498 69.2708C50.7498 69.2708 35.1143 69.2708 31.2151 68.1982C29.0637 67.6076 27.3694 65.8681 26.7944 63.6591C25.7498 59.6552 25.7498 51.3021 25.7498 51.3021C25.7498 51.3021 25.7498 42.9486 26.7944 38.9451C27.3694 36.7361 29.0637 34.9966 31.2151 34.4062C35.1143 33.3333 50.7498 33.3333 50.7498 33.3333C50.7498 33.3333 66.3853 33.3333 70.2841 34.4062ZM46.0621 44.271V59.896L58.5621 52.0838L46.0621 44.271Z" fill="currentColor"/> 10371<title>
10371rrss/youtube</title></svg> 10372</a> 10373 <a href="https://www.facebook.com/conservas.serrats" class="cmsb34-hover:opacity-80 cmsb34-transition-opacity" aria-label="Facebook"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 100 100" fill="none" role="img"> 10374<path d="M59.3989 49.8084H52.6696V74.4616H42.474V49.8084H37.625V41.1443H42.474V35.5376C42.474 31.5283 44.3785 25.25 52.7603 25.25L60.3125 25.2816V33.6916H54.8329C53.9341 33.6916 52.6702 34.1407 52.6702 36.0533V41.1524H60.2896L59.3989 49.8084Z" fill="currentColor"/> 10375<title>rrss/facebook</title></svg> 10376</a> 10377 <a href="https://www.tiktok.com/@serratsconservas" class="cmsb34-hover:opacity-80 cmsb34-transition-opacity" aria-label="TikTok"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 26 26" fill="none" role="img"> 10378 <path d="M16.5256 9.04855C16.4461 9.00698 16.3687 8.96141 16.2936 8.91201C16.0754 8.76615 15.8754 8.59429 15.6978 8.40012C15.2534 7.88599 15.0874 7.36441 15.0263 6.99923H15.0288C14.9777 6.69612 14.9988 6.5 15.002 6.5H12.978V14.4138C12.978 14.52 12.978 14.625 12.9736 14.7288C12.9736 14.7417 12.9723 14.7536 12.9716 14.7675C12.9716 14.7732 12.9716 14.7792 12.9704 14.7851C12.9704 14.7866 12.9704 14.7881 12.9704 14.7896C12.949 15.0736 12.859 15.3479 12.7083 15.5884C12.5575 15.8289 12.3506 16.0282 12.1057 16.1689C11.8505 16.3157 11.5619 16.3927 11.2683 16.3923C10.3252 16.3923 9.56097 15.6148 9.56097 14.6546C9.56097 13.6943 10.3252 12.9168 11.2683 12.9168C11.4468 12.9166 11.6242 12.945 11.7939 13.001L11.7963 10.9171C11.2811 10.8498 10.7577 10.8912 10.259 11.0387C9.76042 11.1862 9.29744 11.4366 8.89931 11.7741C8.55046 12.0806 8.25717 12.4463 8.03266 12.8547C7.94722 13.0037 7.62486 13.6022 7.58583 14.5736C7.56127 15.125 7.72503 15.6962 7.8031 15.9323V15.9373C7.85221 16.0763 8.04248 16.5507 8.35256 16.9506C8.6026 17.2714 8.89801 17.5533 9.22928 17.787V17.782L9.23419 17.787C10.214 18.4603 11.3004 18.4161 11.3004 18.4161C11.4885 18.4084 12.1185 18.4161 12.8339 18.0732C13.6274 17.6932 14.0791 17.1269 14.0791 17.1269C14.3677 16.7886 14.5972 16.403 14.7577 15.9867C14.9409 15.4999 15.002 14.916 15.002 14.6826V10.4842C15.0265 10.4991 15.3536 10.7178 15.3536 10.7178C15.3536 10.7178 15.8247 11.0231 16.5598 11.222C17.0871 11.3635 17.7976 11.3933 17.7976 11.3933V9.36159C17.5487 9.3889 17.0432 9.30946 16.5256 9.04855Z" fill="currentColor"/> 10379<title>rrss/tiktok</title></svg> 10380</a> 10381 <a href="https://es.pinterest.com/ConservasSerrats/" class="cmsb34-hover:opacity-80 cmsb34-transition-opacity" aria-label="Pinterest"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 101 100" fill="none" role="img"> 10382<path d="M54.5 62.185C51.7287 61.9706 50.5642 60.5964 48.3909 59.2771C47.1964 65.5443 45.7366 71.5521 41.4127 74.6907C40.0764 65.2183 43.3717 58.1035 44.9021 50.5516C42.2935 46.1604 45.2158 37.3219 50.7178 39.4998C57.4895 42.1777 44.8551 55.8276 53.3368 57.5324C62.1917 59.3124 65.8066 42.1679 60.315 36.5913C52.3808 28.5402 37.2202 36.4084 39.0845 47.9339C39.5386 50.7516 42.4504 51.6069 40.2476 55.495C35.1697 54.3704 33.655 50.3654 33.8497 45.0261C34.164 36.2862 41.7028 30.1666 49.2645 29.3198C58.8277 28.2494 67.8035 32.8314 69.0425 41.8268C70.4363 51.9794 64.7251 62.9743 54.5 62.185Z" fill="currentColor"/> 10383<title>rrss/pinterest</title></svg> 10384</a> 10385 </div> 10386 </div> 10387 </div> 10388 10389 10390 10391 10392 10393 10394 10395 <div class="o-grid-child" style="--o-grid-area: 8 / 1 / 9 / 2; --o-grid-area-tablet: 8 / 1 / 9 / 2; --o-grid-area-desktop: 3 / 3 / 4 / 4;"> 10396 <div class="cmsb34-lg:pl-10 cmsb34-lg:pr-10 cmsb34-h-full cmsb34-lg:border-l cmsb34-border-white/10"> 10397 <div class="cmsb34-lg:py-4"> 10398 10399 <div x-data="{ open: false }" x-defer="intersect" class="Magento\Store\Block\Switcher"> 10400 <div class="cmsb34-hidden"> 10401 Lenguaje </div> 10402 <div class="cmsb34-relative"> 10403 <span @click.prevent="open = !open" 10404 @click.outside="open = false" 10405 @keydown.window.escape="open = false" 10406 class="cmsb34-flex flex-row cmsb34-flex-nowrap cmsb34-items-center cursor-pointer" 10407 aria-haspopup="true" 10408 aria-expanded="true" 10409 role="button" 10410 >
10411 <span><img class="h-4 w-4 mr-2.5" width="16" height="16" alt="Español" src="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/images/store/es_es.svg" @error="$el.style.display='none'" loading="lazy"/></span> 10412 <span class="mr-2 ">Español</span> 10413 <span class="cmsb34-transition-transform" :class="{'cmsb34-rotate-180': open}"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-4 h-4" width="24" height="24" role="img"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"/><title>caret-down</title></svg> 10414</span> 10415 </span> 10416 <nav x-cloak="" 10417 x-show="open" 10418 class="lg:overflow-auto lg:absolute z-20 w-56 rounded-sm shadow-lg origin-top-left bg-container-lighter cmsb34-text-black my-2 sm:w-48"> 10419 <div class="divide-y divide-gray-light" role="menu" aria-orientation="vertical" aria-labelledby="options-menu"> 10420 <span class="cursor-pointer cmsb34-flex flex-row cmsb34-items-center cmsb34-text-lg cmsb34-uppercase flex-no-wrap cmsb34-px-4 py-2 hover:bg-gray-light" @click="openLink(atob('aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvc3RvcmVzL3N0b3JlL3JlZGlyZWN0L19fX3N0b3JlL2VzX2V1L19fX2Zyb21fc3RvcmUvZXNfZXMvdWVuYy9hSFIwY0hNNkx5OTNkM2N1YzJWeWNtRjBjeTVqYjIwdlpYTmZaWFV2WTI5dGNISmhjaTFpYjI1cGRHOHRaR1ZzTFc1dmNuUmwv'), '_self')" x-data="" x-defer="intersect"> 10421 <span class="w-4"> 10422 <img 10423 class="h-4 w-4 mr-2.5" 10424 width="16" 10425 height="16" 10426 alt="Euskera" 10427 src="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/images/store/es_eu.svg" 10428 @error="$el.style.display='none'" 10429 loading="lazy" 10430 /> 10431 </span> 10432 <p class="">Euskera</p> </span> 10433 </div> 10434 </nav> 10435 </div> 10436 </div> 10437 10438 </div> 10439 </div> 10440 </div> 10441 10442 <div class="o-grid-child" style="--o-grid-area: 11 / 1 / 12 / 2; --o-grid-area-tablet: 11 / 1 / 12 / 2; --o-grid-area-desktop: 3 / 4 / 4 / 5;"> 10443 <div class="cmsb34-lg:pl-10 cmsb34-lg:pr-10 cmsb34-flex cmsb34-items-end cmsb34-h-full cmsb34-justify-center cmsb34-lg:justify-start cmsb34-lg:border-l cmsb34-border-white/10"> 10444 <span class="cmsb34-text-base cmsb34-py-4 cmsb34-text-white/50"><span>© 2026 Conservas Serrats</span></span> 10445 </div> 10446 </div> 10447 </div> 10448 </div> 10449 </div> 10450</section> </div> 10451 </div> 10452 </div></footer>
10452<script> 10453 class GTMEventTracker { 10454 constructor(eventsToTrack) { 10455 this.eventsToTrack = eventsToTrack; 10456 this.initClickListener(); 10457 this.initViewListener(); 10458 } 10459 10460 initClickListener() { 10461 document.body.addEventListener('click', (event) => { 10462 this.checkEventInfo(event); 10463 }, true); 10464 } 10465 10466 initViewListener() { 10467 let self = this; 10468 let intersectionOptions = { 10469 root: document, 10470 rootMargin: "0px", 10471 threshold: 1.0, 10472 }; 10473 10474 this.eventsToTrack.forEach(function(eventToTrack) { 10475 if (eventToTrack.trigger_type !== "view") { 10476 return; 10477 } 10478 10479 document.querySelectorAll(eventToTrack.query_selector).forEach(function (element) { 10480 let intersectionObserver = new IntersectionObserver(function (entries) { 10481 let observer = this; 10482 entries.forEach((entry) => { 10483 if (entry.isIntersecting) { 10484 self.dispatchEvent(eventToTrack); 10485 observer.unobserve(element); 10486 } 10487 }); 10488 }, intersectionOptions); 10489 intersectionObserver.observe(element); 10490 }) 10491 }); 10492 } 10493 10494 checkEventInfo(triggeredEvent) { 10495 let self = this; 10496 this.eventsToTrack.forEach(function(eventToTrack) { 10497 if (eventToTrack.trigger_type === triggeredEvent.type && 10498 triggeredEvent.target.closest(eventToTrack.query_selector)) { 10499 self.dispatchEvent(eventToTrack); 10500 } 10501 }); 10502 } 10503 10504 dispatchEvent(eventToTrack) { 10505 window.dispatchEvent(new CustomEvent('datalayer-event', this.prepareGtmEventObject(eventToTrack))); 10506 } 10507 10508 prepareGtmEventObject(eventToTrack) 10509 { 10510 return { 10511 detail: { 10512 event: eventToTrack.type, 10513 element: { 10514 'category': eventToTrack.category, 10515 'action': eventToTrack.action, 10516 'label': eventToTrack.label, 10517 } 10518 } 10519 }; 10520 } 10521 } 10522 10523 let eventsToTrack = [{"trigger_type":"click","type":"click-contact-footer","page":"catalog_category_view","category":"click-contact-footer","action":"click-contact-footer","label":"click-contact-footer","query_selector":".sb-4845471-footercontact"}]; 10524 new GTMEventTracker(eventsToTrack); 10525</script>
10525 10526
10527<script> 10528 let SnapSlider = class { 10529 constructor(el, { 10530 labelSepparator = 'de', 10531 autoPager, 10532 groupPager 10533 } = {}) { 10534 this.el = el; 10535 this.track = this.el.querySelector("[data-track]"); 10536 if (!this.track) { 10537 console.warn( 10538 "No Slider track defined, reverting back to CSS slider.\nPlease create a wrapper for your slides with the attribute data-track", 10539 this.el 10540 ); 10541 return; 10542 } 10543 this.initialLoad = true; 10544 this.slides = []; 10545 this.inViewObserver; 10546 this.mutationObserver; 10547 this.resizeObserver; 10548 this.pager = this.el.querySelector("[data-pager]"); 10549 this.navBtns = Array.from( 10550 this.el.querySelectorAll("[data-next], [data-prev]") 10551 ); 10552 this.slideLabelSepparator = this.el.dataset.slideLabelSepparator || labelSepparator; 10553 this.useAutoPager = autoPager || this.el.hasAttribute("data-auto-pager") || false; 10554 this.useGroupPager = groupPager || this.el.hasAttribute("data-group-pager") || false; 10555 this.sliderLabel = this.el.hasAttribute("aria-label") && this.el.getAttribute("aria-label").toLowerCase().trim().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, ""); 10556 this.sliderId = this.el.id || this.sliderLabel || "slider"; 10557 this.markerIdName = "data-target-id"; 10558 this.pagerClasses = this.el.dataset.pagerClass || "snap-pager"; 10559 this.markerClasses = this.el.dataset.markerClass || "snap-marker"; 10560 this.init(); 10561 } 10562 init() { 10563 this.setupSlides(); 10564 this.setupNav(); 10565 if (this.useAutoPager) { 10566 this.createPager(); 10567 } else { 10568 this.setupPager(); 10569 } 10570 this.setupObservers(); 10571 this.setupMutationObserver(); 10572 this.setupResizeObserver(); 10573 this.el.addEventListener("click", this.eventHandler.bind(this)); 10574 this.el.addEventListener("keydown", this.eventHandler.bind(this)); 10575 } 10576 destroy() { 10577 this.inViewObserver?.disconnect(); 10578 this.mutationObserver?.disconnect(); 10579 this.resizeObserver?.disconnect(); 10580 this.el.removeEventListener("click", this.eventHandler.bind(this)); 10581 this.el.removeEventListener("keydown", this.eventHandler.bind(this)); 10582 } 10583 roundUpIfGreaterThan(number, min = 8) { 10584 const decimalPart = number - Math.floor(number); 10585 return decimalPart >= min ? Math.ceil(number) : Math.floor(number); 10586 } 10587 getInViewItems() { 10588 const inViewSlides = this.track.querySelectorAll("[data-in-view]"); 10589 const firstInViewSlide = inViewSlides[0] || null; 10590 const lastInViewSlide = inViewSlides[inViewSlides.length - 1] || null; 10591 const isAtStart = firstInViewSlide === this.slides[0]; 10592 const isAtEnd = lastInViewSlide === this.slides[this.slides.length - 1]; 10593 return { 10594 inViewSlides, 10595 totalInViewSlides: inViewSlides.length, 10596 firstInViewSlide, 10597 lastInViewSlide, 10598 isAtStart, 10599 isAtEnd, 10600 hasNoOverflow: isAtStart && isAtEnd 10601 }; 10602 } 10603 groupPagerMarkers() { 10604 if (this.slides.length === 0 || !this.pager || !this.useGroupPager) return; 10605 const totalVisibleSlides = this.roundUpIfGreaterThan( 10606 this.track.offsetWidth / this.slides[0].offsetWidth 10607 ); 10608 const markers = Array.from(this.pager.querySelectorAll("a, button")); 10609 markers.forEach((marker, index) => { 10610 marker.style.display = index % totalVisibleSlides === 0 ? null : "none"; 10611 }); 10612 } 10613 handleInView(entries) { 10614 entries.forEach((entry) => { 10615 const marker = this.pager && (this.pager.querySelector(`[href="#${entry.target.id}"]`) || this.pager.querySelector( 10616 `[${this.markerIdName}="${entry.target.id}"]` 10617 )); 10618 entry.target.toggleAttribute("data-in-view", entry.isIntersecting); 10619 entry.target.toggleAttribute("inert", !entry.isIntersecting); 10620 marker?.setAttribute("aria-current", entry.isIntersecting); 10621 marker?.setAttribute("tabindex", entry.isIntersecting ? "0" : "-1"); 10622 }); 10623 const { 10624 isAtStart, 10625 isAtEnd, 10626 hasNoOverflow 10627 } = this.getInViewItems(); 10628 this.navBtns.forEach((btn) => { 10629 if (btn.hasAttribute("data-next")) { 10630 btn.style.visibility = hasNoOverflow ? "hidden" : null; 10631 isAtEnd ? btn.setAttribute("disabled", "") : btn.removeAttribute("disabled"); 10632 } 10633 if (btn.hasAttribute("data-prev")) { 10634 btn.style.visibility = hasNoOverflow ? "hidden" : null; 10635 isAtStart ? btn.setAttribute("disabled", "") : btn.removeAttribute("disabled"); 10636 } 10637 }); 10638 if (this.pager) { 10639 this.pager.style.visibility = hasNoOverflow ? "hidden" : null; 10640 } 10641 if (!this.initialLoad) { 10642 this.el.dispatchEvent( 10643 new CustomEvent("slideChange", { 10644 detail: this.getInViewItems() 10645 }) 10646 ); 10647 } else { 10648 this.initialLoad = false;
10649 } 10650 if (document.activeElement.parentElement.hasAttribute("data-pager")) { 10651 const activeItems = this.pager.querySelectorAll('[tabindex="0"]'); 10652 if (activeItems.length) { 10653 activeItems[0].focus({ preventScroll: true }); 10654 } 10655 } 10656 } 10657 getSlides() { 10658 if (!this.track) return []; 10659 return Array.from(this.track.children).filter( 10660 (child) => child.tagName.toLowerCase() !== "template" && child.tagName.toLowerCase() !== "style" && child.tagName.toLowerCase() !== "script" 10661 ); 10662 } 10663 refreshSlides() { 10664 this.initialLoad = true; 10665 this.slides = this.getSlides(); 10666 this.setupSlides(); 10667 if (this.useAutoPager) { 10668 this.createPager(); 10669 } else { 10670 this.setupPager(); 10671 } 10672 this.groupPagerMarkers(); 10673 this.setupObservers(); 10674 } 10675 setupSlides() { 10676 this.slides = this.getSlides(); 10677 this.slides.forEach((slide, index) => { 10678 const totalSlides = this.slides.length; 10679 const currentSlide = index + 1; 10680 const existingLabel = slide.getAttribute("aria-label") || ""; 10681 const isImage = slide.tagName.toLowerCase() === "img" || slide.tagName.toLowerCase() === "picture"; 10682 const slideLabelTag = isImage ? "alt" : "aria-label"; 10683 const hasAutoLabel = existingLabel.startsWith( 10684 `${currentSlide} ${this.slideLabelSepparator} ` 10685 ); 10686 if (!slide.hasAttribute("id")) { 10687 slide.setAttribute( 10688 "id", 10689 `${this.sliderId}-item-${currentSlide}` 10690 ); 10691 } 10692 if (!slide.hasAttribute(slideLabelTag) || slide.getAttribute(slideLabelTag) === "" || hasAutoLabel) { 10693 slide.setAttribute( 10694 slideLabelTag, 10695 `${currentSlide} ${this.slideLabelSepparator} ${totalSlides}` 10696 ); 10697 } 10698 if (slide.tagName.toLowerCase() === "div" && !slide.hasAttribute("role")) { 10699 slide.setAttribute("role", "group"); 10700 } 10701 if (this.pager && !isImage) { 10702 slide.setAttribute("role", "tabpanel"); 10703 } 10704 if (slide.getAttribute("role") === "group") { 10705 slide.setAttribute("aria-roledescription", "item"); 10706 } 10707 }); 10708 if (!this.el.hasAttribute("role") && this.el.tagName !== "SECTION") { 10709 this.el.setAttribute("role", "region"); 10710 } 10711 if (!this.el.hasAttribute("aria-roledescription")) { 10712 this.el.setAttribute("aria-roledescription", "carousel"); 10713 } 10714 this.track.setAttribute("tabindex", 0); 10715 this.track.setAttribute("aria-live", "polite"); 10716 } 10717 setupNav() { 10718 this.navBtns.forEach((btn) => { 10719 btn.setAttribute("disabled", ""); 10720 btn.removeAttribute("hidden"); 10721 btn.classList.remove("invisible"); 10722 btn.style.visibility = null; 10723 }); 10724 } 10725 createPager() { 10726 const newPager = document.createElement("nav"); 10727 newPager.setAttribute("data-pager", ""); 10728 newPager.setAttribute("role", "tablist"); 10729 newPager.classList.add(...this.pagerClasses.split(" ")); 10730 this.slides.forEach((slide, index) => { 10731 const marker = document.createElement("button"); 10732 const slideId = slide.id || `${this.sliderId}-item-${index + 1}`; 10733 marker.setAttribute(this.markerIdName, slideId); 10734 marker.classList.add(...this.markerClasses.split(" ")); 10735 this.setupPagerMarker(marker, index); 10736 newPager.appendChild(marker); 10737 if (slide.tagName.toLowerCase() !== "img" && slide.tagName.toLowerCase() !== "picture") { 10738 slide.removeAttribute("aria-roledescription"); 10739 slide.setAttribute("role", "tabpanel"); 10740 } 10741 }); 10742 if (this.pager) { 10743 this.pager.setAttribute("role", "tablist"); 10744 this.pager.replaceChildren(...newPager.children); 10745 } else { 10746 this.track.after(newPager); 10747 this.pager = this.el.querySelector("[data-pager]"); 10748 } 10749 } 10750 setupPager() { 10751 if (!this.pager) return; 10752 this.pager.setAttribute("role", "tablist"); 10753 const items = Array.from(this.pager.querySelectorAll("a, button"));
10754 items.forEach((marker, index) => this.setupPagerMarker(marker, index)); 10755 } 10756 setupPagerMarker(marker, index) { 10757 const markerId = marker.getAttribute("href")?.slice(1) || marker.getAttribute(this.markerIdName); 10758 const slideId = markerId || `${this.sliderId}-item-${index + 1}`; 10759 if (!markerId) { 10760 marker.setAttribute(this.markerIdName, slideId); 10761 } 10762 marker.setAttribute("role", "tab"); 10763 marker.setAttribute("aria-controls", slideId); 10764 marker.setAttribute("aria-posinset", index + 1); 10765 marker.setAttribute("aria-setsize", this.slides.length); 10766 marker.setAttribute("tabindex", "-1"); 10767 if (!marker.hasAttribute("aria-label")) { 10768 marker.setAttribute("aria-label", `Slide ${index + 1}`); 10769 } 10770 } 10771 setupObservers() { 10772 if (this.inViewObserver) { 10773 this.inViewObserver.disconnect(); 10774 } 10775 this.inViewObserver = new IntersectionObserver( 10776 this.handleInView.bind(this), { 10777 root: this.track, 10778 threshold: 0.8 10779 } 10780 ); 10781 this.slides.forEach((slide) => this.inViewObserver.observe(slide)); 10782 } 10783 setupMutationObserver() { 10784 this.mutationObserver = new MutationObserver( 10785 this.refreshSlides.bind(this) 10786 ); 10787 this.mutationObserver.observe(this.track, { 10788 childList: true, 10789 subtree: false 10790 }); 10791 } 10792 setupResizeObserver() { 10793 this.resizeObserver = new ResizeObserver( 10794 this.groupPagerMarkers.bind(this) 10795 ); 10796 this.resizeObserver.observe(this.el); 10797 } 10798 goToSlideDir(dir = "next") { 10799 const { 10800 firstInViewSlide, 10801 lastInViewSlide 10802 } = this.getInViewItems(); 10803 const isPrev = dir === "prev"; 10804 let targetSlide = isPrev ? firstInViewSlide?.previousElementSibling : lastInViewSlide?.nextElementSibling; 10805 if (!targetSlide) return; 10806 if (targetSlide.tagName.toLowerCase() === "template") { 10807 targetSlide = isPrev ? targetSlide?.previousElementSibling : targetSlide?.nextElementSibling; 10808 } 10809 targetSlide.scrollIntoView({ block: "nearest", inline: isPrev ? "end" : "start" }); 10810 } 10811 pagerToSlide(event) { 10812 if (!event.target.closest("[data-pager]")) return; 10813 const marker = event.target.closest("a, button"); 10814 if (!marker) return; 10815 event.preventDefault(); 10816 const slideId = marker.getAttribute("href")?.slice(1) || marker.getAttribute(this.markerIdName); 10817 const targetSlide = this.track.querySelector(`#${slideId}`); 10818 targetSlide?.scrollIntoView({ block: "nearest", inline: "start" }); 10819 } 10820 eventHandler(event) { 10821 const target = event.target.closest( 10822 "[data-next], [data-prev], [data-pager]" 10823 ); 10824 if (!target) return; 10825 if (event.type === "click") { 10826 if (target.hasAttribute("data-next")) { 10827 this.goToSlideDir("next"); 10828 } else if (target.hasAttribute("data-prev")) { 10829 this.goToSlideDir("prev"); 10830 } else if (target.closest("[data-pager]")) { 10831 this.pagerToSlide(event); 10832 } 10833 } 10834 if (event.type === "keydown" && target.closest("[data-pager]")) { 10835 if (event.key === "ArrowRight") { 10836 this.goToSlideDir("next"); 10837 } else if (event.key === "ArrowLeft") { 10838 this.goToSlideDir("prev"); 10839 } 10840 } 10841 } 10842 }; 10843 10844 (() => { 10845 function alpineSnapSlider(Alpine) { 10846 Alpine.directive("snap-slider", (el, { 10847 modifiers 10848 }, { 10849 cleanup 10850 }) => { 10851 const autoPager = modifiers.includes("auto-pager");
10852 const groupPager = modifiers.includes("group-pager"); 10853 const slider = new SnapSlider(el, { 10854 autoPager, 10855 groupPager 10856 }); 10857 cleanup(() => { 10858 slider.destroy(); 10859 }); 10860 }); 10861 } 10862 10863 document.addEventListener("alpine:init", () => { 10864 window.Alpine.plugin(alpineSnapSlider); 10865 }); 10866 })(); 10867</script>
vendor: 1 bytes, line 10867
10867
vendor: 2,348 bytes, lines 10868-10927
10868<script> 10869 (() => { 10870 function src_default(Alpine) { 10871 Alpine.directive("intersect", Alpine.skipDuringClone((el, { value, expression, modifiers }, { evaluateLater, cleanup }) => { 10872 let evaluate = evaluateLater(expression); 10873 let options = { 10874 rootMargin: getRootMargin(modifiers), 10875 threshold: getThreshold(modifiers) 10876 }; 10877 let observer = new IntersectionObserver((entries) => { 10878 entries.forEach((entry) => { 10879 if (entry.isIntersecting === (value === "leave")) 10880 return; 10881 evaluate(); 10882 modifiers.includes("once") && observer.disconnect(); 10883 }); 10884 }, options); 10885 observer.observe(el); 10886 cleanup(() => { 10887 observer.disconnect(); 10888 }); 10889 })); 10890 } 10891 function getThreshold(modifiers) { 10892 if (modifiers.includes("full")) 10893 return 0.99; 10894 if (modifiers.includes("half")) 10895 return 0.5; 10896 if (!modifiers.includes("threshold")) 10897 return 0; 10898 let threshold = modifiers[modifiers.indexOf("threshold") + 1]; 10899 if (threshold === "100") 10900 return 1; 10901 if (threshold === "0") 10902 return 0; 10903 return Number(`.${threshold}`); 10904 } 10905 function getLengthValue(rawValue) { 10906 let match = rawValue.match(/^(-?[0-9]+)(px|%)?$/); 10907 return match ? match[1] + (match[2] || "px") : void 0; 10908 } 10909 function getRootMargin(modifiers) { 10910 const key = "margin"; 10911 const fallback = "0px 0px 0px 0px"; 10912 const index = modifiers.indexOf(key); 10913 if (index === -1) 10914 return fallback; 10915 let values = []; 10916 for (let i = 1; i < 5; i++) { 10917 values.push(getLengthValue(modifiers[index + i] || "")); 10918 } 10919 values = values.filter((v) => v !== void 0); 10920 return values.length ? values.join(" ").trim() : fallback; 10921 } 10922 10923 document.addEventListener("alpine:init", () => { 10924 window.Alpine.plugin(src_default); 10925 }); 10926 })(); 10927</script>
vendor: 1 bytes, line 10927
10927
10928<script> 10929 (function () { 10930 "use strict"; 10931 10932 const hasAlpine = new Promise(resolve => { 10933 window.addEventListener('alpine:initialized', resolve, {once: true, passive: true}); 10934 }); 10935 10936 const hasInteract = new Promise(resolve => { 10937 (events => { 10938 const onInteract = () => { 10939 resolve(); 10940 events.forEach(type => window.removeEventListener(type, onInteract)); 10941 } 10942 events.forEach(type => window.addEventListener(type, onInteract, {once: true, passive: true})) 10943 })(['touchstart', 'mouseover', 'wheel', 'scroll', 'keydown']) 10944 }); 10945 10946 const onIntersect = (el) => { 10947 return new Promise(resolve => { 10948 const observer = new IntersectionObserver(entries => { 10949 for (const entry of entries) { 10950 if (entry.isIntersecting) { 10951 observer.disconnect() 10952 resolve(); 10953 } 10954 } 10955 }, {}); 10956 observer.observe(el); 10957 }); 10958 } 10959 10960 function runComponent(el) { 10961 hasAlpine.then(() => { 10962 el.removeAttribute('x-ignore'); 10963 queueMicrotask(() => Alpine.initTree(el)); 10964 }); 10965 } 10966 10967 function initDeferredComponents() { 10968 document.querySelectorAll('[x-data][x-defer]').forEach(el => { 10969 el.setAttribute('x-ignore', ''); 10970 const deferUntil = (el.getAttribute('x-defer') || '').trim(); 10971 switch (deferUntil) { 10972 case 'interact': 10973 hasInteract.then(() => runComponent(el)); 10974 break; 10975 case 'intersect': 10976 onIntersect(el).then(() => runComponent(el)) 10977 break; 10978 case 'idle': 10979 window.requestIdleCallback 10980 ? window.requestIdleCallback(() => runComponent(el), {timeout: 4000}) 10981 : setTimeout(() => runComponent(el), 4000); 10982 break; 10983 case 'eager': 10984 runComponent(el); 10985 break; 10986 default: 10987 if (deferUntil.startsWith('event:') && deferUntil.length > 6) { 10988 window.addEventListener(deferUntil.substring(6), () => runComponent(el), {once: true, passive: true}); 10989 } 10990 } 10991 }); 10992 } 10993 10994 window.addEventListener('alpine:init', initDeferredComponents, {once: true, passive: true}); 10995 })() 10996</script>
vendor: 1 bytes, line 10996
10996
vendor: 1,470 bytes, lines 10997-10999
10997<script> 10998 (()=>{function g(n){n.directive("collapse",e),e.inline=(t,{modifiers:i})=>{i.includes("min")&&(t._x_doShow=()=>{},t._x_doHide=()=>{})};function e(t,{modifiers:i}){let r=l(i,"duration",250)/1e3,h=l(i,"min",0),u=!i.includes("min");t._x_isShown||(t.style.height=`${h}px`),!t._x_isShown&&u&&(t.hidden=!0),t._x_isShown||(t.style.overflow="hidden");let c=(d,s)=>{let o=n.setStyles(d,s);return s.height?()=>{}:o},f={transitionProperty:"height",transitionDuration:`${r}s`,transitionTimingFunction:"cubic-bezier(0.4, 0.0, 0.2, 1)"};t._x_transition={in(d=()=>{},s=()=>{}){u&&(t.hidden=!1),u&&(t.style.display=null);let o=t.getBoundingClientRect().height;t.style.height="auto";let a=t.getBoundingClientRect().height;o===a&&(o=h),n.transition(t,n.setStyles,{during:f,start:{height:o+"px"},end:{height:a+"px"}},()=>t._x_isShown=!0,()=>{Math.abs(t.getBoundingClientRect().height-a)<1&&(t.style.overflow=null)})},out(d=()=>{},s=()=>{}){let o=t.getBoundingClientRect().height;n.transition(t,c,{during:f,start:{height:o+"px"},end:{height:h+"px"}},()=>t.style.overflow="hidden",()=>{t._x_isShown=!1,t.style.height==`${h}px`&&u&&(t.style.display="none",t.hidden=!0)})}}}}function l(n,e,t){if(n.indexOf(e)===-1)return t;let i=n[n.indexOf(e)+1];if(!i)return t;if(e==="duration"){let r=i.match(/([0-9]+)ms/);if(r)return r[1]}if(e==="min"){let r=i.match(/([0-9]+)px/);if(r)return r[1]}return i}document.addEventListener("alpine:init",()=>{window.Alpine.plugin(g)});})(); 10999</script>
10999 11000 11001 11002
11003<script type="module" 11004 src="https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/Hyva_Theme/js/alpine3.min.js" 11005 defer 11006 crossorigin 11007></script>
vendor: 1 bytes, line 11007
11007
11008<script> 11009 document.addEventListener("alpine:init", () => { 11010 Alpine.data('hyvaCmsToggle', () => ({ 11011 open: false, 11012 notOpen() { 11013 return !this.open; 11014 }, 11015 show() { 11016 this.open = true 11017 }, 11018 hide() { 11019 this.open = false 11020 }, 11021 toggle() { 11022 this.open = !this.open 11023 } 11024 })) 11025 }); 11026</script>
11026 11027
11028<script> 11029(function() { 11030 'use strict'; 11031 const STORAGE_KEY = 'rocket_menu_active'; 11032 const PARENT_SEL = ':scope>a[data-item-id],:scope>div>a[data-item-id],:scope>button[data-item-id],:scope>div>button[data-item-id]'; 11033 11034 const normalize = u => u ? u.split('?')[0].replace(/\/$/, '') : ''; 11035 11036 document.addEventListener('click', e => { 11037 const a = e.target.closest('a[data-item-id]'); 11038 if (a?.dataset.itemId) sessionStorage.setItem(STORAGE_KEY, JSON.stringify({ id: a.dataset.itemId, url: normalize(a.href) })); 11039 }, true); 11040 11041 window.menuActiveTracker = (opts = {}) => ({ 11042 activeItemId: null, 11043 activeItemIds: new Set(), 11044 11045 detectActiveItem() { 11046 const container = this.$refs?.menuContainer || this.$el; 11047 if (!container) return; 11048 11049 const url = normalize(location.href); 11050 const stored = sessionStorage.getItem(STORAGE_KEY); 11051 let link = null; 11052 11053 if (stored) { 11054 try { 11055 const d = JSON.parse(stored); 11056 if (d.url === url) link = container.querySelector(`[data-item-id="${d.id}"]`); 11057 } catch {} 11058 if (!link) sessionStorage.removeItem(STORAGE_KEY); 11059 } 11060 11061 if (!link) { 11062 this.$nextTick(() => { 11063 // Find all matching links and prioritize those with hierarchical parents 11064 const matches = []; 11065 for (const a of container.querySelectorAll('a[data-item-id]')) { 11066 if (normalize(a.href) === url) { 11067 const hasParent = !!a.closest('div[data-item-id]'); 11068 matches.push({ link: a, hasParent }); 11069 } 11070 } 11071 // Prefer link with parent (hierarchical), fallback to first match 11072 const best = matches.find(m => m.hasParent) || matches[0]; 11073 if (best) this._setHierarchy(best.link); 11074 }); 11075 return; 11076 } 11077 this._setHierarchy(link); 11078 }, 11079 11080 _setHierarchy(link) { 11081 const container = this.$refs?.menuContainer || this.$el; 11082 this.activeItemIds.clear(); 11083 this.activeItemId = link.dataset.itemId; 11084 this.activeItemIds.add(this.activeItemId); 11085 11086 for (let p = link.parentElement; p && p !== container && p !== document.body; p = p.parentElement) { 11087 const pl = p.querySelector(PARENT_SEL); 11088 if (pl && pl !== link) this.activeItemIds.add(pl.dataset.itemId); 11089 if (p.dataset?.itemId) this.activeItemIds.add(p.dataset.itemId); 11090 } 11091 11092 opts.onActiveDetected?.call(this, this.activeItemId, link.dataset.itemTitle); 11093 }, 11094 11095 isActive(id) { return this.activeItemIds.has(id); } 11096 }); 11097})(); 11098</script>
vendor: 1 bytes, line 11098
11098
11099<script type="application/ld+json"> 11100 { 11101 "@context": "https://schema.org", 11102 "@type": "Organization", 11103 "@id": "https://www.serrats.com/es_es/#organization", 11104 "name": "Conservas Serrats", 11105 "url": "https://www.serrats.com/es_es/", 11106 "logo": "https://www.serrats.com/static/version1789548230/frontend/Project/default/es_ES/images/logo.svg", 11107 "alternateName": [ 11108 "Serrats", 11109 "Hijos de José Serrats", 11110 "Hijos de José Serrats, S.A." 11111 ], 11112 "legalName": "Hijos de José Serrats, S.A.", 11113 "description": "Conservas Serrats es una empresa conservera de Bermeo especializada en conservas gourmet de pescado del Cantábrico. Desde 1890 elabora conservas artesanas de Bonito del Norte, anchoas del Cantábrico, atún claro, boquerones, mejillones, sardinas, berberechos, zamburiñas y otras especialidades del mar.", 11114 "slogan": "Pasión por lo auténtico", 11115 "foundingDate": "1890", 11116 "taxID": "A48005672", 11117 "vatID": "ESA48005672", 11118 "email": "[email protected]", 11119 "telephone": "+34 946 187 280", 11120 "address": { 11121 "@type": "PostalAddress", 11122 "streetAddress": "PolÃgono Landabaso 3B", 11123 "postalCode": "48370", 11124 "addressLocality": "Bermeo", 11125 "addressRegion": "Bizkaia", 11126 "addressCountry": "ES" 11127 }, 11128 "geo": { 11129 "@type": "GeoCoordinates", 11130 "latitude": 43.42084, 11131 "longitude": -2.736242 11132 }, 11133 "hasMap": "https://maps.app.goo.gl/cC2zEmt8MPP5HpQS9", 11134 "sameAs": [ 11135 "https://www.instagram.com/serratsconservas/", 11136 "https://www.facebook.com/conservas.serrats", 11137 "https://www.youtube.com/user/serratsconservas", 11138 "https://www.linkedin.com/company/conservas-serrats/", 11139 "https://www.tiktok.com/@serratsconservas" 11140 ], 11141 "areaServed": [ 11142 { 11143 "@type": "Country", 11144 "name": "España" 11145 }, 11146 { 11147 "@type": "AdministrativeArea", 11148 "name": "Bizkaia" 11149 }, 11150 { 11151 "@type": "AdministrativeArea", 11152 "name": "PaÃs Vasco" 11153 } 11154 ], 11155 "knowsLanguage": [ 11156 { 11157 "@type": "Language", 11158 "name": "Español", 11159 "alternateName": "es-ES" 11160 }, 11161 { 11162 "@type": "Language", 11163 "name": "Euskera", 11164 "alternateName": "eu-ES" 11165 }, 11166 { 11167 "@type": "Language", 11168 "name": "English", 11169 "alternateName": "en" 11170 } 11171 ], 11172 "contactPoint": [ 11173 { 11174 "@type": "ContactPoint", 11175 "contactType": "Oficina y pedidos online", 11176 "telephone": "+34 946 187 280", 11177 "email": "[email protected]", 11178 "areaServed": "ES", 11179 "availableLanguage": [ 11180 "es-ES", 11181 "eu-ES", 11182 "en" 11183 ], 11184 "url": "https://www.serrats.com/es_es/contacto" 11185 }, 11186 { 11187 "@type": "ContactPoint", 11188 "contactType": "Tienda fÃsica", 11189 "telephone": "+34 607 289 852", 11190 "email": "[email protected]", 11191 "areaServed": [ 11192 "Bermeo", 11193 "Bizkaia", 11194 "PaÃs Vasco" 11195 ], 11196 "availableLanguage": [ 11197 "es-ES", 11198 "eu-ES" 11199 ], 11200 "url": "https://www.serrats.com/es_es/contacto" 11201 }, 11202 { 11203 "@type": "ContactPoint", 11204 "contactType": "Distribuidores", 11205 "telephone": "+34 946 187 280", 11206 "email": "[email protected]", 11207 "areaServed": [ 11208 "ES", 11209 "EU", 11210 "International" 11211 ], 11212 "availableLanguage": [ 11213 "es-ES", 11214 "en" 11215 ], 11216 "url": "https://www.serrats.com/es_es/distribuir-conservas-de-pescado" 11217 } 11218 ], 11219 "knowsAbout": [ 11220 "conservas gourmet", 11221 "conservas de pescado", 11222 "Bonito del Norte", 11223 "anchoas del Cantábrico", 11224 "atún claro", 11225 "boquerones del Cantábrico", 11226 "mejillones en conserva", 11227 "berberechos", 11228 "zamburiñas", 11229 "caviar de erizo de mar", 11230 "conservas ecológicas", 11231 "conservas artesanas", 11232 "cajas regalo gourmet" 11233 ], 11234 "hasPOS": { 11235 "@type": "Place", 11236 "@id": "https://www.serrats.com/es_es/#tienda-bermeo", 11237 "name": "Conservas Serrats - Tienda de Bermeo", 11238 "alternateName": [ 11239 "Tienda Conservas Serrats", 11240 "Tienda fÃsica Serrats", 11241 "Serrats Bermeo" 11242 ], 11243 "description": "Punto fÃsico de Conservas Serrats en Bermeo, Bizkaia, especializado en conservas gourmet de pescado, Bonito del Norte, anch
11243oas del Cantábrico, atún claro, boquerones, mejillones, berberechos, zamburiñas, caviar de erizo de mar, cajas regalo gourmet y conservas artesanas.", 11244 "url": "https://www.serrats.com/es_es/contacto", 11245 "address": { 11246 "@type": "PostalAddress", 11247 "streetAddress": "PolÃgono Landabaso 3B", 11248 "postalCode": "48370", 11249 "addressLocality": "Bermeo", 11250 "addressRegion": "Bizkaia", 11251 "addressCountry": "ES" 11252 }, 11253 "geo": { 11254 "@type": "GeoCoordinates", 11255 "latitude": 43.42084, 11256 "longitude": -2.736242 11257 }, 11258 "hasMap": "https://maps.app.goo.gl/cC2zEmt8MPP5HpQS9", 11259 "telephone": "+34 607 289 852", 11260 "email": "[email protected]", 11261 "openingHours": [ 11262 "Mo-Th 10:00-14:00", 11263 "Mo-Th 15:30-19:00", 11264 "Fr 10:00-14:00", 11265 "Fr 15:30-18:00" 11266 ], 11267 "openingHoursSpecification": [ 11268 { 11269 "@type": "OpeningHoursSpecification", 11270 "name": "Horario de mañana de tienda fÃsica", 11271 "dayOfWeek": [ 11272 "https://schema.org/Monday", 11273 "https://schema.org/Tuesday", 11274 "https://schema.org/Wednesday", 11275 "https://schema.org/Thursday" 11276 ], 11277 "opens": "10:00", 11278 "closes": "14:00" 11279 }, 11280 { 11281 "@type": "OpeningHoursSpecification", 11282 "name": "Horario de tarde de tienda fÃsica", 11283 "dayOfWeek": [ 11284 "https://schema.org/Monday", 11285 "https://schema.org/Tuesday", 11286 "https://schema.org/Wednesday", 11287 "https://schema.org/Thursday" 11288 ], 11289 "opens": "15:30", 11290 "closes": "19:00" 11291 }, 11292 { 11293 "@type": "OpeningHoursSpecification", 11294 "name": "Horario de viernes por la mañana", 11295 "dayOfWeek": [ 11296 "https://schema.org/Friday" 11297 ], 11298 "opens": "10:00", 11299 "closes": "14:00" 11300 }, 11301 { 11302 "@type": "OpeningHoursSpecification", 11303 "name": "Horario de viernes por la tarde", 11304 "dayOfWeek": [ 11305 "https://schema.org/Friday" 11306 ], 11307 "opens": "15:30", 11308 "closes": "18:00" 11309 } 11310 ], 11311 "amenityFeature": [ 11312 { 11313 "@type": "LocationFeatureSpecification", 11314 "name": "Tienda fÃsica de conservas gourmet", 11315 "value": true 11316 }, 11317 { 11318 "@type": "LocationFeatureSpecification", 11319 "name": "Atención presencial en Bermeo", 11320 "value": true 11321 }, 11322 { 11323 "@type": "LocationFeatureSpecification", 11324 "name": "Venta de cajas regalo gourmet", 11325 "value": true 11326 }, 11327 { 11328 "@type": "LocationFeatureSpecification", 11329 "name": "Productos artesanos", 11330 "value": true 11331 }, 11332 { 11333 "@type": "LocationFeatureSpecification", 11334 "name": "Conservas sin gluten", 11335 "value": true 11336 } 11337 ] 11338 } 11339}</script>
vendor: 1 bytes, line 11339
11339
11340<script type="application/ld+json"> 11341 { 11342 "@context": "https://schema.org", 11343 "@type": "WebPage", 11344 "name": "Bonito del Norte en conserva | Sabor y calidad", 11345 "description": "Compra bonito en conserva de la mejor calidad. Sabor auténtico en cada lata, ideal para cualquier receta. ¡Haz tu pedido online!", 11346 "url": "https://www.serrats.com/es_es/comprar-bonito-del-norte", 11347 "isPartOf": { 11348 "@type": "WebSite", 11349 "url": "https://www.serrats.com", 11350 "name": "Serrats" 11351 } 11352}</script>
11352 11353
11354<script> 11355 window.RocketAjaxCart = rocketAjaxCart(); 11356 11357 function rocketAjaxCart() { 11358 'use strict'; 11359 11360 let cartId = null; 11361 let cartData = {}; 11362 let customerToken = null; 11363 let cartEmpty = false; 11364 11365 function reloadCustomerData() { 11366 window.dispatchEvent(new CustomEvent('reload-customer-section-data')); 11367 } 11368 function getUpdateCartItemMutation() { 11369 return `mutation updateCartItemQtyMutation($cartId: String!, $itemId: Int, $qty: Float) {updateCartItems( 11370 input: { 11371 cart_id: $cartId, 11372 cart_items: [ 11373 { 11374 cart_item_id: $itemId 11375 quantity: $qty 11376 } 11377 ] 11378 } 11379 ) { 11380 cart { 11381 11382 total_quantity 11383 items { 11384 id 11385 errors { 11386 code 11387 message 11388 } 11389 prices { 11390 price { 11391 value 11392 } 11393 row_total { 11394 value 11395 currency 11396 } 11397 row_total_incl_tax { 11398 value 11399 currency 11400 } 11401 price_incl_tax { 11402 value 11403 } 11404 } 11405 product_type 11406 simple_image 11407 product { 11408 id 11409 name 11410 sku 11411 ... on ConfigurableProduct { 11412 name 11413 configurable_options { 11414 values { 11415 swatch_data { 11416 __typename 11417 value 11418 } 11419 } 11420 } 11421 options { 11422 uid 11423 title 11424 ... on CustomizableOptionInterface { 11425 title 11426 } 11427 ... on CustomizableDropDownOption { 11428 value { 11429 option_type_id 11430 title 11431 sku 11432 } 11433 } 11434 ... on CustomizableMultipleOption { 11435 value { 11436 option_type_id 11437 title 11438 sku 11439 } 11440 } 11441 ... on CustomizableRadioOption { 11442 value { 11443 option_type_id 11444 title 11445 sku 11446 } 11447 } 11448 ... on CustomizableCheckboxOption { 11449 value { 11450 option_type_id 11451 title 11452 sku 11453 } 11454 } 11455 } 11456 } 11457 ... on SimpleProduct { 11458 name 11459 options { 11460 title 11461 } 11462 } 11463 ... on VirtualProduct { 11464 name 11465 options { 11466 title 11467 } 11468 } 11469 ... on DownloadableProduct { 11470 name 11471 options { 11472 title 11473 } 11474 } 11475 ... on BundleProduct { 11476 name 11477 options { 11478 title 11479 } 11480 } 11481 small_image { 11482 label 11483 url 11484 } 11485 url_key 11486 url_suffix 11487 price_tiers { 11488 quantity 11489 final_price { 11490 value 11491 } 11492 discount { 11493 amount_off 11494 percent_off 11495 } 11496 } 11497 } 11498 quantity 11499 ... on ConfigurableCartItem { 11500 configurable_options { 11501 option_label 11502 swatch_type 11503 swatch_value 11504 } 11505 options: customizable_options { 11506 type 11507 label 11508 values { 11509 label 11510 value 11511 } 11512 } 11513 } 11514 ... on SimpleCartItem { 11515 customizable_options { 11516 label 11517 values { 11518 label 11519 value 11520 price { 11521 value 11522 type 11523 } 11524 } 11525 } 11526 } 11527 ... on VirtualCartItem { 11528 customizable_options { 11529 type 11530 label 11531 values { 11532 label 11533 value 11534 price { 11535 value 11536 type 11537 } 11538 } 11539 } 11540 } 11541 ... on DownloadableCartItem { 11542 customizable_options { 11543 type 11544 label 11545 values { 11546 label 11547 value 11548 price { 11549 value 11550 type 11551 } 11552 } 11553 } 11554 } 11555 ... on BundleCartItem { 11556 bundle_options { 11557 id 11558 label 11559 values { 11560 quantity 11561 label 11562 } 11563 } 11564 customizable_options: bundle_options { 11565 uid 11566 type 11567 label 11568 values{ 11569 id 11570 label 11571 } 11572 } 11573 } 11574 } 11575 available_payment_methods { 11576 code 11577 title 11578 } 11579 selected_payment_method { 11580 code 11581 title 11582 } 11583 applied_coupons { 11584 code 11585 } 11586 billing_address { 11587 country { 11588 code 11589 } 11590 region { 11591 label 11592 region_id 11593 } 11594 postcode 11595 } 11596 shipping_addresses { 11597 country { 11598 code 11599 } 11600 region { 11601 label 11602 region_id 11603 } 11604 postcode 11605 selected_shipping_method { 11606 amount { 11607 value 11608 currency 11609 } 11610 price_incl_tax { 11611 value 11612 currency 11613 } 11614 carrier_title 11615 carrier_code 11616 method_title 11617 method_code 11618 } 11619 available_shipping_methods { 11620 price_excl_tax { 11621 value 11622 currency 11623 } 11624 price_incl_tax { 11625 value 11626 currency 11627 } 11628 carrier_title 11629 carrier_code 11630 method_title 11631 method_code 11632 } 11633 } 11634 prices { 11635 grand_total { 11636 value 11637 currency 11638 } 11639 subtotal_excluding_tax { 11640 value 11641 currency 11642 } 11643 subtotal_including_tax { 11644 value 11645 currency 11646 } 11647 applied_taxes { 11648 amount { 11649 value 11650 currency 11651 } 11652 label 11653 } 11654 discounts { 11655 amount { 11656 value 11657 currency 11658 } 11659 label 11660 } 11661 } 11662 11663 } 11664 }}`; 11665 } 11666 function getRemoveCartItemMutation() { 11667 return `mutation removeCartItemMutation($cartId: String!, $itemId: Int) {removeItemFromCart( 11668 input: { 11669 cart_id: $cartId, 11670 cart_item_id: $itemId 11671 } 11672 ){ 11673 cart { 11674 11675 total_quantity 11676 items { 11677 id 11678 errors { 11679 code 11680 message 11681 } 11682 prices { 11683 price { 11684 value 11685 } 11686 row_total { 11687 value 11688 currency 11689 } 11690 row_total_incl_tax { 11691 value 11692 currency 11693 } 11694 price_incl_tax { 11695 value 11696 } 11697 } 11698 product_type 11699 simple_image 11700 product { 11701 id 11702 name 11703 sku 11704 ... on ConfigurableProduct { 11705 name 11706 configurable_options { 11707 values { 11708 swatch_data { 11709 __typename 11710 value 11711 } 11712 } 11713 } 11714 options { 11715 uid 11716 title 11717 ... on CustomizableOptionInterface { 11718 title 11719 } 11720 ... on CustomizableDropDownOption { 11721 value { 11722 option_type_id 11723 title 11724 sku 11725 } 11726 } 11727 ... on CustomizableMultipleOption { 11728 value { 11729 option_type_id 11730 title 11731 sku 11732 } 11733 } 11734 ... on CustomizableRadioOption { 11735 value { 11736 option_type_id 11737 title 11738 sku 11739 } 11740 } 11741 ... on CustomizableCheckboxOption { 11742 value { 11743 option_type_id 11744 title 11745 sku 11746 } 11747 } 11748 } 11749 } 11750 ... on SimpleProduct { 11751 name 11752 options { 11753 title 11754 } 11755 } 11756 ... on VirtualProduct { 11757 name 11758 options { 11759 title 11760 } 11761 } 11762 ... on DownloadableProduct { 11763 name 11764 options { 11765 title 11766 } 11767 } 11768 ... on BundleProduct { 11769 name 11770 options { 11771 title 11772 } 11773 } 11774 small_image { 11775 label 11776 url 11777 } 11778 url_key 11779 url_suffix 11780 price_tiers { 11781 quantity 11782 final_price { 11783 value 11784 } 11785 discount { 11786 amount_off 11787 percent_off 11788 } 11789 } 11790 } 11791 quantity 11792 ... on ConfigurableCartItem { 11793 configurable_options { 11794 option_label 11795 swatch_type 11796 swatch_value 11797 } 11798 options: customizable_options { 11799 type 11800 label 11801 values { 11802 label 11803 value 11804 } 11805 } 11806 } 11807 ... on SimpleCartItem { 11808 customizable_options { 11809 label 11810 values { 11811 label 11812 value 11813 price { 11814 value 11815 type 11816 } 11817 } 11818 } 11819 } 11820 ... on VirtualCartItem { 11821 customizable_options { 11822 type 11823 label 11824 values { 11825 label 11826 value 11827 price { 11828 value 11829 type 11830 } 11831 } 11832 } 11833 } 11834 ... on DownloadableCartItem { 11835 customizable_options { 11836 type 11837 label 11838 values { 11839 label 11840 value 11841 price { 11842 value 11843 type 11844 } 11845 } 11846 } 11847 } 11848 ... on BundleCartItem { 11849 bundle_options { 11850 id 11851 label 11852 values { 11853 quantity 11854 label 11855 } 11856 } 11857 customizable_options: bundle_options { 11858 uid 11859 type 11860 label 11861 values{ 11862 id 11863 label 11864 } 11865 } 11866 } 11867 } 11868 available_payment_methods { 11869 code 11870 title 11871 } 11872 selected_payment_method { 11873 code 11874 title 11875 } 11876 applied_coupons { 11877 code 11878 } 11879 billing_address { 11880 country { 11881 code 11882 } 11883 region { 11884 label 11885 region_id 11886 } 11887 postcode 11888 } 11889 shipping_addresses { 11890 country { 11891 code 11892 } 11893 region { 11894 label 11895 region_id 11896 } 11897 postcode 11898 selected_shipping_method { 11899 amount { 11900 value 11901 currency 11902 } 11903 price_incl_tax { 11904 value 11905 currency 11906 } 11907 carrier_title 11908 carrier_code 11909 method_title 11910 method_code 11911 } 11912 available_shipping_methods { 11913 price_excl_tax { 11914 value 11915 currency 11916 } 11917 price_incl_tax { 11918 value 11919 currency 11920 } 11921 carrier_title 11922 carrier_code 11923 method_title 11924 method_code 11925 } 11926 } 11927 prices { 11928 grand_total { 11929 value 11930 currency 11931 } 11932 subtotal_excluding_tax { 11933 value 11934 currency 11935 } 11936 subtotal_including_tax { 11937 value 11938 currency 11939 } 11940 applied_taxes { 11941 amount { 11942 value 11943 currency 11944 } 11945 label 11946 } 11947 discounts { 11948 amount { 11949 value 11950 currency 11951 } 11952 label 11953 } 11954 } 11955 11956 } 11957 }}`; 11958 } 11959 11960 window.addEventListener('private-content-loaded', function (event) { 11961 const data = event.detail.data; 11962 11963 if (data && data.customer && data.customer.signin_token) { 11964 customerToken = data.customer.signin_token; 11965 } 11966 11967 if (data && data.cart && data.cart.cartId) { 11968 cartId = data.cart.cartId; 11969 11970 if (data.cart.summary_count !== cartData.summary_count) { 11971 cartData = ((data.rocket_checkout_cart_actions)) || {}; 11972 cartEmpty = !(cartData && cartData.ite
11972ms && Object.keys(cartData.items).length); 11973 } 11974 } else { 11975 cartEmpty = true; 11976 } 11977 }); 11978 11979 return { 11980 /** 11981 * @param sku 11982 * @param quantity 11983 * @returns {Promise} 11984 */ 11985 addProductToCart(sku, quantity=1) { 11986 return new Promise((resolve, reject) => { 11987 11988 if (quantity <= 0) { 11989 return reject('Por favor, introduzca una cantidad mayor que 0.'); 11990 } 11991 11992 const data = { 11993 form_key: hyva.getFormKey(), 11994 product: sku, 11995 uenc: btoa(window.location.href), 11996 qty: quantity, 11997 remove_messages: true, 11998 isAjax: true 11999 }; 12000 12001 let postData = Object.keys(data).map(key => { 12002 return `${key}=${data[key]}`; 12003 }).join('&'); 12004 12005 fetch(`${BASE_URL}rocket_checkout_cart_actions/cart/add/`, { 12006 "headers": { 12007 "content-type": "application/x-www-form-urlencoded; charset=UTF-8", 12008 }, 12009 "body": postData, 12010 "method": "POST", 12011 "mode": "cors", 12012 "credentials": "include" 12013 }).then((response) => { 12014 if (response.ok) { 12015 return response.json(); 12016 } 12017 12018 return reject(response); 12019 }).then((response) => { 12020 if (!response) { 12021 return reject('No podemos añadir este artÃculo a su carrito de compras ahora mismo.'); 12022 } 12023 12024 reloadCustomerData(); 12025 return resolve('Añadiste %1 a tu cesta.'.replace('%1', sku)); 12026 }).catch((error) => { 12027 return reject(error); 12028 }); 12029 }) 12030 }, 12031 /** 12032 * @param sku 12033 * @param quantity 12034 * @returns {Promise} 12035 */ 12036 updateProductToCart(sku, quantity) { 12037 return new Promise((resolve, reject) => { 12038 const cartItem = this.getCartItemBySku(sku); 12039 12040 if (!cartItem || !cartItem.item_id) { 12041 return reject('No\u0020pudimos\u0020a\u00F1adir\u0020el\u0020producto\u0020a\u0020tu\u0020carrito\u0020de\u0020compras.'); 12042 } 12043 12044 const qty = parseFloat(quantity); 12045 if (isNaN(qty) || qty < 0) { 12046 return reject('Please\u0020enter\u0020a\u0020valid\u0020quantity.'); 12047 } 12048 12049 const variables = { 12050 cartId: cartId, 12051 itemId: cartItem.item_id, 12052 qty: qty 12053 }; 12054 12055 fetch(`${BASE_URL}graphql`, { 12056 method: 'POST', 12057 headers: { 12058 'Content-Type': 'application/json;charset=utf-8', 12059 'Store': 'es_es' 12060 }, 12061 body: JSON.stringify({query: getUpdateCartItemMutation(), variables: variables}) 12062 } 12063 ).then((response) => { 12064 return response.json() 12065 }).then((data) => { 12066 if (data.errors) { 12067 return reject(data.errors); 12068 } 12069 12070 reloadCustomerData(); 12071 12072 return resolve('\u00251\u0020ha\u0020alcanzado\u0020una\u0020cantidad\u0020de\u0020\u00252.' 12073 .replace('%1', cartItem.name) 12074 .replace('%2', quantity)); 12075 }).catch((error) => { 12076 return reject(error); 12077 }); 12078 }); 12079 }, 12080 /** 12081 * @param sku 12082 * @returns {Promise} 12083 */ 12084 removeProductToCart(sku) { 12085 return new Promise((resolve, reject) => { 12086 const cartItem = this.getCartItemBySku(sku); 12087 12088 if (!cartItem || !cartItem.item_id) { 12089 return reject('No\u0020se\u0020puede\u0020quitar\u0020el\u0020producto.'); 12090 } 12091 12092 const variables = { 12093 cartId: cartId, 12094 itemId: cartItem.item_id 12095 }; 12096 12097 fetch(`${BASE_URL}graphql`, { 12098 method: 'POST', 12099 headers: { 12100 'Content-Type': 'application/json;charset=utf-8', 12101 'Store': 'es_es' 12102 }, 12103 body: JSON.stringify({query: getRemoveCartItemMutation(), variables: variables}) 12104 } 12105 ).then((response) => { 12106 return response.json() 12107 }).then((data) => { 12108 if (data.errors) { 12109 return reject(data.errors); 12110 } 12111 12112 reloadCustomerData(); 12113 12114 return resolve('\u00251\u0020has\u0020been\u0020removed\u0020from\u0020your\u0020shopping\u0020cart.' 12115 .replace('%1', cartItem.name)); 12116 }).catch((error) => { 12117 return reject(error); 12118 }); 12119 }); 12120 }, 12121 /** 12122 * @param sku 12123 * @returns {boolean|{}} 12124 */ 12125 getCartItemBySku(sku) { 12126 if (!cartData.items || cartData.items.length === 0) { 12127 return false;
12128 } 12129 12130 const cartItem = cartData.items.find((item) => { 12131 return item.product_sku === sku; 12132 }); 12133 12134 return (cartItem) ? cartItem : false; 12135 } 12136 }; 12137 } 12138</script>
12138 12139 12140
12141<script> 12142 'use strict'; 12143 12144 (function () { 12145 12146 window.rocket.selectSearch = function(options) { 12147 12148 const baseConfig = { 12149 id: 'base', 12150 open: false, 12151 selectedOption: "", 12152 selectedOptionDisplay: "<span x-text='selectedOption'><\/span>", 12153 options: ""[]"", 12154 filter: "", 12155 valueToFilter: "name", 12156 noResultsLiteral: "No hay resultados", 12157 inputPlaceholderLiteral: "Buscar", 12158 }; 12159 12160 return { 12161 ...baseConfig, 12162 ...options, 12163 } 12164 } 12165 12166 })( window.rocket = window.rocket || {} ); 12167</script>
vendor: 1 bytes, line 12167
12167
12168<script> 12169 'use strict'; 12170 function dispatchMessages(messages, hideAfter) { 12171 const messagesEvent = new CustomEvent("messages-loaded", { 12172 detail: { 12173 messages: messages, 12174 hideAfter: hideAfter 12175 } 12176 }); 12177 window.dispatchEvent(messagesEvent); 12178 } 12179 12180 if (typeof hyva === 'undefined' || (!hyva.getBrowserStorage || !hyva.getCookie || !hyva.setCookie)) { 12181 console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script"); 12182 } 12183 12184 (function( hyva, undefined ) { 12185 12186 hyva.initFormKey = () => { 12187 const inputSelector = 'input[name="form_key"]', 12188 formKey = hyva.getFormKey(); 12189 12190 Array.from(document.querySelectorAll(inputSelector)).map(function (input) { 12191 input.value = formKey 12192 }); 12193 } 12194 12195 hyva.initMessages = () => { 12196 try { 12197 const messages = hyva.getCookie('mage-messages'); 12198 window.mageMessages = messages ? JSON.parse(decodeURIComponent(messages).replace(/\+/g, ' ')) : []; 12199 12200 dispatchMessages(window.mageMessages); 12201 12202 // empty `mage-messages` cookie 12203 const skipSetDomain = true; 12204 hyva.setCookie('mage-messages','', -1, skipSetDomain); 12205 12206 } catch (error) { 12207 console.warn('Error parsing Cookie Messages:', error); 12208 } 12209 } 12210 12211 window.addEventListener('DOMContentLoaded', hyva.initFormKey); 12212 hyva.alpineInitialized(hyva.initMessages) 12213 12214 }( window.hyva = window.hyva || {} )); 12215</script>
vendor: 1 bytes, line 12215
12215
12216<script> 12217 'use strict'; 12218 { 12219 const private_content_key = 'mage-cache-storage'; 12220 const private_content_expire_key = 'mage-cache-timeout'; 12221 const private_content_version_key = 'private_content_version'; 12222 const section_data_ids_key = 'section_data_ids'; 12223 const mage_cache_session_id_key = 'mage-cache-sessid'; 12224 const last_visited_store_key = 'last_visited_store'; 12225 12226 const ttl = 3600; 12227 12228 if (typeof hyva === 'undefined' || (!hyva.getBrowserStorage || !hyva.getCookie || !hyva.setCookie)) { 12229 console.warn("Hyvä helpers are not loaded yet. Make sure they are included before this script"); 12230 } 12231 12232 function loadSectionData () { 12233 const browserStorage = hyva.getBrowserStorage(); 12234 if (!browserStorage) { 12235 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages( 12236 [{ 12237 type: "warning", 12238 text: "Por favor, active LocalStorage en su navegador" 12239 }] 12240 ); 12241 return; 12242 } 12243 try { 12244 let isInvalid = false; 12245 12246 if (hyva.getCookie(last_visited_store_key) !== CURRENT_STORE_CODE) { 12247 isInvalid = true; 12248 } 12249 hyva.setCookie(last_visited_store_key, CURRENT_STORE_CODE, false, false); 12250 12251 if (!hyva.getCookie(mage_cache_session_id_key)) { 12252 isInvalid = true; 12253 browserStorage.removeItem(private_content_key); 12254 const skipSetDomain = true; 12255 const days = false; 12256 hyva.setCookie(mage_cache_session_id_key, true, days, skipSetDomain) 12257 } 12258 12259 const cookieVersion = hyva.getCookie(private_content_version_key); 12260 const storageVersion = browserStorage.getItem(private_content_version_key); 12261 12262 if (cookieVersion && !storageVersion || cookieVersion !== storageVersion) { 12263 isInvalid = true; 12264 } 12265 12266 const privateContentExpires = browserStorage.getItem(private_content_expire_key); 12267 if (privateContentExpires && new Date(privateContentExpires) < new Date()) { 12268 browserStorage.removeItem(private_content_key); 12269 } 12270 12271 if (isInvalid && cookieVersion) { 12272 fetchPrivateContent([]); 12273 } else if (cookieVersion && storageVersion && cookieVersion === storageVersion) { 12274 const privateContent = JSON.parse(browserStorage.getItem(private_content_key)); 12275 if ( 12276 privateContent && 12277 privateContentExpires && 12278 privateContent.cart && 12279 privateContent.customer 12280 ) { 12281 dispatchPrivateContent(privateContent); 12282 } else { 12283 fetchPrivateContent([]); 12284 } 12285 } else { 12286 fetchPrivateContent([]); 12287 } 12288 12289 } catch (error) { 12290 console.warn('Error retrieving Private Content:', error); 12291 } 12292 } 12293 12294 hyva.alpineInitialized(loadSectionData) 12295 window.addEventListener('reload-customer-section-data', loadSectionData); 12296 12297 function dispatchPrivateContent(data) { 12298 const privateContentEvent = new CustomEvent("private-content-loaded", { 12299 detail: { 12300 data: data 12301 } 12302 }); 12303 window.dispatchEvent(privateContentEvent); 12304 } 12305 12306 function fetchPrivateContent(sections) { 12307 fetch(`${BASE_URL}customer/section/load/?sections=${encodeURIComponent(sections.join(','))}`, { 12308 method: 'GET', 12309 headers: { 12310 'Content-Type': 'application/json', 12311 'X-Requested-With': 'XMLHttpRequest' 12312 } 12313 }) 12314 .then(response => response.json()) 12315 .then( 12316 data => { 12317 if (data) { 12318 try { 12319 const browserStorage = hyva.getBrowserStorage(); 12320 12321 // merge new data preserving non-invalidated sections 12322 const oldSectionData = JSON.parse(browserStorage.getItem(private_content_key) || '{}') || {}; 12323 12324 if ((! data.cart || ! data.cart.cartId) && oldSectionData['checkout-data']) { 12325 delete oldSectionData['checkout-data']; 12326 } 12327 const newSectionData = Object.assign(oldSectionData, data); 12328 12329 dispatchPrivateContent(newSectionData); 12330 12331 // don't persist messages, they've been dispatched already 12332 if (newSectionData.messages && newSectionData.messages.messages ) { 12333 newSectionData.messages.messages = []; 12334 } 12335 12336 browserStorage.setItem(private_content_key, JSON.stringify(newSectionData)); 12337 12338 const expiresAt = new Date(Date.now() + (ttl * 1000)).toISOString(); 12339 browserStorage.setItem(private_content_expire_key, expiresAt); 12340 12341 const newCookieVersion = hyva.getCookie(private_content_version_key); 12342 browserStorage.setItem(private_content_version_key, newCookieVersion); 12343 12344 // We don't need the section_data_ids in Hyvä, but we store them for compatibility 12345 // with Luma Fallback. Otherwise, not all sections are loaded in Luma Checkout 12346 hyva.setCookie( 12347 section_data_ids_key, 12348 JSON.stringify( 12349 Object.keys(data).reduce((sectionDataIds, sectionKey) => { 12350 sectionDataIds[sectionKey] = data[sectionKey]['data_id']; 12351 return sectionDataIds; 12352 }, {}) 12353 ), 12354 false, 12355 true 12356 ); 12357 } catch (error) { 12358 console.warn("Couldn't store privateContent", error); 12359 } 12360 } 12361 } 12362 ); 12363 } 12364 } 12365</script>
vendor: 1 bytes, line 12365
12365
12366<script> 12367 (() => { 12368 document.addEventListener('submit', event => event.target.action = event.target.action.replace('%25uenc%25', hyva.getUenc())); 12369 })() 12370</script>
vendor: 1 bytes, line 12370
12370
12371<script> 12372 (events => { 12373 const dispatchUserInteractionEvent = () => { 12374 events.forEach(type => window.removeEventListener(type, dispatchUserInteractionEvent)) 12375 window.dispatchEvent(new Event('init-external-scripts')) 12376 }; 12377 events.forEach(type => window.addEventListener(type, dispatchUserInteractionEvent, {once: true, passive: true})) 12378 })(['touchstart', 'mousemove', 'wheel', 'scroll', 'keydown']) 12379</script>
vendor: 1 bytes, line 12379
12379
12380<script type="text/javascript"> 12381 'use strict'; 12382 12383 document.addEventListener('alpine:init', () => { 12384 Alpine.data('initCalculateSavePercent', (productId, tierPrices, regularPrice, finalPrice) => ({ 12385 productId: productId, 12386 qty: null, 12387 tierPrices: tierPrices, 12388 regularPrice: regularPrice, 12389 oldFinalPrice: finalPrice, 12390 finalPrice: finalPrice, 12391 percentage: 0, 12392 12393 init() { 12394 let targetQty = document.querySelector('[id="qty[' + this.productId + ']"]'); 12395 this.qty = targetQty ? parseInt(targetQty.value) : 1; 12396 this.calculatePercentage(); 12397 this.$watch('finalPrice', value => this.calculatePercentage()) 12398 this.$watch('regularPrice', value => this.calculatePercentage()) 12399 }, 12400 calculatePercentage() { 12401 this.percentage = Math.round(100 - (this.finalPrice / this.regularPrice) * 100); 12402 }, 12403 eventListeners: { 12404 ['@update-prices.window'](event) { 12405 if (parseInt(event.detail.productId) !== parseInt(this.productId)) { 12406 return; 12407 } 12408 12409 this.finalPrice = event.detail.finalPrice.amount; 12410 this.oldFinalPrice = event.detail.finalPrice.amount; 12411 this.regularPrice = event.detail.oldPrice.amount; 12412 this.tierPrices = event.detail.tierPrices; 12413 this.calculateTierPrice(); 12414 }, 12415 ['@update-qty.window'](event) { 12416 if (parseInt(event.detail.productId) !== parseInt(this.productId)) { 12417 return; 12418 } 12419 12420 this.qty = event.detail.qty; 12421 this.calculateTierPrice(); 12422 }, 12423 ['@update-qty-'+productId+'.window'](event) { 12424 this.qty = event.detail; 12425 this.calculateTierPrice(); 12426 } 12427 }, 12428 calculateTierPrice() { 12429 if (this.qty <= 1 || Object.values(this.tierPrices).length === 0) { 12430 this.finalPrice = this.oldFinalPrice; 12431 return; 12432 } 12433 12434 let newPrice = Object.values(this.tierPrices).findLast(tier_price => parseInt(tier_price.price_qty || tier_price.qty) <= this.qty); 12435 this.finalPrice = newPrice ? newPrice.price : this.oldFinalPrice; 12436 } 12437 })) 12438 }) 12439</script>
vendor: 1 bytes, line 12439
12439
12440<script type="text/javascript"> 12441 'use strict'; 12442 12443 document.addEventListener('alpine:init', () => { 12444 Alpine.data('initPriceBox', () => ({ 12445 updatePrice(priceData) { 12446 const regularPriceLabel = this.$root.querySelector('.normal-price .price-label'); 12447 const oldPrice = this.$root.querySelector('.old-price'); 12448 12449 if (regularPriceLabel) { 12450 if (priceData.finalPrice.amount < priceData.oldPrice.amount) { 12451 regularPriceLabel.classList.add('hidden'); 12452 oldPrice.classList.remove('hidden'); 12453 } else { 12454 regularPriceLabel.classList.remove('hidden'); 12455 oldPrice.classList.add('hidden'); 12456 } 12457 } 12458 12459 const oldPriceElement = this.$root.querySelector('.old-price .price-wrapper .price') || this.$root.querySelector('.price'); 12460 const regularPriceElement = this.$root.querySelector('.normal-price [data-price-type=finalPrice].price-wrapper .price') || this.$root.querySelector('.price'); 12461 const basePriceElement = this.$root.querySelector('.normal-price [data-price-type=basePrice].price-wrapper .price'); 12462 oldPriceElement.innerText = hyva.formatPrice(priceData.oldPrice.amount); 12463 regularPriceElement.innerText = hyva.formatPrice(priceData.finalPrice.amount); 12464 basePriceElement && (basePriceElement.innerText = hyva.formatPrice(priceData.basePrice.amount)); 12465 } 12466 })) 12467 }) 12468</script>
vendor: 1 bytes, line 12468
12468
12469<script> 12470 function initConfigurableOptions(productId, optionConfig) { 12471 12472 function findPathParam(key) { 12473 const baseUrl = (BASE_URL.substr(0, 2) === '//' ? 'http:' : '') + BASE_URL; 12474 const baseUrlParts = (new URL(baseUrl)).pathname.replace(/\/$/, '').split('/'); 12475 const pathParts = window.location.pathname.split('/').slice(baseUrlParts.length + 3); 12476 for (let i = 0; i < pathParts.length; i += 2) { 12477 if (pathParts[i] === key && pathParts.length > i) { 12478 return pathParts[i + 1]; 12479 } 12480 } 12481 } 12482 12483 return { 12484 optionConfig, 12485 productId, 12486 itemId: (new URLSearchParams(window.location.search)).get('id') || findPathParam('id'), 12487 allowedAttributeOptions: [], 12488 selectedValues: [], 12489 init() { 12490 this.findAllowedAttributeOptions(); 12491 this.$nextTick(() => { 12492 window.dispatchEvent( 12493 new CustomEvent( 12494 'configurable-selection-init', 12495 { 12496 detail: { 12497 productId: this.productId, 12498 attributes: optionConfig && optionConfig.attributes ? optionConfig.attributes : undefined 12499 } 12500 } 12501 ) 12502 ); 12503 12504 if (typeof this.optionConfig.defaultValues === 'object') { 12505 for (const [optionId, value] of Object.entries(this.optionConfig.defaultValues)) { 12506 this.changeOption(optionId, value + ''); 12507 } 12508 } 12509 }); 12510 }, 12511 findSimpleIndex() { 12512 this.productIndex = this.calculateSimpleIndexForPartialSelection(this.selectedValues); 12513 }, 12514 calculateSimpleIndexForPartialSelection(selectedValues) { 12515 if (selectedValues.length === 0) return 0; 12516 let productIndexIds = Object.keys(this.optionConfig.index); 12517 Object.keys(this.optionConfig.attributes).forEach((attribute) => { 12518 const selectedAttributeValue = this.selectedValues[attribute]; 12519 const indexConfig = this.optionConfig.index; 12520 12521 const productsWithAttributeMatch = selectedAttributeValue 12522 ? productIndexIds.filter(productIndex => indexConfig[productIndex][attribute] === selectedAttributeValue) 12523 : []; 12524 12525 productIndexIds = productsWithAttributeMatch.length ? productsWithAttributeMatch : productIndexIds 12526 }) 12527 return productIndexIds[0]; 12528 }, 12529 calculateSimpleIndexForFullSelection(selectedValues) { 12530 const productIndexes = this.optionConfig.index; 12531 return Object.keys(productIndexes).find(productIndex => { 12532 const productCandidateOptions = productIndexes[productIndex]; 12533 12534 for (const productOption in productCandidateOptions) { 12535 if ( 12536 ! selectedValues[productOption] || 12537 selectedValues[productOption] !== productCandidateOptions[productOption] 12538 ) { 12539 return false; 12540 } 12541 } 12542 return productIndex; 12543 }); 12544 }, 12545 productIndex: 0, 12546 findAllowedAttributeOptions() { 12547 this.allowedAttributeOptions = this.calculateAllowedAttributeOptions(this.selectedValues); 12548 }, 12549 calculateAllowedAttributeOptions(selectedValues) { 12550 const allAttributes = this.optionConfig.attributes; 12551 const allAttributesSorted = Object.values(allAttributes).sort((a,b) => { 12552 return a.position - b.position 12553 }); 12554 12555 const selectionWithoutAttr = attrId => { 12556 return Object.keys(selectedValues).reduce((acc, id) => { 12557 if (id !== attrId) acc[id] = selectedValues[id]; 12558 return acc; 12559 }, {}) 12560 } 12561 12562 const newAllowedAttributeOptions = []; 12563 12564 allAttributesSorted.forEach(attribute => { 12565 const availableIndexes = this.calculateAvailableProductIndexes(selectionWithoutAttr(attribute.id)); 12566 const availableIndexesSet = new Set(availableIndexes); 12567 newAllowedAttributeOptions[attribute.id] = allAttributes[attribute.id].options.filter(option => { 12568 option.availableProductsId = option.products.filter(x => availableIndexesSet.has(x));
12569 option.saleable = this.isSaleable(option); 12570 12571 return option.products.some(product => availableIndexesSet.has(product)); 12572 }) 12573 }); 12574 return newAllowedAttributeOptions; 12575 }, 12576 isSaleable(option) { 12577 if(option.availableProductsId.length) { 12578 return !option.availableProductsId.every(productId => this.optionConfig.saleable[productId] === false); 12579 } 12580 return true; 12581 }, 12582 calculateAvailableProductIndexes(selectedOptions) { 12583 if (Object.keys(selectedOptions).length === 0) { 12584 return Object.keys(this.optionConfig.index); 12585 } 12586 12587 const selectedIds = Object.keys(selectedOptions); 12588 if (Object.values(this.optionConfig.salable || {}).length) { 12589 const selectedOptionIndexes = selectedIds.map(attrId => { 12590 const optionValue = selectedOptions[attrId]; 12591 return this.optionConfig.salable[attrId] && this.optionConfig.salable[attrId][optionValue] || [] 12592 }) 12593 return selectedOptionIndexes.reduce((acc, optionIndexes) => { 12594 return acc.filter(index => optionIndexes.includes(index)); 12595 }); 12596 } else { 12597 const productIndexes = this.optionConfig.index; 12598 return Object.keys(productIndexes).filter(index => { 12599 const currentIndex = productIndexes[index]; 12600 return selectedIds.some(attrId => currentIndex[attrId] === `${selectedOptions[attrId]}`); 12601 }); 12602 } 12603 }, 12604 findAttributeByOptionId(optionId) { 12605 for (const attributeId in this.optionConfig.attributes) { 12606 const attributeOptions = this.optionConfig.attributes[attributeId].options || []; 12607 if (attributeOptions.find(option => option.id === optionId)) { 12608 return attributeId; 12609 } 12610 } 12611 }, 12612 getAllowedAttributeOptions(attributeId) { 12613 return this.allowedAttributeOptions[attributeId] || [] 12614 }, 12615 getProductIdsForOption(option) { 12616 const attributeId = this.findAttributeByOptionId(option.id); 12617 const allOptions = this.optionConfig.attributes[attributeId]; 12618 const opt = (allOptions && allOptions.options || []).find(o => o.id === option.id); 12619 return opt && opt.products 12620 ? opt.products 12621 : []; 12622 }, 12623 findProductIdsForPartialSelection(optionSelection) { 12624 const candidateProducts = Object.values(optionSelection).reduce((candidates, optionId) => { 12625 const newCandidates = this.getProductIdsForOption({id: optionId}); 12626 return candidates === null 12627 ? newCandidates 12628 : candidates.filter(productId => newCandidates.includes(productId)); 12629 }, null); 12630 return candidateProducts || []; 12631 }, 12632 findCheapestProductForPartialSelection(optionSelection) { 12633 const candidateProducts = this.findProductIdsForPartialSelection(optionSelection); 12634 return candidateProducts.reduce((cheapest, simpleIdx) => { 12635 // in the first iteration we start with simpleIdx as the currently cheapest product 12636 if (! this.optionConfig.optionPrices[cheapest]) return simpleIdx; 12637 const knownCheapestPrice = this.optionConfig.optionPrices[cheapest].finalPrice.amount; 12638 return knownCheapestPrice > this.optionConfig.optionPrices[simpleIdx].finalPrice.amount 12639 ? simpleIdx 12640 : cheapest; 12641 }, 0) 12642 }, 12643 findProductIdToUseForOptionPrice(option) { 12644 // try to find a product for a complete selection 12645 const attributeId = this.findAttributeByOptionId(option.id); 12646 const optionSelection = Object.assign({}
12646, this.selectedValues, {[attributeId]: option.id}); 12647 const matchingSimpleIndex = this.calculateSimpleIndexForFullSelection(optionSelection); 12648 // if there is no complete selection, use the cheapest product for the option 12649 return matchingSimpleIndex || this.findCheapestProductForPartialSelection(optionSelection); 12650 }, 12651 getAttributeOptionLabel(option) { 12652 const optionProduct = this.findProductIdToUseForOptionPrice(option); 12653 if ((! optionProduct) || (optionProduct === this.productIndex)) { 12654 return option.label; 12655 } 12656 12657 const currentPrice = this.getOptionPriceAdjustmentBasePrice(); 12658 12659 if (this.optionConfig.optionPrices[optionProduct]) { 12660 const optionPrice = this.optionConfig.optionPrices[optionProduct].finalPrice.amount; 12661 if (optionPrice !== currentPrice){ 12662 return option.label + ' ' + hyva.formatPrice(optionPrice - currentPrice, true); 12663 } 12664 } 12665 return option.label; 12666 }, 12667 getOptionPriceAdjustmentBasePrice() { 12668 if (this.optionConfig.optionPrices[this.productIndex]) { 12669 return this.optionConfig.optionPrices[this.productIndex].finalPrice.amount 12670 } 12671 const cheapestForSelection = this.findCheapestProductForPartialSelection(this.selectedValues); 12672 return this.optionConfig.optionPrices[cheapestForSelection] 12673 ? this.optionConfig.optionPrices[cheapestForSelection].finalPrice.amount 12674 : this.optionConfig.prices.finalPrice.amount; // default price if no option selection 12675 }, 12676 changeOption(optionId, value) { 12677 if (value === '') { 12678 // create new array so the length property is reset if no option is selected (avoiding delete) 12679 this.selectedValues = this.selectedValues.reduce((newSelection, val, opt) => { 12680 if (opt !== optionId) { 12681 newSelection[opt] = val; 12682 } 12683 return newSelection; 12684 }, []); 12685 } else { 12686 this.selectedValues[optionId] = value; 12687 } 12688 this.findSimpleIndex(); 12689 this.findAllowedAttributeOptions(); 12690 this.updatePrices(); 12691 this.updateGallery(); 12692 window.dispatchEvent( 12693 new CustomEvent( 12694 'configurable-selection-changed', 12695 { 12696 detail: { 12697 productId: this.productId, 12698 optionId: optionId, 12699 value: value, 12700 attributes: optionConfig && optionConfig.attributes ? optionConfig.attributes : undefined, 12701 productIndex: this.productIndex, 12702 selectedValues: this.selectedValues, 12703 candidates: this.findProductIdsForPartialSelection(this.selectedValues), 12704 saleable: this.productIndex ? this.optionConfig.saleable[this.productIndex] : true 12705 } 12706 } 12707 ) 12708 ); 12709 }, 12710 calculateIsMinimalPrice() { 12711 return ( 12712 this.selectedValues.filter(value => !!value).length < 12713 Object.keys(this.optionConfig.attributes).length 12714 ); 12715 }, 12716 updatePrices() { 12717 const value = this.productIndex ? 12718 this.optionConfig.optionPrices[this.productIndex] : 12719 this.optionConfig.prices; 12720 window.dispatchEvent( 12721 new CustomEvent( 12722 "update-prices-" + this.productId, 12723 { 12724 detail: Object.assign( 12725 value, 12726 { isMinimalPrice: this.calculateIsMinimalPrice() } 12727 ) 12728 } 12729 ) 12730 ); 12731 window.dispatchEvent( 12732 new CustomEvent( 12733 "update-prices", 12734 { 12735 detail: Object.assign( 12736 value, 12737 { 12738 productId: this.productId, 12739 isMinimalPrice: this.calculateIsMinimalPrice() 12740 } 12741 ) 12742 } 12743 ) 12744 ); 12745 12746 }, 12747 updateGallery () { 12748 const value = this.productIndex ? 12749 this.optionConfig.images[this.productIndex] : 12750 Object.values(this.optionConfig.images)[0]; 12751 12752 value && window.dispatchEvent( 12753 new CustomEvent( 12754 "update-gallery", 12755 { detail: value } 12756 ) 12757 ); 12758 }, 12759 onGetCartData(data) { 12760 this.preselectCartItems(data); 12761 this.preselectSaleableAttributeOptions(); 12762 this.preselectSkuChildAttributeItems(); 12763 this.preselectQuerySimpleSkuItems(); 12764 this.preselectQuerystringItems(); 12765 this.preselectLocationHashItems(); 12766 }, 12767 preselectCartItems(data) { 12768 // pre-select options based on cart data for current (quote) itemId 12769 const cart = data && data.cart; 12770 if (cart && cart.items) { 12771 const cartItem = cart.items.find((item) => { 12772 return ( 12773 item.item_id === this.itemId 12774 && item.product_id === this.productId 12775 ) 12776 }); 12777 if (cartItem && cartItem.options && cartItem.options.length) { 12778 cartItem.options.map(option => { 12779 this.changeOption(option.option_id, option.option_value); 12780 }) 12781 } 12782 } 12783 }, 12784 preselectSkuChildAttributeItems() { 12785 // pre-select options based on preselect_sku_child product attribute value 12786 const skuChild = this.optionConfig.preselect_sku_child; 12787 12788 if (skuChild !== undefined && skuChild.length) { 12789 this.preselectOptionBySku(skuChild); 12790 } 12791 }, 12792 preselectQuerySimpleSkuItems() { 12793 // pre-select options based on simple sku like ?sku=WP02-28-Purple 12794 const urlQueryParams = new URLSearchParams(window.location.search.replace('?','')); 12795 const skuParam = urlQueryParams.get('sku'); 12796 12797 if (skuParam) { 12798 this.preselectOptionBySku(skuParam); 12799 } 12800 }, 12801 preselectOptionBySku(optionSku) { 12802 if (typeof this.optionConfig.childProducts[optionSku] === "undefined") { 12803 return; 12804 } 12805 12806 const productId = this.optionConfig.childProducts[optionSku]; 12807 12808 if (this.optionConfig.index[productId]) { 12809 let targetProduct = this.optionConfig.index[productId]; 12810 Object.entries(targetProduct).map((options) => { 12811 const attributeId = options[0]; 12812 const attributeCode = options[1]; 12813 this.changeOption(attributeId, attributeCode); 12814 }) 12815 } 12816 }, 12817 preselectQuerystringItems() { 12818 // pre-select option like ?size=167 12819 const urlQueryParams = new URLSearchParams(window.location.search.replace('?','')); 12820 Object.values(this.optionConfig.attributes).map(attribute => { 12821 urlQueryParams.get(attribute.code) && 12822 this.changeOption(attribute.id, urlQueryParams.get(attribute.code)); 12823 }); 12824 }, 12825 preselectLocationHashItems() { 12826 // pre-select option like #144=167 12827 const urlHashParams = new URLSearchParams(window.location.hash.replace('#','')); 12828 Object.values(this.optionConfig.attributes).map(attribute => { 12829 urlHashParams.get(attribute.id) && 12830 this.changeOption(attribute.id, urlHashParams.get(attribute.id)); 12831 }); 12832 }, 12833 preselectSaleableAttributeOptions() { 12834 // pre-select attribute options by stock preference 12835 const saleableAttributeOptions = this.findSaleableAttributeOptions(); 12836 let modifyAttributes = true; 12837 let attributeOptionsToSelect = []; 12838 // Check all attributes than can be selected 12839 saleableAttributeOptions.forEach((attributeOption, attributeId) => { 12840 if (attributeOption.length === 1 && Object.values(attributeOption[0].saleable).find(x => x === true)) { 12841 attributeOptionsToSelect.push([attributeId, attributeOption[0].optionId]); 12842 } else { 12843 let countSaleable = 0; 12844 let optionId = null; 12845 attributeOption.forEach(option => { 12846 if (Object.values(option.saleable).find(x => x === true)) { 12847 optionId = option.optionId; 12848 countSaleable += 1; 12849 } 12850 }) 12851 12852 if (countSaleable === 1 && optionId) { 12853 attributeOptionsToSelect.push([attributeId, optionId]); 12854 } else { 12855 modifyAttributes = false;
12856 } 12857 } 12858 }); 12859 12860 // Only if all attributes of the product can be selected, then select them 12861 if (modifyAttributes) { 12862 attributeOptionsToSelect.forEach((attributeOption) => { 12863 this.changeOption(attributeOption[0], attributeOption[1]); 12864 }); 12865 } 12866 }, 12867 findSaleableAttributeOptions() { 12868 const saleableAttributeOptions = []; 12869 const saleableOptions = Object.entries(this.optionConfig.saleable).map(([id, saleable]) => ({id,saleable})); 12870 12871 Object.values(this.optionConfig.attributes).forEach(attribute => { 12872 let attributeId = attribute.id; // size: 143, color: 93 12873 let options = attribute.options; 12874 saleableAttributeOptions[attributeId] = 12875 options.map(option => { 12876 let productsOption = option.products; 12877 let saleable = []; 12878 productsOption.forEach(product => { // products: ["1820", "1821", "1822"] 12879 saleable[product] = false; 12880 saleableOptions.forEach(x => { 12881 if (x.id === product && x.saleable) { 12882 saleable[product] = true; 12883 } 12884 }); 12885 }); 12886 12887 // {optionId: 50, saleable: [1820: true, 1821: false] 12888 return {optionId: option.id, saleable: saleable} 12889 }); 12890 }); 12891 12892 return saleableAttributeOptions; 12893 } 12894 } 12895 } 12896 12897</script>
vendor: 1 bytes, line 12897
12897
12898<script> 12899 function initSwatchOptions(swatchConfig) { 12900 return { 12901 swatchConfig, 12902 getAttributeSwatchData(attributeId) { 12903 const swatchConfig = Object.assign({}, this.swatchConfig[attributeId]); 12904 swatchConfig['details'] = JSON.parse(swatchConfig['additional_data']); 12905 12906 return swatchConfig; 12907 }, 12908 getAllAttributeOptions(attributeId) { 12909 return ( 12910 this.optionConfig.attributes[attributeId] && 12911 this.optionConfig.attributes[attributeId].options 12912 ) || [] 12913 }, 12914 optionIsActive(attributeId, optionId) { 12915 // return true if a product with this option is in stock 12916 return !!this.getAllowedAttributeOptions(attributeId).find( 12917 option => option.id === optionId 12918 ) 12919 }, 12920 optionIsEnabled(attributeId, optionId) { 12921 // return true if a product with this option is enabled 12922 for (const productId in this.optionConfig.index) { 12923 if (this.optionConfig.index[productId][attributeId] === optionId) { 12924 return true; 12925 } 12926 } 12927 return false; 12928 }, 12929 mapSwatchTypeNumberToTypeCode(typeNumber) { 12930 switch ("" + typeNumber) { 12931 case "1": 12932 return "color" 12933 case "2": 12934 return "image" 12935 case "3": 12936 return "empty" 12937 case "0": 12938 default: 12939 return "text" 12940 } 12941 }, 12942 getTypeOfFirstOption(attributeId) { 12943 for (const optionId in this.swatchConfig[attributeId]) { 12944 const option = this.swatchConfig[attributeId][optionId]; 12945 if (typeof option.type !== 'undefined') { 12946 return this.mapSwatchTypeNumberToTypeCode(option.type); 12947 } 12948 } 12949 }, 12950 getVisualSwatchType(attributeId, targetOptionId) { 12951 // If a type configuration is present for the given option id, use it 12952 const config = this.swatchConfig[attributeId]; 12953 if (config[targetOptionId] && typeof config[targetOptionId].type !== 'undefined') { 12954 return this.mapSwatchTypeNumberToTypeCode(config[targetOptionId].type); 12955 } 12956 12957 // Otherwise - if no config is present for the target option - use the type of the first option 12958 // with a type property from the attribute, thus assuming its the same type as the target option. 12959 // (This edge case condition can occur on single swatch products if some options are not salable) 12960 return this.getTypeOfFirstOption(attributeId); 12961 }, 12962 getSwatchType(attributeId, optionId) { 12963 // Deserialize the attribute details the first time they are used 12964 if (this.swatchConfig[attributeId] && ! this.swatchConfig[attributeId].details) { 12965 this.swatchConfig[attributeId] = this.getAttributeSwatchData(attributeId); 12966 } 12967 const type = this.swatchConfig[attributeId] && 12968 this.swatchConfig[attributeId].details && 12969 this.swatchConfig[attributeId].details.swatch_input_type || 12970 "empty"; 12971 return type === 'visual' ? this.getVisualSwatchType(attributeId, optionId) : type; 12972 }, 12973 isTextSwatch(attributeId, optionId) { 12974 return this.getSwatchType(attributeId, optionId) === 'text'; 12975 }, 12976 isVisualSwatch(attributeId, optionId) { 12977 const type = this.getSwatchType(attributeId, optionId); 12978 12979 return ['image', 'color'].includes(type); 12980 }, 12981 getSwatchBackgroundStyle(attributeId, optionId) {
12982 const config = this.getSwatchConfig(attributeId, optionId); 12983 const type = this.getSwatchType(attributeId, optionId); 12984 12985 if (type === "color") { 12986 return 'background-color:' + config.value; 12987 } else if (type === "image") { 12988 return "background-image: url('" + config.value + "')"; 12989 } else { 12990 return 'background-color: #ffffff'; 12991 } 12992 }, 12993 getSwatchText(attributeId, optionId) { 12994 const config = this.getSwatchConfig(attributeId, optionId); 12995 return config.label || config.value || this.getOptionLabelFromOptionConfig(attributeId, optionId); 12996 }, 12997 getOptionLabelFromOptionConfig(attributeId, optionId) { 12998 // Fallback if no value is present in swatchConfig data 12999 // Reference issue https://gitlab.hyva.io/hyva-themes/magento2-default-theme/-/issues/190 13000 const option = this.getAllAttributeOptions(attributeId).filter(option => option.id === optionId); 13001 return option && option[0] && option[0].label ||''; 13002 }, 13003 getSwatchConfig(attributeId, optionId) { 13004 return this.swatchConfig[attributeId] && this.swatchConfig[attributeId][optionId] 13005 ? this.swatchConfig[attributeId][optionId] 13006 : false; 13007 }, 13008 activeTooltipItem: false, 13009 tooltipPositionElement: false, 13010 isTooltipVisible() { 13011 return this.activeTooltipItem &&
13012 this.getSwatchConfig( 13013 this.activeTooltipItem.attribute, 13014 this.activeTooltipItem.item 13015 ); 13016 }, 13017 getTooltipImageStyle(attributeId, optionId) { 13018 const config = this.getSwatchConfig(attributeId, optionId); 13019 const type = this.getSwatchType(attributeId, optionId); 13020 13021 if (type === "color") { 13022 return 'background-color:' + config.value + '; width: 110px; height: 90px;'; 13023 } else if (type === "image") { 13024 return "background: #ffffff url('" + config.thumb + 13025 "') center center no-repeat; width: 110px; height: 90px;"; 13026 } else { 13027 return 'display:none'; 13028 } 13029 }, 13030 getTooltipPosition() { 13031 return this.tooltipPositionElement ? 13032 `width: ${this.tooltipPositionElement.offsetWidth}px;` + 13033 `top: ${this.tooltipPositionElement.offsetTop}px;` + 13034 `left: ${ 13035 this.tooltipPositionElement.offsetLeft - ( 13036 this.tooltipPositionElement.closest('.snap') && 13037 this.tooltipPositionElement.closest('.snap').scrollLeft || 13038 0 13039 ) 13040 }px;` : '' 13041 }, 13042 getTooltipLabel() { 13043 return this.getSwatchConfig(this.activeTooltipItem.attribute, this.activeTooltipItem.item).label 13044 }, 13045 focusedLabel: false, 13046 focusLabel(optionId) { 13047 this.focusedLabel = optionId; 13048 }, 13049 blurLabel() { 13050 this.focusedLabel = false; 13051 }, 13052 showSwatches: false, 13053 initShowSwatchesIntersect() { 13054 if ('IntersectionObserver' in window && !window.scrollY) { 13055 let io = new IntersectionObserver( 13056 entries => { 13057 entries.map(entry => { 13058 if (entry.isIntersecting) { 13059 this.showSwatches = true; 13060 io.unobserve(this.$root); 13061 } 13062 }) 13063 } 13064 ); 13065 io.observe(this.$root); 13066 } else { 13067 this.showSwatches = true 13068 } 13069 } 13070 } 13071 } 13072</script>
vendor: 1 bytes, line 13072
13072
13073<script defer type="text/javascript"> 13074 'use strict'; 13075 13076 document.addEventListener('alpine:init', () => { 13077 Alpine.data('showHoverImage', () => ({ 13078 onHover() { 13079 this.toggleImage(true); 13080 }, 13081 onLeave() { 13082 this.toggleImage(false); 13083 }, 13084 toggleImage(hover) { 13085 if (this.$root.getAttribute('src-hover')) { 13086 this.$root.setAttribute('src', hover ? this.$root.getAttribute('src-hover') : this.$root.getAttribute('src-leave')); 13087 } 13088 } 13089 })) 13090 }) 13091</script>
vendor: 1 bytes, line 13091
13091
13092<script> 13093 const selector = '.form-email, .form-input, .form-multiselect, .form-select, .form-textarea'; 13094 const BINDED = 'binded'; 13095 13096 function _bindEvents($inputField) { 13097 let field = $inputField.closest('.field'); 13098 13099 if (!field || field.classList.contains(BINDED)) { 13100 return false; 13101 } 13102 13103 if ($inputField.tagName === 'SELECT') { 13104 field.classList.add('select'); 13105 13106 if (($inputField.options[$inputField.selectedIndex] && $inputField.options[$inputField.selectedIndex].text.length > 0) || $inputField.hasAttribute('multiple')) { 13107 field.classList.add('active'); 13108 } 13109 } 13110 13111 if ($inputField.tagName === 'TEXTAREA') { 13112 field.classList.add('textarea'); 13113 } 13114 13115 if ($inputField.value && $inputField.value.length > 0 || $inputField.placeholder && $inputField.placeholder.length > 0) { 13116 if ($inputField.getAttribute('aria-invalid')) { 13117 try { 13118 $inputField.closest('form').validation(); 13119 $inputField.closest('form').validation('isValid'); 13120 } catch (e) { 13121 } 13122 } 13123 13124 field.classList.add('active'); 13125 } 13126 13127 const inputs = field.querySelectorAll('input'); 13128 if (inputs.length > 1 && Array.from(inputs).some(input => input.value.trim() !== '')) { 13129 field.classList.add('active'); 13130 } 13131 13132 $inputField.addEventListener('focus', function () { 13133 field.classList.add('active'); 13134 }); 13135 $inputField.addEventListener('input', function () { 13136 field.classList.add('active'); 13137 }); 13138 $inputField.addEventListener('blur', function () { 13139 const inputs = field.querySelectorAll('input'); 13140 if (inputs.length > 1 && Array.from(inputs).some(input => input.value.trim() !== '')) { 13141 return; 13142 } 13143 13144 if ($inputField.tagName === 'SELECT' && $inputField.options[$inputField.selectedIndex] && $inputField.options[$inputField.selectedIndex].text.length <= 0) { 13145 field.classList.remove('active') 13146 } 13147 if (!this.value && $inputField.tagName !== 'SELECT') { 13148 field.classList.remove('active') 13149 } 13150 }); 13151 13152 $inputField.addEventListener('change', function () { 13153 if ($inputField.tagName === 'SELECT') { 13154 if (($inputField.options[$inputField.selectedIndex] && $inputField.options[$inputField.selectedIndex].text.length > 0) || $inputField.hasAttribute('multiple')) { 13155 this.closest('.field').classList.add('active'); 13156 } else { 13157 this.closest('.field').classList.remove('active') 13158 } 13159 } 13160 13161 let form = $inputField.closest('form'); 13162 if (form && form.length) { 13163 try { 13164 if (typeof $inputField.validation === 'function') { 13165 $inputField.validation(); 13166 $inputField.validation('isValid'); 13167 } 13168 } catch (e) { 13169 } 13170 } 13171 13172 if ($inputField.tagName === "INPUT") { 13173 if ($inputField.value && $inputField.value.length > 0 && !field.classList.contains('active')) { 13174 field.classList.add('active'); 13175 } 13176 } 13177 13178 }); 13179 13180 field.classList.add(BINDED); 13181 } 13182 13183 window.addEventListener('load', function () { 13184 const targetNode = document.body; 13185 const config = {attributes: false, childList: true, subtree: true}; 13186 13187 let elements = document.querySelectorAll(selector); 13188 Array.prototype.forEach.call(elements, function ($inputField, i) { 13189 _bindEvents($inputField); 13190 }); 13191 13192 const callback = function (mutationsList, observer) { 13193 mutationsList.forEach(function (mutation) { 13194 for (let i = 0; i < mutation.addedNodes.length; i++) { 13195 if (mutation.addedNodes[i].nodeType === 1) { 13196 if (mutation.addedNodes[i].closest(selector) || mutation.addedNodes[i].querySelectorAll(selector).length) { 13197 let closest = mutation.addedNodes[i].closest(selector); 13198 let childs = mutation.addedNodes[i].querySelectorAll(selector); 13199 let $inputFields = []; 13200 13201 if (closest) { 13202 $inputFields.push(closest); 13203 } 13204 13205 if (childs) { 13206 $inputFields.push(...childs); 13207 } 13208 13209 Array.prototype.forEach.call($inputFields, function ($inputField, i) { 13210 let field = $inputField.closest('.field'); 13211 if (field && field.classList) { 13212 field.classList.remove('active'); 13213 field.classList.remove('select'); 13214 field.classList.remove('textarea'); 13215 field.classList.remove(BINDED); 13216 } 13217 _bindEvents($inputField); 13218 }); 13219 } 13220 } 13221 } 13222 }); 13223 }; 13224 13225 const observer = new MutationObserver(callback); 13226 observer.observe(targetNode, config); 13227 if(typeof Livewire !== 'undefined'){
13228 Livewire.hook('element.updated', (el, component) => { 13229 let closest = el.closest(selector); 13230 let childs = el.querySelectorAll(selector); 13231 let $inputFields = []; 13232 13233 if (closest) { 13234 $inputFields.push(closest); 13235 } 13236 13237 if (childs) { 13238 $inputFields.push(...childs); 13239 } 13240 13241 Array.prototype.forEach.call($inputFields, function ($inputField, i) { 13242 let field = $inputField.closest('.field'); 13243 if (field && field.classList) { 13244 field.classList.remove('active'); 13245 field.classList.remove('select'); 13246 field.classList.remove('textarea'); 13247 field.classList.remove(BINDED); 13248 } 13249 _bindEvents($inputField); 13250 }); 13251 }) 13252 13253 Livewire.hook('message.processed', (message, component) => { 13254 let elements = document.querySelectorAll(selector); 13255 Array.prototype.forEach.call(elements, function ($inputField, i) { 13256 let field = $inputField.closest('.field'); 13257 if (field && field.classList) { 13258 field.classList.remove('active'); 13259 field.classList.remove('select'); 13260 field.classList.remove('textarea'); 13261 field.classList.remove(BINDED); 13262 } 13263 _bindEvents($inputField); 13264 }); 13265 }) 13266 } 13267 }); 13268</script>
vendor: 1 bytes, line 13268
13268
13269<script> 13270 window.addEventListener("load", () => { 13271 setTimeout(() => { 13272 window.dispatchEvent( 13273 new CustomEvent("thirdparty-trigger") 13274 ); 13275 }, 1500); 13276 }); 13277</script>
vendor: 1 bytes, line 13277
13277
13278<script> 13279 class RktCarousel { 13280 /** 13281 * Constructor 13282 */ 13283 constructor (selector, options = {}, hooks = []) { 13284 this.container = document.querySelector(selector); 13285 if (!this.container) return; 13286 13287 // Selectors 13288 this.slidesSelector = options.slidesSelector || '.js-carousel__slide'; 13289 this.trackSelector = options.trackSelector || '.js-carousel__track'; 13290 this.slides = []; 13291 this.track = this.container.querySelector(this.trackSelector); 13292 this.slidesLength = 0; 13293 13294 // Breakpoints 13295 this.currentBreakpoint = undefined; 13296 this.breakpoints = options.breakpoints || {}; 13297 13298 // Hooks 13299 this.hooks = hooks; 13300 13301 // Options 13302 this.initialOptions = { 13303 loop: options.loop || false, 13304 autoplay: options.autoplay || false, 13305 autoplaySpeed: options.autoplaySpeed || 3000, 13306 transitionSpeed: options.transitionSpeed || 650, 13307 slidesPerView: options.slidesPerView || 1, 13308 spacing: options.spacing || 0, 13309 }; 13310 this.options = this.initialOptions; 13311 13312 // Transitions 13313 this.animationStart = undefined; 13314 this.animation = undefined; 13315 this.animationCurrentTrans = 0; 13316 this.animationIndex = 0; 13317 13318 // Animations 13319 window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || 13320 window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; 13321 window.cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame; 13322 13323 13324 // Functional 13325 this.autoplayInterval = undefined; 13326 this.isButtonRightDisabled = false; 13327 this.isButtonLeftDisabled = false; 13328 this.currentIndex = 0; 13329 this.maxIndex = 0; 13330 this.isInfinite = false; 13331 this.isPrevInfinite = false; 13332 13333 // Swipe Event 13334 this.swipeStartX = undefined; 13335 this.swipeStartY = undefined; 13336 this.swipeThreshold = 100; // Required min distance traveled to be considered swipe. 13337 this.swipeRestraint = 100; // Maximum distance allowed at the same time in perpendicular direction. 13338 this.swipeDir = undefined; 13339 13340 if (!this.track) return; 13341 13342 this.addEventListeners(); 13343 this.initCarousel(); 13344 }; 13345 13346 /** 13347 * Fire hook. 13348 */ 13349 hook (name) { 13350 this.hooks[name] && this.hooks[name](this); 13351 }; 13352 13353 /** 13354 * Is touchable device? 13355 */ 13356 isTouchableDevice () { 13357 return window.matchMedia("(pointer: coarse)").matches; 13358 }; 13359 13360 /** 13361 * Handle Swipe. 13362 */ 13363 handleSwipe () { 13364 switch (this.swipeDir) { 13365 case 'top': 13366 case 'bottom': 13367 break; 13368 case 'left': 13369 this.next(); 13370 break; 13371 case 'right': 13372 this.prev(); 13373 break; 13374 default: 13375 break; 13376 } 13377 }; 13378 13379 /** 13380 * On swipe start. 13381 */ 13382 onSwipeStart (e) { 13383 if (!this.isTouchableDevice() || !e.changedTouches) return; 13384 const touch = e.changedTouches[0]; 13385 this.swipeStartX = touch.pageX; 13386 this.swipeStartY = touch.pageY; 13387 }; 13388 13389 /** 13390 * Set swipe direction. 13391 */ 13392 setSwipeDirection (e) { 13393 const touch = e.changedTouches[0]; 13394 const distX = touch.pageX - this.swipeStartX; 13395 const distY = touch.pageY - this.swipeStartY; 13396 13397 if (Math.abs(distX) >= this.swipeThreshold && Math.abs(distY) <= this.swipeRestraint) { 13398 this.swipeDir = (distX < 0) ? 'left' : 'right'; 13399 } else if (Math.abs(distY) >= this.swipeThreshold && Math.abs(distX) <= this.swipeRestraint) { 13400 this.swipeDir = (distY < 0) ? 'up' : 'down'; 13401 } 13402 }; 13403 13404 /** 13405 * On swipe move. 13406 */ 13407 onSwipeMove (e) { 13408 if (!this.isTouchableDevice() || !e.changedTouches) return; 13409 this.setSwipeDirection(e); 13410 if (['left', 'right'].includes(this.swipeDir) && e.cancelable) e.preventDefault(); 13411 }; 13412 13413 /** 13414 * On swipe end. 13415 */ 13416 onSwipeEnd (e) { 13417 if (!this.isTouchableDevice() || !e.changedTouches) return; 13418 this.setSwipeDirection(e); 13419 this.handleSwipe(); 13420 }; 13421 13422 /** 13423 * Add Event Listeners. 13424 */ 13425 addEventListeners () { 13426 // Resize Events 13427 window.addEventListener('orientationchange', () => this.onResize()); 13428 window.addEventListener('resize', () => this.onResize()); 13429 13430 // Swipe Events 13431 this.container.addEventListener('touchstart', (e) => this.onSwipeStart(e), { 13432 passive: true 13433 }); 13434 this.container.addEventListener('touchmove', (e) => this.onSwipeMove(e), { 13435 passive: true 13436 }); 13437 this.container.addEventListener('touchend', (e) => this.onSwipeEnd(e), { 13438 passive: true 13439 }); 13440 }; 13441 13442 /** 13443 * On Resize Event. 13444 */ 13445 onResize () { 13446 const breakpoint = this.checkBreakpoint(); 13447 breakpoint && this.buildCarousel(); 13448 this.hook('resized'); 13449 }; 13450 13451 /** 13452 * Configure Autoplay. 13453 */ 13454 setUpAutoplay () { 13455 if (!this.options.autoplay) return; 13456 clearInterval(this.autoplayInterval); 13457 this.autoplayInterval = setInterval(() => this.next(), this.options.autoplaySpeed); 13458 }; 13459 13460 /** 13461 * Check current breakpoint. 13462 */ 13463 checkBreakpoint() { 13464 if (!this.breakpoints) return; 13465 13466 const currentBreakpoint = Object.keys(this.breakpoints).reverse().find(breakpoint => { 13467 const media = `(min-width: ${breakpoint}px)`; 13468 return window.matchMedia(media).matches; 13469 }); 13470 13471 if (this.currentBreakpoint === currentBreakpoint) return; 13472 13473 this.currentBreakpoint = currentBreakpoint; 13474 const options = currentBreakpoint ? this.breakpoints[currentBreakpoint] : this.initialOptions; 13475 this.options = { 13476 ...this.initialOptions, 13477 ...options 13478 }; 13479 return true; 13480 }; 13481 13482 /** 13483 * Set buttons visibility. 13484 */ 13485 setButtonsVisibility () { 13486 this.isButtonLeftDisabled = !this.options.loop && this.currentIndex === 0; 13487 this.isButtonRightDisabled = !this.options.loop && this.currentIndex === (this.maxIndex - 1); 13488 }; 13489 13490 /**
13491 * Clear Carousel Styles. 13492 */ 13493 clearCarouselStyles () { 13494 const trackStyles = ['grid-auto-columns', 'gap', 'transition', 'left']; 13495 trackStyles.map(style => this.track.style.removeProperty(style)); 13496 const slideStyles = ['grid-column-start', 'grid-column-end', 'grid-row-start', 'grid-row-end', 'left']; 13497 this.slides.forEach(slide => { 13498 slideStyles.map(style => slide.style.removeProperty(style)); 13499 }); 13500 }; 13501 13502 /** 13503 * Set Carousel Classes. 13504 */ 13505 setCarouselStyles () { 13506 if (!this.slides) return; 13507 const slidesPerView = this.options.slidesPerView; 13508 const slideWidth = 100 / slidesPerView; 13509 const gap = (this.options.spacing * (slidesPerView - 1)) / slidesPerView; 13510 this.track.style.gridAutoColumns = `calc(${slideWidth}% - ${gap}px)`; 13511 this.track.style.gridGap = `${this.options.spacing}px`; 13512 this.track.style.left = 0; 13513 }; 13514 13515 /** 13516 * Build Carousel with current Options. 13517 */ 13518 buildCarousel () { 13519 this.maxIndex = Math.ceil(this.slidesLength / this.options.slidesPerView); 13520 this.clearCarouselStyles(); 13521 this.setCarouselStyles(); 13522 this.setButtonsVisibility(); 13523 this.setUpAutoplay(); 13524 this.currentIndex = 0; 13525 this.hook('built'); 13526 }; 13527 13528 /** 13529 * Initialize carousel and fire created event. 13530 */ 13531 initCarousel () { 13532 this.slides = this.container.querySelectorAll(this.slidesSelector); 13533 this.slidesLength = this.slides ? this.slides.length : 0; 13534 this.checkBreakpoint(); 13535 this.buildCarousel(); 13536 this.hook('created'); 13537 }; 13538 13539 /** 13540 * On Animation End. 13541 */ 13542 onAnimationEnd () { 13543 const gap = this.options.spacing * this.animationIndex; 13544 const trans = this.animationIndex * -100; 13545 this.track.style.left = `calc(${trans}% - ${gap}px)`; 13546 this.animationCurrentTrans = trans; 13547 this.animation = null; 13548 this.isInfinite && this.clearInfinite(); 13549 this.isPrevInfinite && this.clearPrevInfinite(); 13550 } 13551 13552 /** 13553 * Cancel Animation frame. 13554 */ 13555 moveAnimateAbort () { 13556 if (!this.animation) return; 13557 13558 window.cancelAnimationFrame(this.animation); 13559 this.onAnimationEnd(); 13560 }; 13561 13562 /** 13563 * Animate Left. 13564 * @param timestamp 13565 * @param trans 13566 * @param gap 13567 * @param duration 13568 */ 13569 animateLeft (timestamp, trans, gap, duration) { 13570 const runtime = timestamp - this.animationStart; 13571 const easing = t => 1 - Math.pow(1 - t, 5); 13572 const progress = easing(runtime / duration); 13573 const dist = ((trans * progress) + (this.animationCurrentTrans * (1 - progress))).toFixed(2); 13574 this.track.style.left = `calc(${dist}% - ${gap}px)`; 13575 13576 if (runtime >= duration) { 13577 this.onAnimationEnd(); 13578 return; 13579 } 13580 13581 this.animation = window.requestAnimationFrame(timestamp => { 13582 this.animateLeft(timestamp, trans, gap, duration) 13583 }) 13584 }; 13585 13586 /** 13587 * Move Slide. 13588 */ 13589 moveSlide (index, cIndex) { 13590 this.moveAnimateAbort(); 13591 const gap = this.options.spacing * index; 13592 const trans = index * -100; 13593 13594 this.animation = window.requestAnimationFrame((timestamp) => { 13595 index === this.maxIndex && this.setInfinite(); 13596 index === -1 && this.setPrevInfinite(); 13597 this.animationStart = timestamp; 13598 this.animationIndex = this.currentIndex; 13599 this.animateLeft(timestamp, trans, gap, this.options.transitionSpeed); 13600 }); 13601 13602 this.currentIndex = cIndex; 13603 13604 this.setUpAutoplay(); 13605 this.setButtonsVisibility(); 13606 this.hook('moved'); 13607 }; 13608 13609 /** 13610 * Set Infinity. 13611 */ 13612 setInfinite () { 13613 this.isInfinite = true; 13614 const count = this.options.slidesPerView * this.maxIndex; 13615 13616 for (let idx = 0; idx < this.options.slidesPerView; idx++) { 13617 const slide = this.slides[idx]; 13618 slide.style.left = `calc((100% * ${count}) + (${this.options.spacing}px * ${count}))`;
13619 } 13620 }; 13621 13622 /** 13623 * Clear Infinity. 13624 */ 13625 clearInfinite () { 13626 this.isInfinite = false; 13627 this.track.style.left = `calc(${this.currentIndex * -100}% - ${this.options.spacing * this.currentIndex}px)`; 13628 13629 this.slides.forEach((slide, idx) => { 13630 if (idx >= this.options.slidesPerView) return; 13631 slide.style.removeProperty('left'); 13632 }) 13633 }; 13634 13635 /** 13636 * Next Slide. 13637 */ 13638 next () { 13639 const nextIndex = this.currentIndex === this.maxIndex -1 ? 0 : this.currentIndex + 1; 13640 if (!this.options.loop && nextIndex < this.currentIndex) return; 13641 13642 if (nextIndex < this.currentIndex) { 13643 this.moveSlide(this.currentIndex + 1, nextIndex); 13644 return; 13645 } 13646 13647 this.moveSlide(nextIndex, nextIndex); 13648 }; 13649 13650 /** 13651 * Set Prev Infinity. 13652 */ 13653 setPrevInfinite () { 13654 this.isPrevInfinite = true; 13655 const count = this.options.slidesPerView * this.maxIndex; 13656 const maxIdx = count - this.options.slidesPerView; 13657 13658 for (let idx = this.slides.length - 1; idx >= 0; idx--) { 13659 if (idx < maxIdx) return; 13660 const slide = this.slides[idx]; 13661 slide.style.left = `calc((-100% * ${count}) - (${this.options.spacing}px * ${count}))`; 13662 } 13663 }; 13664 13665 /** 13666 * Clear Prev Infinity. 13667 */ 13668 clearPrevInfinite () { 13669 this.isPrevInfinite = false; 13670 this.track.style.left = `calc(${this.currentIndex * -100}% - ${this.options.spacing * this.currentIndex}px)`; 13671 this.slides.forEach((slide, idx) => { 13672 slide.style.removeProperty('left'); 13673 }); 13674 }; 13675 13676 /** 13677 * Prev Slide. 13678 */ 13679 prev () { 13680 const nextIndex = this.currentIndex === 0 ? this.maxIndex - 1 : this.currentIndex - 1; 13681 if (!this.options.loop && nextIndex > this.currentIndex) return; 13682 13683 if (nextIndex > this.currentIndex) { 13684 this.moveSlide(this.currentIndex - 1, nextIndex); 13685 return; 13686 } 13687 13688 this.moveSlide(nextIndex, nextIndex); 13689 }; 13690 13691 /** 13692 * Move to Slide. 13693 */ 13694 moveToSlide (index) { 13695 if (index === this.currentIndex) return; 13696 this.moveSlide(index, index); 13697 }; 13698 13699 /** 13700 * Get Slides 13701 */ 13702 getSlides () { 13703 return this.slides; 13704 }; 13705 13706 /** 13707 * Get Current Index. 13708 */ 13709 getCurrentIndex () { 13710 return this.currentIndex; 13711 }; 13712 13713 /** 13714 * Get Options. 13715 */ 13716 getOptions () { 13717 return this.options; 13718 }; 13719 13720 /** 13721 * Get Page Size. 13722 */ 13723 getPageSize () { 13724 return this.maxIndex; 13725 }; 13726 } 13727 13728 window.RktCarousel = RktCarousel; 13729</script>
vendor: 1 bytes, line 13729
13729
13730<script> 13731 function openLink(link, target) { 13732 if (typeof window.open === "function") { 13733 window.open(link, target); 13734 } else { 13735 let a = document.createElement("a"); 13736 a.href = link; 13737 a.target = target; 13738 a.click(); 13739 } 13740 } 13741</script>
vendor: 1 bytes, line 13741
13741
13742<script> 13743 window.addEventListener("lock-screen", () => { 13744 document.querySelector("html").classList.add('screen-locked') 13745 }); 13746 window.addEventListener("unlock-screen", () => { 13747 document.querySelector("html").classList.remove('screen-locked') 13748 }); 13749</script>
vendor: 1 bytes, line 13749
13749
13750<script> 13751 function initCartDrawer() { 13752 return { 13753 open: false, 13754 isLoading: false, 13755 isLoadingButtonCheckout: false, 13756 cartId: null, 13757 cartEmpty: true, 13758 cart: {}, 13759 maxItemsToDisplay: 10, 13760 itemsCount: 0, 13761 totalCartAmount: 0, 13762 discountSummaryIsOpen: false, 13763 showTaxInStorefront: false, 13764 isGuestCheckoutAllowed: false, 13765 customer: {}, 13766 setLoader(){ 13767 if (this.isGuestCheckoutAllowed) this.isLoadingButtonCheckout = true 13768 if (!this.isGuestCheckoutAllowed && this.customer.firstname) this.isLoadingButtonCheckout = true 13769 }, 13770 getCartQuery(cartId) { 13771 return "{cart (cart_id: \"%cartId\") {\n total_quantity\n items {\n id\n errors {\n code\n message\n }\n prices {\n price {\n value\n }\n row_total {\n value\n currency\n }\n row_total_incl_tax {\n value\n currency\n }\n price_incl_tax {\n value\n }\n }\n product_type\n simple_image\n product {\n id\n name\n sku\n ... on ConfigurableProduct {\n name\n configurable_options {\n values {\n swatch_data {\n __typename\n value\n }\n }\n }\n options {\n uid\n title\n ... on CustomizableOptionInterface {\n title\n }\n ... on CustomizableDropDownOption {\n value {\n option_type_id\n title\n sku\n }\n }\n ... on CustomizableMultipleOption {\n value {\n option_type_id\n title\n sku\n }\n }\n ... on CustomizableRadioOption {\n value {\n option_type_id\n title\n sku\n }\n }\n ... on CustomizableCheckboxOption {\n value {\n option_type_id\n title\n sku\n }\n }\n }\n }\n ... on SimpleProduct {\n name\n options {\n title\n }\n }\n ... on VirtualProduct {\n name\n options {\n title\n }\n }\n ... on DownloadableProduct {\n name\n options {\n title\n }\n }\n ... on BundleProduct {\n name\n options {\n title\n }\n }\n small_image {\n label\n url\n }\n url_key\n url_suffix\n price_tiers {\n quantity\n final_price {\n value\n }\n discount {\n amount_off\n percent_off\n }\n }\n }\n quantity\n ... on ConfigurableCartItem {\n configurable_options {\n option_label\n swatch_type\n swatch_value\n }\n options: customizable_options {\n type\n label\n values {\n label\n value\n }\n }\n }\n ... on SimpleCartItem {\n customizable_options {\n label\n values {\n label\n value\n price {\n value\n type\n }\n }\n }\n }\n ... on VirtualCartItem {\n customizable_options {\n type\n label\n values {\n label\n value\n price {\n value\n type\n }\n }\n }\n }\n ... on DownloadableCartItem {\n customizable_options {\n type\n label\n values {\n label\n value\n price {\n value\n type\n }\n }\n }\n }\n ... on BundleCartItem {\n bundle_options {\n id\n label\n values {\n quantity\n label\n }\n }\n customizable_options: bundle_options {\n uid\n type\n label\n values{\n id\n label\n }\n }\n }\n }\n available_payment_methods {\n code\n title\n }\n selected_payment_method {\n code\n title\n }\n applied_coupons {\n code\n }\n billing_address {\n country {\n code\n }\n region {\n label\n region_id\n }\n postcode\n }\n shipping_addresses {\n country {\n code\n }\n region {\n label\n region_id\n }\n postcode\n selected_shipping_method {\n amount {\n value\n currency\n }\n price_incl_tax {\n value\n currency\n }\n carrier_title\n carrier_code\n method_title\n method_code\n }\n available_shipping_methods {\n price_excl_tax {\n value\n currency\n }\n price_incl_tax {\n value\n currency\n }\n carrier_title\n carrier_code\n method_title\n method_code\n }\n }\n prices {\n grand_total {\n value\n currency\n }
13771\n subtotal_excluding_tax {\n value\n currency\n }\n subtotal_including_tax {\n value\n currency\n }\n applied_taxes {\n amount {\n value\n currency\n }\n label\n }\n discounts {\n amount {\n value\n currency\n }\n label\n }\n }\n }}".replace('%cartId', cartId) 13772 }, 13773 getData(data) { 13774 if (data.cart) { 13775 this.isGuestCheckoutAllowed = data.cart.isGuestCheckoutAllowed 13776 this.cart = data.cart; 13777 this.getCartByCustomerSectionData(data); 13778 this.itemsCount = data.cart.items && data.cart.items.length || 0; 13779 this.totalCartAmount = this.cart.summary_count; 13780 this.setCartItems(); 13781 } 13782 if (data.customer) this.customer = data.customer 13783 this.isLoading = false; 13784 }, 13785 getSwatchStyle(option, value) { 13786 switch (option) { 13787 case "1": 13788 return `background-color: ${value};` 13789 case "2": 13790 return `background-image: url("https://www.serrats.com/media/attribute/swatch${value}"); 13791 background-size: cover;` 13792 default: 13793 return "" 13794 } 13795 }, 13796 cartItems: [], 13797 getItemCountTitle() { 13798 return hyva.strf('(%0 de %1)', this.maxItemsToDisplay, this.itemsCount) 13799 }, 13800 setCartItems() { 13801 this.cartItems = this.cart.items && this.cart.items.sort((a, b) => b.item_id - a.item_id) || []; 13802 13803 if (this.maxItemsToDisplay > 0) { 13804 this.cartItems = this.cartItems.slice(0, parseInt(this.maxItemsToDisplay, 10)); 13805 } 13806 }, 13807 deleteItemFromCart(itemId) { 13808 this.isLoading = true; 13809 13810 const formKey = hyva.getFormKey(); 13811 const postUrl = BASE_URL + 'checkout/sidebar/removeItem/'; 13812 13813 fetch(postUrl, { 13814 "headers": { 13815 "content-type": "application/x-www-form-urlencoded; charset=UTF-8", 13816 }, 13817 "body": "form_key=" + formKey + "&item_id=" + itemId, 13818 "method": "POST", 13819 "mode": "cors", 13820 "credentials": "include" 13821 }).then(response => { 13822 if (response.redirected) { 13823 window.location.href = response.url; 13824 } else if (response.ok) { 13825 return response.json(); 13826 } else { 13827 window.dispatchMessages && window.dispatchMessages([{ 13828 type: 'warning', 13829 text: 'No\u0020se\u0020ha\u0020podido\u0020eliminar\u0020el\u0020elemento\u0020del\u0020carrito' 13830 }]); 13831 this.isLoading = false; 13832 } 13833 }).then(result => { 13834 window.dispatchMessages && window.dispatchMessages([{ 13835 type: result.success ? 'success' : 'error', 13836 text: result.success 13837 ? 'Elimin\u00F3\u0020el\u0020elemento.' 13838 : result.error_message 13839 }], result.success ? 5000 : 0) 13840 window.dispatchEvent(new CustomEvent('reload-customer-section-data')); 13841 }); 13842 }, 13843 getCartByCustomerSectionData(data) { 13844 if (data && data.cart && data.cart.cartId) { 13845 this.cartId = data.cart.cartId; 13846 } else { 13847 this.cartEmpty = true; 13848 this.isLoading = false;
13849 } 13850 }, 13851 getCart() { 13852 this.isLoading = true; 13853 fetch('https://www.serrats.com/es_es/graphql', { 13854 method: 'POST', 13855 headers: { 13856 'Content-Type': 'application/json', 13857 'Store': 'es_es' 13858 }, 13859 credentials: 'include', 13860 body: JSON.stringify({ 13861 query: ( 13862 this.customerToken && 13863 this.getCustomerCartQuery()) || 13864 this.getCartQuery(this.cartId) 13865 }) 13866 } 13867 ).then((response) => { 13868 return response.json() 13869 } 13870 ).then((data) => { 13871 if (data && data.errors) { 13872 this.initErrorMessages(data.errors); 13873 } else { 13874 this.cartData = (data && data.data && (data.data.customerCart || data.data.cart)) || []; 13875 } 13876 }).catch(error => { 13877 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages( 13878 [{ 13879 type: "error", 13880 text: "Algo\u0020sali\u00F3\u0020mal.\u0020Por\u0020favor,\u0020int\u00E9ntelo\u0020de\u0020nuevo." 13881 }], 10000 13882 ); 13883 }).finally(() => { 13884 this.isLoading = false; 13885 }); 13886 }, 13887 mutateItemQty(itemId, qty) { 13888 this.isLoading = true; 13889 13890 const cartItemUpdateQuery = `mutation updateCartItemQtyMutation($cartId: String!, $itemId: Int, $qty: Float) {updateCartItems( 13891 input: { 13892 cart_id: $cartId, 13893 cart_items: [ 13894 { 13895 cart_item_id: $itemId 13896 quantity: $qty 13897 } 13898 ] 13899 } 13900 ) { 13901 cart { 13902 13903 total_quantity 13904 items { 13905 id 13906 errors { 13907 code 13908 message 13909 } 13910 prices { 13911 price { 13912 value 13913 } 13914 row_total { 13915 value 13916 currency 13917 } 13918 row_total_incl_tax { 13919 value 13920 currency 13921 } 13922 price_incl_tax { 13923 value 13924 } 13925 } 13926 product_type 13927 simple_image 13928 product { 13929 id 13930 name 13931 sku 13932 ... on ConfigurableProduct { 13933 name 13934 configurable_options { 13935 values { 13936 swatch_data { 13937 __typename 13938 value 13939 } 13940 } 13941 } 13942 options { 13943 uid 13944 title 13945 ... on CustomizableOptionInterface { 13946 title 13947 } 13948 ... on CustomizableDropDownOption { 13949 value { 13950 option_type_id 13951 title 13952 sku 13953 } 13954 } 13955 ... on CustomizableMultipleOption { 13956 value { 13957 option_type_id 13958 title 13959 sku 13960 } 13961 } 13962 ... on CustomizableRadioOption { 13963 value { 13964 option_type_id 13965 title 13966 sku 13967 } 13968 } 13969 ... on CustomizableCheckboxOption { 13970 value { 13971 option_type_id 13972 title 13973 sku 13974 } 13975 } 13976 } 13977 } 13978 ... on SimpleProduct { 13979 name 13980 options { 13981 title 13982 } 13983 } 13984 ... on VirtualProduct { 13985 name 13986 options { 13987 title 13988 } 13989 } 13990 ... on DownloadableProduct { 13991 name 13992 options { 13993 title 13994 } 13995 } 13996 ... on BundleProduct { 13997 name 13998 options { 13999 title 14000 } 14001 } 14002 small_image { 14003 label 14004 url 14005 } 14006 url_key 14007 url_suffix 14008 price_tiers { 14009 quantity 14010 final_price { 14011 value 14012 } 14013 discount { 14014 amount_off 14015 percent_off 14016 } 14017 } 14018 } 14019 quantity 14020 ... on ConfigurableCartItem { 14021 configurable_options { 14022 option_label 14023 swatch_type 14024 swatch_value 14025 } 14026 options: customizable_options { 14027 type 14028 label 14029 values { 14030 label 14031 value 14032 } 14033 } 14034 } 14035 ... on SimpleCartItem { 14036 customizable_options { 14037 label 14038 values { 14039 label 14040 value 14041 price { 14042 value 14043 type 14044 } 14045 } 14046 } 14047 } 14048 ... on VirtualCartItem { 14049 customizable_options { 14050 type 14051 label 14052 values { 14053 label 14054 value 14055 price { 14056 value 14057 type 14058 } 14059 } 14060 } 14061 } 14062 ... on DownloadableCartItem { 14063 customizable_options { 14064 type 14065 label 14066 values { 14067 label 14068 value 14069 price { 14070 value 14071 type 14072 } 14073 } 14074 } 14075 } 14076 ... on BundleCartItem { 14077 bundle_options { 14078 id 14079 label 14080 values { 14081 quantity 14082 label 14083 } 14084 } 14085 customizable_options: bundle_options { 14086 uid 14087 type 14088 label 14089 values{ 14090 id 14091 label 14092 } 14093 } 14094 } 14095 } 14096 available_payment_methods { 14097 code 14098 title 14099 } 14100 selected_payment_method { 14101 code 14102 title 14103 } 14104 applied_coupons { 14105 code 14106 } 14107 billing_address { 14108 country { 14109 code 14110 } 14111 region { 14112 label 14113 region_id 14114 } 14115 postcode 14116 } 14117 shipping_addresses { 14118 country { 14119 code 14120 } 14121 region { 14122 label 14123 region_id 14124 } 14125 postcode 14126 selected_shipping_method { 14127 amount { 14128 value 14129 currency 14130 } 14131 price_incl_tax { 14132 value 14133 currency 14134 } 14135 carrier_title 14136 carrier_code 14137 method_title 14138 method_code 14139 } 14140 available_shipping_methods { 14141 price_excl_tax { 14142 value 14143 currency 14144 } 14145 price_incl_tax { 14146 value 14147 currency 14148 } 14149 carrier_title 14150 carrier_code 14151 method_title 14152 method_code 14153 } 14154 } 14155 prices { 14156 grand_total { 14157 value 14158 currency 14159 } 14160 subtotal_excluding_tax { 14161 value 14162 currency 14163 } 14164 subtotal_including_tax { 14165 value 14166 currency 14167 } 14168 applied_taxes { 14169 amount { 14170 value 14171 currency 14172 } 14173 label 14174 } 14175 discounts { 14176 amount { 14177 value 14178 currency 14179 } 14180 label 14181 } 14182 } 14183 14184 } 14185 }}`; 14186 const variables = { 14187 cartId: this.cartId, 14188 itemId: itemId, 14189 qty: qty 14190 }; 14191 14192 fetch('https://www.serrats.com/es_es/graphql', { 14193 method: 'POST', 14194 headers: { 14195 'Content-Type': 'application/json;charset=utf-8', 14196 'Store': 'es_es' 14197 }, 14198 body: JSON.stringify({query: cartItemUpdateQuery, variables: variables}) 14199 } 14200 ).then((response) => { 14201 return response.json() 14202 } 14203 ).then((data) => { 14204 this.clearErrorMessages(); 14205 14206 if (data.errors) { 14207 this.initErrorMessages(data.errors); 14208 this.getCart(); 14209 } else { 14210 this.cartData = ( 14211 data && 14212 data.data && 14213 (data.data.updateCartItems && (data.data.updateCartItems.cart)) 14214 ) || []; 14215 this.setCartItems(); 14216 } 14217 this.reloadCustomerData(); 14218 }).catch(error => { 14219 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages( 14220 [{ 14221 type: "error", 14222 text: "Algo\u0020sali\u00F3\u0020mal.\u0020Por\u0020favor,\u0020int\u00E9ntelo\u0020de\u0020nuevo." 14223 }], 10000 14224 ); 14225 }).finally(() => { 14226 this.isLoading = false;
14227 }); 14228 }, 14229 reloadCustomerData() { 14230 var reloadCustomerDataEvent = new CustomEvent("reload-customer-section-data"); 14231 window.dispatchEvent(reloadCustomerDataEvent); 14232 }, 14233 clearErrorMessages() { 14234 window.dispatchEvent(new CustomEvent('clear-messages')); 14235 }, 14236 initErrorMessages(errors) { 14237 var genericMessage = 'We\u0020couldn\u005C\u0027t\u0020update\u0020your\u0020cart.\u0020Please\u0020try\u0020again.'; 14238 var technicalErrorPattern = /Variable "\$|got invalid value|cannot represent|Argument .* of type/i; 14239 var messages = []; 14240 for (var error in Object.keys(errors)) { 14241 var rawMessage = (errors[error] && errors[error].message) || ''; 14242 var safeMessage = technicalErrorPattern.test(rawMessage) ? genericMessage : rawMessage; 14243 messages.push({type: 'error', text: safeMessage}); 14244 } 14245 dispatchMessages(messages) 14246 }, 14247 toggleCartDrawer(value) { 14248 value ? 14249 window.dispatchEvent(new CustomEvent('lock-screen')) : 14250 window.dispatchEvent(new CustomEvent('unlock-screen')) 14251 this.open = value 14252 }, 14253 } 14254 } 14255</script>
14255 14256 14257<section id="cart-drawer" 14258 x-data="initCartDrawer()" 14259 @private-content-loaded.window="getData($event.detail.data); cart && cart.summary_count ? toggleCartDrawer(open) : toggleCartDrawer(false);" 14260 @toggle-cart.window="toggleCartDrawer(true)" 14261 @keydown.window.escape="toggleCartDrawer(false)" 14262 x-cloak 14263> 14264 <div role="dialog" 14265 aria-labelledby="cart-drawer-title" 14266 aria-modal="true" 14267 class="fixed inset-y-0 right-0 z-30 flex max-w-[420px]"> 14268 <div class="backdrop backdrop-close" 14269 x-show="open" 14270 x-transition:enter="ease-in-out duration-500" 14271 x-transition:enter-start="opacity-0" 14272 x-transition:enter-end="opacity-100" 14273 x-transition:leave="ease-in-out duration-500" 14274 x-transition:leave-start="opacity-100" 14275 x-transition:leave-end="opacity-0" 14276 @click="toggleCartDrawer(false)" 14277 aria-label="Close panel"></div> 14278 <div class="relative w-screen max-w-[420px] shadow-2xl" 14279 x-show="open" 14280 x-transition:enter="transform transition ease-in-out duration-500 sm:duration-700" 14281 x-transition:enter-start="translate-x-full" 14282 x-transition:enter-end="translate-x-0" 14283 x-transition:leave="transform transition ease-in-out duration-500 sm:duration-700" 14284 x-transition:leave-start="translate-x-0" 14285 x-transition:leave-end="translate-x-full" 14286 > 14287 <div class="flex flex-col justify-between h-full bg-white shadow-xl overflow-y-auto" rcm-data="minicart-container"> 14288 14289 <header class="px-2.5 py-2.5 flex flex-row justify-between items-center border-b border-gray"> 14290 <div x-show="open" 14291 x-transition:enter="ease-in-out duration-500" 14292 x-transition:enter-start="opacity-0" 14293 x-transition:enter-end="opacity-100" 14294 x-transition:leave="ease-in-out duration-500" 14295 x-transition:leave-start="opacity-100" 14296 x-transition:leave-end="opacity-0" class="flex"> 14297 <button @click="toggleCartDrawer(false);" aria-label="Close panel" 14298 class="text-black transition duration-150 ease-in-out hover:text-black"> 14299 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-6 h-6 p-0.5" width="24" height="24" role="img"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/><title>x</title></svg> 14300 </button> 14301 </div> 14302 <p id="cart-drawer-title" class="text-xl md:text-4xl font-bold">Carrito</p> 14303 <span class="items-total text-xs absolute right-12" 14304 x-show="maxItemsToDisplay && maxItemsToDisplay < itemsCount"> 14305 <span class="block" x-text="getItemCountTitle()"></span> 14306 <span class="cursor-pointer underline text-brand-primary text-sm mt-4" @click="openLink(atob('aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvY2hlY2tvdXQvY2FydC8='), '_self')" x-data="" x-defer="intersect" mcclane-data="minicart-to-cart-button"> 14307 Ver más </span> 14308 </span> 14309 <div class="relative px-1"> 14310 <span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-5 h-5" width="24" height="24" role="img"><path d="M236,69.4A16.13,16.13,0,0,0,223.92,64H176a48,48,0,0,0-96,0H32.08a16.13,16.13,0,0,0-12,5.4,16,16,0,0,0-3.92,12.48l14.26,120a16,16,0,0,0,16,14.12H209.67a16,16,0,0,0,16-14.12l14.26-120A16,16,0,0,0,236,69.4ZM128,32a32,32,0,0,1,32,32H96A32,32,0,0,1,128,32Zm81.76,168a.13.13,0,0,1-.09,0H46.25L32.08,80H224Z"/><title>tote-simple</title></svg> 14311</span> 14312 <div x-text="totalCartAmount" class="absolute bg-primary text-white top-0 text-2xs right-0 text-center px-1 min-w-[14px] leading-[14px] rounded-full" :class="totalCartAmount > 0 ? 'bg-primary text-white' : 'bg-gray-medium text-white'"></div> 14313 </div> 14314 </header> 14315 14316
14316<script> 14317 function initFreeShippingInfoCartComponent() { 14318 return { 14319 shipping_cart_info: {}, 14320 onPrivateContentLoaded: function (data) { 14321 if (event.detail.data.cart && event.detail.data.cart.free_shipping_cart_notification) { 14322 this.shipping_cart_info = event.detail.data.cart.free_shipping_cart_notification; 14323 } 14324 }, 14325 getProgressBarWidth: function() { 14326 return 'width: ' + this.shipping_cart_info.reachedPercentage + '%;' 14327 }, 14328 getReachedPercentageText: function() { 14329 return this.shipping_cart_info.reachedPercentage + '%' 14330 } 14331 } 14332 } 14333</script>
14333 14334<div x-data="initFreeShippingInfoCartComponent()" 14335 @private-content-loaded.window="onPrivateContentLoaded(event.detail.data);" 14336 class="free-shipping-info-cart-notification mb-2.5"> 14337 <div class="bg-gray-light font-light text-black px-4 text-center" :class="{'bg-gray-light text-black': shipping_cart_info.reachedPercentage < 100, 'bg-success text-white': shipping_cart_info.reachedPercentage == 100}"> 14338 <span x-text="shipping_cart_info.message" mcclane-data="free-shipping-cart-info" class="text-sm font-bold"></span> 14339 </div> 14340</div> 14341 14342 <template x-if="cartItems.length" hidden> 14343 <div class="relative flex flex-col px-2.5 divide-y divide-gray space-y-3 grow overflow-y-auto" mcclane-data="minicart-list-items"> 14344 <template x-for="item in cartItems" hidden> 14345 <div class="relative flex justify-between pt-2.5" mcclane-data="minicart-list-item"> 14346 <div class="w-24 shrink-0 mr-2"> 14347 <a :href="item.is_visible_in_site_visibility ? item.product_url : 'javascript:void(0)'"> 14348 <img 14349 class="" 14350 :src="item.product_image.src" 14351 :width="item.product_image.width" 14352 :height="item.product_image.height" 14353 loading="lazy" 14354 /> 14355 </a> 14356 </div> 14357 <div class="flex-1"> 14358 <span x-html="item.product_name" class="flex text-md font-primary font-bold mb-1 pr-6"></span> 14359 <template x-if="item.product_type !== 'bundle'" hidden> 14360 <div class="product-item-options " 14361 x-show="item.options.length > 0"> 14362 <template x-for="option in item.options" hidden> 14363 <div class="product-item-option "> 14364 <template x-if="option.swatchType == 0 || option.swatchType == undefined"> 14365 <p class="product-item-option-swatch-text " x-text="option.print_value || option.value"></p> 14366 </template> 14367 <template x-if="option.swatchType == 1"> 14368 <div class="product-item-option-swatch "> 14369 <span class="product-item-option-swatch-color" 14370 :class="{ 14371 'product-item-option-swatch-color-white ': !option.swatchValue || option.swatchValue == '#ffffff', 14372 '': option.swatchValue && option.swatchValue != '#ffffff', 14373 }" 14374 :style="getSwatchStyle(option.swatchType, option.swatchValue)"></span> 14375 <span class="product-item-option-swatch-label" x-text="option.value"></span> 14376 </div> 14377 </template> 14378 <template x-if="option.swatchType == 2"> 14379 <div class="product-item-option-swatch "> 14380 <span class="product-item-option-swatch-image" 14381 :style="getSwatchStyle(option.swatchType, option.swatchValue)"></span> 14382 <span class="product-item-option-swatch-label" x-text="option.value"></span> 14383 </div> 14384 </template> 14385 </div> 14386 </template> 14387</div> 14388 </template> 14389 <template x-if="item.product_type === 'bundle'" hidden> 14390 <div class="product-item-bundle" 14391 x-data="{showTooltip: false}" 14392 @mouseover.prevent.stop="showTooltip = true" 14393 @mouseleave.prevent.stop="showTooltip = false" 14394 x-cloak 14395 > 14396 <div class="product-item-options "> 14397 <template x-for="option in item.options" hidden> 14398 <template x-if="option['print_value'] != undefined" hidden> 14399 <div class="product-item-option "> 14400 <p class="product-item-option-swatch-text" x-html="option.print_value || option.value"></p> 14401 </div> 14402 </template> 14403 </template> 14404 </div> 14405 <div class="product-item-bundle-row"> 14406 <div class="product-item-bundle-options-tooltip"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="product-item-bundle-options-tooltip-icon" width="24" height="24" role="img"><path d="M140,180a12,12,0,1,1-12-12A12,12,0,0,1,140,180ZM128,72c-22.06,0-40,16.15-40,36v4a8,8,0,0,0,16,0v-4c0-11,10.77-20,24-20s24,9,24,20-10.77,20-24,20a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-.72c18.24-3.35,32-17.9,32-35.28C168,88.15,150.06,72,128,72Zm104,56A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128Z"/><title>question</title></svg> 14407</div> 14408 <div class="product-item-bundle-options" x-show="showTooltip"> 14409 <template x-for="option in item.options" hidden> 14410 <div class="product-item-bundle-option" x-show="!option['print_value']">
14411 <span class="product-item-bundle-option-name" x-text="option.label + ':'"></span> 14412 <span class="product-item-bundle-option-value" x-html="option.value"></span> 14413 </div> 14414 </template> 14415 </div> 14416 </div> 14417 </div> 14418 </template> 14419 <div class="flex justify-between items-end"> 14420 <div class="field qty input-qty "> 14421 <button class="input-qty-button " 14422 mcclane-data="minicart-item-decrease-qty" 14423 :disabled="item.min !== null && item.qty <= item.min" 14424 @click="$el.nextElementSibling.stepDown(); $el.nextElementSibling.dispatchEvent(new Event('input'))"> 14425 <span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="input-qty-button-icon " width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128Z"/><title>minus</title></svg> 14426</span> 14427 </button> 14428 <input type="number" 14429 :min="item.min" 14430 :max="item.max" 14431 :step="item.step" 14432 x-model="item.qty" 14433 :value="item.qty" 14434 @input.debounce="item.qty = parseFloat($el.value) || 0; mutateItemQty(item.item_id, item.qty)" 14435 class="input-qty-input " 14436 /> 14437 <button class="input-qty-button " 14438 mcclane-data="minicart-item-increase-qty" 14439 :disabled="item.max !== null && item.qty >= item.max" 14440 @click="$el.previousElementSibling.stepUp(); $el.previousElementSibling.dispatchEvent(new Event('input'))"> 14441 <span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="input-qty-button-icon " width="24" height="24" role="img"><path d="M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z"/><title>plus</title></svg> 14442</span> 14443 </button> 14444 </div> 14445 <div class="inline-flex flex-col items-end"> 14446 <span x-show="item.product_regular_price_value" 14447 x-html="item.product_regular_price" 14448 class="text-product-price-old text-xs line-through"> 14449 </span> 14450 <span x-html="item.product_price" 14451 :class="{'text-product-price-discount': item.product_regular_price_value, 'text-product-price': !item.product_regular_price_value}" 14452 class="text-md font-bold"> 14453 </span> 14454 </div> 14455 </div> 14456 <div x-show="item.message" class="cart item message text-md bg-red-500 py-1 px-2 rounded my-2 text-white"> 14457 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-4 h-4 mr-0.5 inline align-middle" width="25" height="25" role="img"><path d="M225.9,102.8c-3.8-3.9-7.7-8-9.2-11.5s-1.4-8.7-1.5-14c-.1-9.7-.3-20.8-8-28.5s-18.8-7.9-28.5-8c-5.3-.1-10.7-.2-14-1.5s-7.6-5.4-11.5-9.2C146.3,23.5,
14457138.4,16,128,16s-18.3,7.5-25.2,14.1c-3.9,3.8-8,7.7-11.5,9.2s-8.7,1.4-14,1.5c-9.7.1-20.8.3-28.5,8s-7.9,18.8-8,28.5c-.1,5.3-.2,10.7-1.5,14s-5.4,7.6-9.2,11.5C23.5,109.7,16,117.6,16,128s7.5,18.3,14.1,25.2c3.8,3.9,7.7,8,9.2,11.5s1.4,8.7,1.5,14c.1,9.7.3,20.8,8,28.5s18.8,7.9,28.5,8c5.3.1,10.7.2,14,1.5s7.6,5.4,11.5,9.2c6.9,6.6,14.8,14.1,25.2,14.1s18.3-7.5,25.2-14.1c3.9-3.8,8-7.7,11.5-9.2s8.7-1.4,14-1.5c9.7-.1,20.8-.3,28.5-8s7.9-18.8,8-28.5c.1-5.3.2-10.7,1.5-14s5.4-7.6,9.2-11.5c6.6-6.9,14.1-14.8,14.1-25.2S232.5,109.7,225.9,102.8Zm-11.6,39.3c-4.8,5-9.7,10.2-12.4,16.5s-2.6,13.1-2.7,19.8-.2,14.4-3.3,17.5-10.4,3.2-17.5,3.3-13.7.2-19.8,2.7-11.5,7.6-16.5,12.4S132,224,128,224s-9.1-4.9-14.1-9.7-10.2-9.7-16.5-12.4-13.1-2.6-19.8-2.7-14.4-.2-17.5-3.3-3.2-10.4-3.3-17.5-.2-13.7-2.7-19.8-7.6-11.5-12.4-16.5S32,132,32,128s4.9-9.1,9.7-14.1,9.7-10.2,12.4-16.5,2.6-13.1,2.7-19.8.2-14.4,3.3-17.5,10.4-3.2,17.5-3.3,13.7-.2,19.8-2.7,11.5-7.6,16.5-12.4S124,32,128,32s9.1,4.9,14.1,9.7,10.2,9.7,16.5,12.4,13.1,2.6,19.8,2.7,14.4.2,17.5,3.3,3.2,10.4,3.3,17.5.2,13.7,2.7,19.8,7.6,11.5,12.4,16.5S224,124,224,128,219.1,137.1,214.3,142.1ZM120,136V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z"/><title>circle-wavy-warning</title></svg> 14458 <span x-html="item.message"></span> 14459 </div> 14460 <button class="cart-item__delete-button absolute top-3.5 right-0" 14461 @click="deleteItemFromCart(item.item_id)" 14462 mcclane-data="minicart-item-delete" 14463 ><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-5 h-5 text-gray-medium" width="24" height="24" role="img"><path d="M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM96,40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96Zm96,168H64V64H192ZM112,104v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Z"/><title>trash</title></svg> 14464</button> 14465 </div> 14466 </div> 14467 </template> 14468 </div> 14469 </template> 14470 <template x-if="!cartItems.length" hidden> 14471 <div class="relative flex flex-col px-4 grow"> 14472 <div class="flex flex-col items-center justify-center text-center h-full"> 14473 <div class="flex flex-col items-center justify-center gap-8"> 14474 <div class="w-full flex items-center justify-center"> 14475 <div class="bg-gray-light rounded-full p-4"> 14476 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-8 h-8 text-gray-medium" width="24" height="24" role="img"><path d="M236,69.4A16.13,16.13,0,0,0,223.92,64H176a48,48,0,0,0-96,0H32.08a16.13,16.13,0,0,0-12,5.4,16,16,0,0,0-3.92,12.48l14.26,120a16,16,0,0,0,16,14.12H209.67a16,16,0,0,0,16-14.12l14.26-120A16,16,0,0,0,236,69.4ZM128,32a32,32,0,0,1,32,32H96A32,32,0,0,1,128,32Zm81.76,168a.13.13,0,0,1-.09,0H46.25L32.08,80H224Z"/><title>tote-simple</title></svg> 14477 </div> 14478 </div> 14479 <div class="flex flex-col gap-3"> 14480 <p class="primary text-lg font-bold"> 14481 Aún no tienes artÃculos en tu cesta. </p> 14482 14483 <p class="primary text-sm font-light"> 14484 ¡Es hora de empezar a comprar! Llénalo con nuestros artÃculos más populares. </p> 14485 </div> 14486 <a class="btn btn-primary btn-md lg:btn-lg " 14487 href="https://www.serrats.com/es_es/tienda-conservas" x-data="" x-defer="intersect" target="" 14488 > 14489 <span>Empieza a comprar</span> </a> 14490 <div class="flex flex-col gap-4"> 14491 <div class="flex items-center gap-3"><div 14492 class="flex flex-col items-center justify-center text-center h-full cursor-pointer" 14493 @private-content-loaded.window="handleAuthState($event.detail.data)"
14494 x-data="{ 14495 show: false, 14496 showWhenLoggedIn: false, 14497 handleAuthState(data) { 14498 const isLoggedIn = !!data?.customer?.firstname 14499 this.show = this.showWhenLoggedIn ? isLoggedIn : !isLoggedIn 14500 } 14501 }" 14502 x-show="show" 14503> 14504 <a 14505 class="flex items-center gap-0.5 underline text-sm" 14506 @click.prevent="$dispatch('toggle-authentication-popup', { url: 'https://www.serrats.com/es_es/customer/account/login/' });" 14507 > 14508 Inicia sesión </a> 14509</div> 14510</div> </div> 14511 </div> 14512</div> 14513 </div> 14514 </template> 14515 14516 <div class="w-full flex flex-col items-center bg-white border-t border-gray"> 14517 <template x-if="cart && cart.summary_count" hidden> 14518 <div class="w-full"> 14519 <div class="w-full pb-4 px-2.5 pt-1"> 14520 <div class="flex flex-row flex-no-wrap items-baseline justify-between text-sm pt-2"> 14521 <div class="w-7/12 text-left md:w-auto" 14522 >Total parcial</div> 14523 <div class="w-5/12 text-right md:w-auto" 14524 x-html="cart.subtotal" 14525 mcclane-data="cart-subtotal" 14526 rcm-data="minicart-subtotal" 14527 ></div> 14528 </div> 14529 <template x-if="cart.totalsData !== undefined && cart.totalsData.shipping !== undefined"> 14530 <template x-for="shippingData in cart.totalsData.shipping"> 14531 <div class="flex flex-row flex-no-wrap items-baseline justify-between text-sm pt-2"> 14532 <div class="w-7/12 text-left md:w-auto" 14533 x-text="shippingData.title"></div> 14534 <div class="w-5/12 text-right md:w-auto" 14535 x-html="shippingData.value" 14536 ></div> 14537 </div> 14538 </template> 14539 </template> 14540 <template x-if="showTaxInStorefront && cart.totalsData !== undefined && cart.totalsData.tax !== undefined"> 14541 <div class="flex flex-row flex-no-wrap items-baseline justify-between text-sm pt-2"> 14542 <div class="w-7/12 text-left md:w-auto" 14543 x-text="cart.totalsData.tax.title"></div> 14544 <div class="w-5/12 text-right md:w-auto" 14545 x-html="cart.totalsData.tax.value" 14546 ></div> 14547 </div> 14548 </template> 14549 <template x-if="cart.discount_breakdown && cart.discount_breakdown !== undefined && cart.discount_breakdown.length > 0"> 14550 <div class="flex pb-1 mt-2 text-md lg:text-sm md:grid md:grid-cols-2 w-full justify-between" @click="discountSummaryIsOpen = !discountSummaryIsOpen"> 14551 <div class="w-5/12 text-left md:w-auto flex items-start"> 14552 <div class="flex"> 14553 <span class="mr-2">Descuento</span> 14554 <span :class="{'rotate-180': discountSummaryIsOpen}"> 14555 <span class="a-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-4 h-4" width="24" height="24" role="img"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z"/><title>caret-down</title></svg> 14556</span> 14557 </span> 14558 </div> 14559 </div> 14560 <div class="w-5/12 text-right md:w-auto" 14561 mcclane-data="cart-price-with-discount" 14562 x-html="cart.discount_amount" 14563 ></div> 14564 </div> 14565 </template> 14566 <template x-if="cart.discount_breakdown && cart.discount_breakdown !== undefined && cart.discount_breakdown.length > 0"> 14567 <template x-for="discount_rule in cart.discount_breakdown"> 14568 <template x-if="discount_rule.rule_name !== undefined && 14569 discount_rule.rule_amount !== undefined"> 14570 <div x-show="discountSummaryIsOpen" class="flex py-2 pl-2 text-md lg:text-sm md:grid md:grid-cols-2 md:w-full"> 14571 <div class="w-7/12 text-left md:w-auto" x-html="discount_rule.rule_name"></div> 14572 <div class="w-5/12 text-right md:w-auto" mcclane-data="cart-price-with-discount" x-text="hyva.formatPrice(discount_rule.rule_amount)"></div> 14573 </div> 14574 </template> 14575 </template> 14576 </template> 14577 </div> 14578 <div class="w-full pb-4 px-2.5 pt-1"> 14579 <div class="flex flex-row justify-between text-xl font-primary font-bold mb-4">
14580 <span class="flex flex-col"> 14581 <span>Total</span> 14582 <span class="text-sm text-gray-medium pt-1"> 14583 Impuestos incluidos </span> 14584 </span> 14585 <span x-html="cart.totalsData.total.value" mcclane-data="minicart-subtotal"></span> 14586 </div> 14587 <div class="w-full flex flex-col items-center transition duration-150 ease-in-out"> 14588 <button @click.prevent.stop="setLoader();$dispatch('toggle-authentication', {url: atob('aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvY2hlY2tvdXQv')})" 14589 mcclane-data="minicart-checkout-button" 14590 class="btn btn-primary md:btn-lg w-full" 14591 :disabled="isLoadingButtonCheckout" 14592 > 14593 <span x-show="!isLoadingButtonCheckout" class="flex justify-center items-center"> 14594 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-5 h-5 mr-1" width="24" height="24" role="img"><path d="M236,69.4A16.13,16.13,0,0,0,223.92,64H176a48,48,0,0,0-96,0H32.08a16.13,16.13,0,0,0-12,5.4,16,16,0,0,0-3.92,12.48l14.26,120a16,16,0,0,0,16,14.12H209.67a16,16,0,0,0,16-14.12l14.26-120A16,16,0,0,0,236,69.4ZM128,32a32,32,0,0,1,32,32H96A32,32,0,0,1,128,32Zm81.76,168a.13.13,0,0,1-.09,0H46.25L32.08,80H224Z"/><title>tote-simple</title></svg> 14595Finalizar compra </span> 14596 <span x-show="isLoadingButtonCheckout" class="flex justify-center items-center"> 14597 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="animate-spin mr-1" width="24" height="24" role="img"><path d="M232,128a104,104,0,0,1-208,0c0-41,23.81-78.36,60.66-95.27a8,8,0,0,1,6.68,14.54C60.15,61.59,40,93.27,40,128a88,88,0,0,0,176,0c0-34.73-20.15-66.41-51.34-80.73a8,8,0,0,1,6.68-14.54C208.19,49.64,232,87,232,128Z"/><title>circle-notch</title></svg> 14598 Cargando... </span> 14599 </button> 14600 14601 <span class="cursor-pointer underline text-brand-primary text-sm mt-4" @click="openLink(atob('aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvY2hlY2tvdXQvY2FydC8='), '_self')" x-data="" x-defer="intersect" mcclane-data="minicart-to-cart-button"> 14602 Ver carrito </span> 14603 </div> 14604 </div> 14605 14606
14606<script> 14607 function prepareMollieApplePayMinicart() { 14608 const objectToFormData = (object, prefix = null, formDataObject = null) => { 14609 const formData = formDataObject || new FormData(); 14610 Object.keys(object).forEach(key => { 14611 const value = object[key]; 14612 const name = prefix ? `${prefix}[${key}]` : key; 14613 if (value instanceof Object) { 14614 objectToFormData(value, name, formData); 14615 } else { 14616 formData.append(name, value); 14617 } 14618 }); 14619 14620 return new URLSearchParams(formData).toString(); 14621 }; 14622 14623 return { 14624 totalAmount: 0, 14625 14626 init() { 14627 // Normally we would use private-content-loaded to get this information, but this component is 14628 // rendered after this event has been dispatched. So get the information from the browser storage. 14629 const browserStorage = hyva.getBrowserStorage(); 14630 if (browserStorage) { 14631 const cacheStorage = browserStorage.getItem('mage-cache-storage'); 14632 const cart = JSON.parse(cacheStorage).cart; 14633 14634 this.totalAmount = cart.subtotalAmount; 14635 } 14636 14637 window.addEventListener('private-content-loaded', event => { 14638 this.totalAmount = event.detail.data.cart.subtotalAmount 14639 }) 14640 }, 14641 14642 isLoading(value) { 14643 // This loader lives outside the cart in view/frontend/templates/applepay/loader.phtml 14644 const eventName = value ? 'mollie-applepay-loading-start' : 'mollie-applepay-loading-stop'; 14645 window.dispatchEvent(new CustomEvent(eventName, {})) 14646 }, 14647 14648 pay() { 14649 const amount = this.totalAmount; 14650 let countryCode, postalCode, shippingMethods, selectedShippingMethod, quoteTotals; 14651 14652 const request = { 14653 countryCode: "ES", 14654 currencyCode: "EUR", 14655 supportedNetworks: ["amex","masterCard","visa","maestro","vPay"], 14656 merchantCapabilities: ['supports3DS'], 14657 total: { 14658 label: "Espa\u00F1ol", 14659 amount: amount 14660 }, 14661 shippingType: 'shipping', 14662 requiredBillingContactFields: [ 14663 'postalAddress', 14664 'name', 14665 'email', 14666 'phone' 14667 ], 14668 requiredShippingContactFields: [ 14669 'postalAddress', 14670 'name', 14671 'email', 14672 'phone' 14673 ] 14674 } 14675 14676 let session = new ApplePaySession(3, request); 14677 14678 const getTotal = () => { 14679 const total = quoteTotals.find(item => item.code === 'grand_total') || quoteTotals[quoteTotals.length - 1]; 14680 14681 total.label = "Espa\u00F1ol"; 14682 14683 const payload = { total }; 14684 window.dispatchEvent(new CustomEvent('mollie-applepay-total', { 14685 detail: payload, 14686 })); 14687 14688 return payload.total; 14689 }; 14690 14691 const getLineItems = () => { 14692 let totals = [...quoteTotals]; 14693 totals = totals.filter(item => item.code !== 'grand_total'); 14694 14695 const payload = { lineItems: totals }; 14696 window.dispatchEvent(new CustomEvent('mollie-applepay-lineitems', { 14697 detail: payload, 14698 })); 14699 14700 return payload.lineItems; 14701 }; 14702 14703 const handleAjaxError = (message) => { 14704 this.isLoading(false); 14705 session.abort(); 14706 14707 dispatchMessages([ 14708 { 14709 text: message, 14710 type: 'error' 14711 } 14712 ]); 14713 }; 14714 14715 session.onpaymentmethodselected = () => { 14716 session.completePaymentMethodSelection(getTotal(), []); 14717 }; 14718 14719 session.onshippingcontactselected = (event) => { 14720 countryCode = event.shippingContact.countryCode; 14721 postalCode = event.shippingContact.postalCode; 14722 14723 fetch(`${BASE_URL}mollie/applePay/shippingMethods?form_key=${hyva.getFormKey()}`, { 14724 method: 'POST', 14725 headers: { 14726 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', 14727 }, 14728 body: 'countryCode=' + event.shippingContact.countryCode + 14729 '&postalCode=' + event.shippingContact.postalCode 14730 }) 14731 .then(async (response) => { 14732 if (!response.ok) { 14733 const data = await response.json(); 14734 if (data.message) { 14735 throw new Error(data.message); 14736 } 14737 14738 throw new Error('Network response was not ok'); 14739 } 14740 return response.json(); 14741 }) 14742 .then(result => { 14743 shippingMethods = result.shipping_methods; 14744 selectedShippingMethod = result.shipping_methods[0]; 14745 quoteTotals = result.totals; 14746 14747 session.completeShippingContactSelection( 14748 ApplePaySession.STATUS_SUCCESS, 14749 result.shipping_methods, 14750 getTotal(), 14751 getLineItems() 14752 ); 14753 }) 14754 .catch(error => handleAjaxError(error)); 14755 }; 14756 14757 session.onshippingmethodselected = (event) => { 14758 selectedShippingMethod = event.shippingMethod; 14759 14760 fetch(`${BASE_URL}mollie/applePay/shippingMethods?form_key=${hyva.getFormKey()}`, { 14761 method: 'POST', 14762 headers: { 14763 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', 14764 }, 14765 body: objectToFormData({ 14766 shippingMethod: selectedShippingMethod, 14767 countryCode: countryCode, 14768 postalCode: postalCode 14769 }) 14770 }) 14771 .then(async (response) => { 14772 if (!response.ok) { 14773 const data = await response.json(); 14774 if (data.message) { 14775 throw new Error(data.message); 14776 } 14777 14778 throw new Error('Network response was not ok'); 14779 } 14780 return response.json(); 14781 }) 14782 .then(result => { 14783 quoteTotals = result.totals; 14784 14785 session.completeShippingMethodSelection( 14786 ApplePaySession.STATUS_SUCCESS, 14787 getTotal(), 14788 getLineItems() 14789 ); 14790 }) 14791 .catch(error => handleAjaxError(error)); 14792 }; 14793 14794 session.onpaymentauthorized = (event) => { 14795 fetch(`${BASE_URL}mollie/applePay/placeOrder?form_key=${hyva.getFormKey()}`, { 14796 method: 'POST', 14797 headers: { 14798 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', 14799 }, 14800 body: objectToFormData({ 14801 shippingMethod: selectedShippingMethod, 14802 billingAddress: event.payment.billingContact, 14803 shippingAddress: event.payment.shippingContact, 14804 applePayPaymentToken: JSON.stringify(event.payment.token) 14805 }) 14806 }) 14807 .then(async (response) => { 14808 if (!response.ok) { 14809 const data = await response.json(); 14810 if (data.message) { 14811 throw new Error(data.message); 14812 } 14813 14814 throw new Error('Network response was not ok'); 14815 } 14816 return response.json(); 14817 }) 14818 .then(result => { 14819 if (!session) { 14820 console.warn('Payment canceled'); 14821 return; 14822 } 14823 14824 if (result.error) { 14825 handleAjaxError(result.error_message); 14826 return; 14827 } 14828 14829 if (!result.url) { 14830 handleAjaxError('Something went wrong, please try again later.'); 14831 return; 14832 } 14833 14834 session.completePayment(ApplePaySession.STATUS_SUCCESS); 14835 14836 location.href = result.url; 14837 }) 14838 .catch(error => handleAjaxError(error)); 14839 }; 14840 14841 session.onvalidatemerchant = (event) => { 14842 fetch( 14843 `${BASE_URL}mollie/checkout/applePayValidation?form_key=${hyva.getFormKey()}`, 14844 { 14845 method: 'POST', 14846 headers: { 14847 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8', 14848 }, 14849 body: objectToFormData({validationURL: event.validationURL}), 14850 } 14851 ) 14852 .then((response) => { 14853 if (!response.ok) { 14854 throw new Error('Merchant validation failed'); 14855 } 14856 14857 return response.json() 14858 }) 14859 .then((result) => session.completeMerchantValidation(result)) 14860 .catch(error => handleAjaxError(error)); 14861 }; 14862 14863 session.oncancel = () => { 14864 this.isLoading(false); 14865 session = null; 14866 } 14867 14868 this.isLoading(true); 14869 session.begin(); 14870 } 14871 } 14872 } 14873 14874 window.addEventListener( 14875 'alpine:init', 14876 () => Alpine.data('prepareMollieApplePayMinicart', prepareMollieApplePayMinicart), 14877 {once: true} 14878 ) 14879</script>
14879 14880 14881 <template x-if="cart.extra_actions"> 14882 <div class="relative grid gap-6 px-4 py-6 bg-white sm:gap-8 sm:px-6"> 14883 <div x-html="cart.extra_actions"></div> 14884 </div> 14885 </template> 14886 </div> 14887 </template> 14888 </div> 14889 14890 <div id="rocket_loading" class="flex flex-row justify-center items-center w-full h-full fixed select-none z-50" 14891 style="left: 50%;top: 50%;transform: translateX(-50%) translateY(-50%);background: rgba(255,255,255,0.7);" 14892 x-show="isLoading" 14893 x-transition:enter="ease-out duration-200" 14894 x-transition:enter-start="opacity-0" 14895 x-transition:enter-end="opacity-100" 14896 x-transition:leave="ease-in duration-200" 14897 x-transition:leave-start="opacity-100" 14898 x-transition:leave-end="opacity-0"> 14899 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 57 57" stroke="currentColor" class="text-primary" width="57" height="57" role="img"> 14900 <g fill="none" fill-rule="evenodd"> 14901 <g transform="translate(1 1)" stroke-width="2"> 14902 <circle cx="5" cy="50" r="5"> 14903 <animate attributeName="cy" begin="0s" dur="2.2s" values="50;5;50;50" calcMode="linear" repeatCount="indefinite"/> 14904 <animate attributeName="cx" begin="0s" dur="2.2s" values="5;27;49;5" calcMode="linear" repeatCount="indefinite"/> 14905 </circle> 14906 <circle cx="27" cy="5" r="5"> 14907 <animate attributeName="cy" begin="0s" dur="2.2s" from="5" to="5" values="5;50;50;5" calcMode="linear" repeatCount="indefinite"/> 14908 <animate attributeName="cx" begin="0s" dur="2.2s" from="27" to="27" values="27;49;5;27" calcMode="linear" repeatCount="indefinite"/> 14909 </circle> 14910 <circle cx="49" cy="50" r="5"> 14911 <animate attributeName="cy" begin="0s" dur="2.2s" values="50;50;5;50" calcMode="linear" repeatCount="indefinite"/> 14912 <animate attributeName="cx" from="49" to="49" begin="0s" dur="2.2s" values="49;5;27;49" calcMode="linear" repeatCount="indefinite"/> 14913 </circle> 14914 </g> 14915 </g> 14916<title>loader</title></svg> 14917 <div class="ml-10 text-primary text-xl"> 14918 Cargando... </div> 14919</div> 14920 </div> 14921 </div> 14922 </div> 14923</section>
14924<script> 14925 function initAuthentication() { 14926 return { 14927 open: false, 14928 forceAuthentication: false, 14929 checkoutUrl: 'https://www.serrats.com/es_es/checkout/index/', 14930 errors: 0, 14931 showPassword: false, 14932 isLoading: false, 14933 isLoadingButtonCreateAccount: false, 14934 hasCaptchaToken: 0, 14935 displayErrorMessage: false, 14936 errorMessages: [], 14937 errorLogin: '', 14938 setErrorMessages: function setErrorMessages(messages) { 14939 this.errorMessages = [messages]; 14940 this.displayErrorMessage = this.errorMessages.length; 14941 }, 14942 submitForm: function () { 14943 // Do not rename $form, the variable is expected to be declared in the recaptcha output 14944 const $form = document.querySelector('#login-form'); 14945 this.errors = 0; 14946 14947 if (this.errors && !this.hasCaptchaToken) { 14948 return; 14949 } 14950 14951 if (this.errors === 0) { 14952 this.dispatchLoginRequest($form); 14953 } else { 14954 (async () => { 14955 this.isLoading = true; 14956 await new Promise(resolve => setTimeout(resolve, 1000)) 14957 this.isLoading = false; 14958 dispatchMessages([{ 14959 type: 'error', 14960 text: this.errorLogin 14961 }], 5000); 14962 })(); 14963 } 14964 }, 14965 onPrivateContentLoaded: function (data) { 14966 const isLoggedIn = data.customer && data.customer.firstname; 14967 if (data.cart && !isLoggedIn) { 14968 this.forceAuthentication = !data.cart.isGuestCheckoutAllowed; 14969 } 14970 }, 14971 redirectIfAuthenticated: function (event) { 14972 if (event.detail && event.detail.url) { 14973 this.checkoutUrl = event.detail.url; 14974 } 14975 if (!this.forceAuthentication) { 14976 window.location.href = this.checkoutUrl; 14977 } 14978 }, 14979 addRedirectCookie: function (event) { 14980 if (this.forceAuthentication && event.detail && event.detail.url) { 14981 hyva.setCookie("login_redirect", event.detail.url, 1); 14982 } 14983 }, 14984 dispatchLoginRequest: function (form) { 14985 this.isLoading = true; 14986 const username = this.$refs['customer-email'].value; 14987 const password = this.$refs['customer-password'].value; 14988 const formKey = hyva.getFormKey(); 14989 const bodyFields = { 14990 'username': username, 14991 'password': password, 14992 'formKey': formKey 14993 }; 14994 const fieldName = 'g\u002Drecaptcha\u002Dresponse'; 14995 const recaptchaField = fieldName && form[fieldName]; 14996 if (recaptchaField) { 14997 bodyFields[fieldName] = recaptchaField.value; 14998 } 14999 fetch('https://www.serrats.com/es_es/customer/ajax/login/', { 15000 method: 'POST', 15001 headers: { 15002 'Content-Type': 'application/json', 15003 'X-Requested-With': 'XMLHttpRequest' 15004 }, 15005 body: JSON.stringify(bodyFields) 15006 } 15007 ).then(response => { 15008 return response.json() 15009 } 15010 ).then(data => { 15011 if (data.errors) { 15012 dispatchMessages([{ 15013 type: 'error', 15014 text: data.message 15015 }], 5000); 15016 this.errorLogin = data.message; 15017 this.errors = 1; 15018 this.hasCaptchaToken = 0; 15019 this.isLoading = false;
15020 } else { 15021 window.location.href = this.checkoutUrl; 15022 } 15023 }); 15024 } 15025 } 15026 } 15027</script>
15027 15028<section id="authentication-popup" 15029 x-data="initAuthentication()" 15030 @private-content-loaded.window="onPrivateContentLoaded($event.detail.data)" 15031 @toggle-authentication.window="open = forceAuthentication; redirectIfAuthenticated(event); addRedirectCookie(event)" 15032 @toggle-authentication-popup.window="open = !open; checkoutUrl = event.detail.url" 15033 @keydown.window.escape="open = false" 15034> 15035 <div role="dialog" 15036 aria-modal="true" 15037 aria-label="Región de autenticación de usuario" 15038 class="fixed inset-y-0 right-0 z-40 flex max-w-[420px]"> 15039 <div class="hidden" 15040 :class="{ 'backdrop backdrop-close': open, 'hidden': !open }" 15041 x-transition:enter="ease-in-out duration-500" 15042 x-transition:enter-start="opacity-0" 15043 x-transition:enter-end="opacity-100" 15044 x-transition:leave="ease-in-out duration-500" 15045 x-transition:leave-start="opacity-100" 15046 x-transition:leave-end="opacity-0" 15047 @click="open = false" 15048 aria-label="Close panel"></div> 15049 <div class="relative w-screen max-w-md bg-white" 15050 x-show="open" 15051 x-cloak="" 15052 x-transition:enter="transform transition ease-in-out duration-500 sm:duration-700" 15053 x-transition:enter-start="translate-x-full" 15054 x-transition:enter-end="translate-x-0" 15055 x-transition:leave="transform transition ease-in-out duration-500 sm:duration-700" 15056 x-transition:leave-start="translate-x-0" 15057 x-transition:leave-end="translate-x-full" 15058 > 15059 <div class="flex flex-col h-full space-y-4 px-5 md:space-y-5  overflow-y-auto"> 15060 <header class="pr-2 pl-0.5 md:pr-4 md:pl-1.5 pt-2 pb-1 md:py-2 flex flex-row justify-between items-center -mx-4 md:-mx-5"> 15061 <div 15062 x-show="open" 15063 x-cloak="" 15064 x-transition:enter="ease-in-out duration-500" 15065 x-transition:enter-start="opacity-0" 15066 x-transition:enter-end="opacity-100" 15067 x-transition:leave="ease-in-out duration-500" 15068 x-transition:leave-start="opacity-100" 15069 x-transition:leave-end="opacity-0" class="flex"> 15070 <button @click="open = false;" aria-label="Close panel" 15071 class="text-black transition duration-150 ease-in-out block hover:text-black"> 15072 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-8 h-8 p-1" width="24" height="24" role="img"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/><title>x</title></svg> 15073 </button> 15074 </div> 15075 <p class="md:text-4xl font-bold text-xl"> 15076 Mi cuenta </p> 15077 <div class="w-8 h-8"></div> 15078 </header> 15079 <div class="block-customer-login "> 15080 <form class="form form-login" 15081 method="post" 15082 @submit.prevent="submitForm();" 15083 id="login-form"> 15084 <p class="text-xl font-bold mb-3.5 md:mb-5 md:text-3xl mt-1.5">Bienvenido a Serrats</p> 15085 <div class="fieldset login"> 15086 <div class="field email required "> 15087 <label class="label " for="customer-email"> 15088 <span>Email</span> 15089 </label> 15090 <div class="control"> 15091 <input name="username" 15092 id="form-login-username" 15093 x-ref="customer-email" 15094 @change="errors = 0" 15095 mcclane-data="login-form-email" 15096 type="email" 15097 required 15098 class="form-input input-text" 15099 > 15100 </div> 15101 </div> 15102 <div class="field password required "> 15103 <label for="pass" class="label ">
15104 <span>Contraseña</span> 15105 </label> 15106 <div class="control relative flex items-center"> 15107 <input name="password" 15108 id="form-login-password" 15109 :type="showPassword ? 'text' : 'password'" 15110 type="password" 15111 class="form-input input-text" 15112 required 15113 x-ref="customer-password" 15114 @change="errors = 0" 15115 mcclane-data="login-form-password" 15116 > 15117 <button type="button" 15118 x-on:click="showPassword = !showPassword" 15119 :aria-pressed="showPassword" 15120 :aria-label="showPassword ? 'Ocultar\u0020contrase\u00F1a' : 'Mostrar\u0020contrase\u00F1a'" 15121 class="cursor-pointer px-4 absolute right-0 rounded focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-1" 15122> 15123 <template x-if="!showPassword"> 15124 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-4 h-4 text-input-text hover:text-input-text-focus" width="24" height="24" role="img"><path d="M247.31,124.76c-.35-.79-8.82-19.58-27.65-38.41C194.57,61.26,162.88,48,128,48S61.43,61.26,36.34,86.35C17.51,105.18,9,124,8.69,124.76a8,8,0,0,0,0,6.5c.35.79,8.82,19.57,27.65,38.4C61.43,194.74,93.12,208,128,208s66.57-13.26,91.66-38.34c18.83-18.83,27.3-37.61,27.65-38.4A8,8,0,0,0,247.31,124.76ZM128,192c-30.78,0-57.67-11.19-79.93-33.25A133.47,133.47,0,0,1,25,128,133.33,133.33,0,0,1,48.07,97.25C70.33,75.19,97.22,64,128,64s57.67,11.19,79.93,33.25A133.46,133.46,0,0,1,231.05,128C223.84,141.46,192.43,192,128,192Zm0-112a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,80Zm0,80a32,32,0,1,1,32-32A32,32,0,0,1,128,160Z"/><title>eye</title></svg> 15125 </template> 15126 <template x-if="showPassword"> 15127 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-4 h-4 text-input-text hover:text-input-text-focus" width="24" height="24" role="img"><path d="M53.92,34.62A8,8,0,1,0,42.08,45.38L61.32,66.55C25,88.84,9.38,123.2,8.69,124.76a8,8,0,0,0,0,6.5c.35.79,8.82,19.57,27.65,38.4C61.43,194.74,93.12,208,128,208a127.11,127.11,0,0,0,52.07-10.83l22,24.21a8,8,0,1,0,11.84-10.76Zm47.33,75.84,41.67,45.85a32,32,0,0,1-41.67-45.85ZM128,192c-30.78,0-57.67-11.19-79.93-33.25A133.16,133.16,0,0,1,25,128c4.69-8.79,19.66-33.39,47.35-49.38l18,19.75a48,48,0,0,0,63.66,70l14.73,16.2A112,112,0,0,1,128,192Zm6-95.43a8,8,0,0,1,3-15.72,48.16,48.16,0,0,1,38.77,42.64,8,8,0,0,1-7.22,8.71,6.39,6.39,0,0,1-.75,0,8,8,0,0,1-8-7.26A32.09,32.09,0,0,0,134,96.57Zm113.28,34.69c-.42.94-10.55,23.37-33.36,43.8a8,8,0,1,1-10.67-11.92A132.77,132.77,0,0,0,231.05,128a133.15,133.15,0,0,0-23.12-30.77C185.67,75.19,158.78,64,128,64a118.37,118.37,0,0,0-19.36,1.57A8,8,0,1,1,106,49.79,134,134,0,0,1,128,48c34.88,0,66.57,13.26,91.66,38.35,18.83,18.83,27.3,37.62,27.65,38.41A8,8,0,0,1,247.31,131.26Z"/><title>eye-slash</title></svg> 15128 </template> 15129</button> 15130 </div> 15131 </div> 15132 15133 <input name="context" type="hidden" value="checkout"/> 15134 <div class="actions-toolbar flex flex-col flex-nowrap"> 15135 <div> 15136 <span class="cursor-pointer text-sm underline text-brand-primary mb-4 md:mb-5 block" @click="openLink(atob('aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvY3VzdG9tZXIvYWNjb3VudC9mb3Jnb3RwYXNzd29yZC8='), '_self')" x-data="" x-defer="intersect" mcclane-data="customer-password-recovery-button"> 15137 ¿Has olvidado tu contraseña? </span> 15138 </div> 15139 15140 <button type="submit" class="inline-flex btn btn-primary md:btn-lg" mcclane-data="login-form-submit" 15141 :class="{ 'relative ajax-btn-is-loading': isLoading }" 15142 :disabled="isLoading">
15143 <span x-show="!isLoading">Inicia sesión</span> 15144 <div x-show="isLoading" class="flex absolute inset-0 justify-center items-center loader"> 15145 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="animate-spin" width="24" height="24" role="img"><path d="M232,128a104,104,0,0,1-208,0c0-41,23.81-78.36,60.66-95.27a8,8,0,0,1,6.68,14.54C60.15,61.59,40,93.27,40,128a88,88,0,0,0,176,0c0-34.73-20.15-66.41-51.34-80.73a8,8,0,0,1,6.68-14.54C208.19,49.64,232,87,232,128Z"/><title>circle-notch</title></svg> 15146 </div> 15147 </button> 15148 </div> 15149 15150 </div> 15151 </form> 15152 </div> 15153 15154 15155 <div class="block-new-customer border-t-2 border-gray pt-6 md:pt-5"> 15156 <p id="authenticate-new-customer" class="text-lg md:text-xl font-bold text-black mb-2"> 15157 No tengo una cuenta </p> 15158 15159 <div class="block-content "> 15160 <p class="text-md font-light"> 15161 Crear una cuenta tiene muchos beneficios: Pago más rápido, guardar más de una dirección, seguimiento de pedidos y mucho más. </p> 15162 <div class="actions-toolbar flex justify-between mt-5 mb-2 items-center" @click="isLoadingButtonCreateAccount = true"> 15163 <span class="cursor-pointer inline-flex btn btn-dark-stroke md:btn-lg w-full" @click="openLink(atob('aHR0cHM6Ly93d3cuc2VycmF0cy5jb20vZXNfZXMvY3VzdG9tZXIvYWNjb3VudC9jcmVhdGUv'), '_self')" x-data="" x-defer="intersect" mcclane-data="customer-register-form-register-button" x-show="!isLoadingButtonCreateAccount"> 15164 Crear cuenta </span> 15165 <button x-show="isLoadingButtonCreateAccount" class="inline-flex btn btn-dark-stroke md:btn-lg w-full loader" disabled> 15166 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="animate-spin" width="24" height="24" role="img"><path d="M232,128a104,104,0,0,1-208,0c0-41,23.81-78.36,60.66-95.27a8,8,0,0,1,6.68,14.54C60.15,61.59,40,93.27,40,128a88,88,0,0,0,176,0c0-34.73-20.15-66.41-51.34-80.73a8,8,0,0,1,6.68-14.54C208.19,49.64,232,87,232,128Z"/><title>circle-notch</title></svg> 15167 </button> 15168 </div> 15169 </div> 15170 </div> 15171 </div> 15172 </div> 15173 </div> 15174</section>
15175<script> 15176 'use strict'; 15177 (function( rocketWishlist, undefined ) { 15178 let isLoggedIn = false; 15179 const sendWishlistStatus = (e) => { 15180 isLoggedIn = e.detail.data.customer.firstname != null; 15181 if (!isLoggedIn) return; 15182 e.detail.data.wishlist.items.forEach(item => { 15183 window.dispatchEvent(new CustomEvent(`setwishliststatus${item.product_id}`, {detail: {status: true, deleteParams: JSON.parse(item.delete_item_params)}})) 15184 }) 15185 } 15186 rocketWishlist.add = (productId) => { 15187 if (!isLoggedIn) { 15188 window.dispatchEvent(new CustomEvent(`setwishliststatus${productId}`, {detail: {status: false}})) 15189 window.dispatchEvent(new CustomEvent("toggle-authentication-popup", {detail: {url: window.location.href}})) 15190 return; 15191 } 15192 const postParams = { 15193 action: BASE_URL + "wishlist/index/add/", 15194 data: { 15195 product: productId, 15196 uenc: hyva.getUenc(), 15197 isAjax: true, 15198 form_key: hyva.getFormKey() 15199 } 15200 } 15201 let postData = Object.keys(postParams.data).map(key => { 15202 return `${key}=${postParams.data[key]}`; 15203 }).join('&'); 15204 15205 // Take all the grouped product options 15206 Array 15207 .from( 15208 document.querySelectorAll( 15209 '[x-ref^="super_group_"]' 15210 ) 15211 ) 15212 .forEach((input) => { 15213 //super_group[productId]=qty 15214 let childProductId = input.getAttribute('x-ref').replace('super_group_', ''); 15215 postData += `&super_group[${childProductId}]=1` 15216 }) 15217 fetch(postParams.action, { 15218 "headers": { 15219 "content-type": "application/x-www-form-urlencoded; charset=UTF-8", 15220 }, 15221 "body": postData, 15222 "method": "POST", 15223 "mode": "cors", 15224 "credentials": "include" 15225 }).then(async (response) => { 15226 let responseData = await response.json(); 15227 if (false && responseData.backUrl) { 15228 window.location.href = responseData.backUrl; 15229 } else if (response.ok) { 15230 if (responseData && responseData.delete_item_params) { 15231 window.addEventListener('private-content-loaded', () => window.dispatchEvent(new CustomEvent(`setwishliststatus${productId}`, {detail: {status: true, deleteParams : responseData.delete_item_params}})), {once: true}); 15232 } 15233 window.dispatchEvent(new CustomEvent("change-counter-wishlist", { detail: { action: 'add' }})); 15234 window.dispatchEvent(new CustomEvent("reload-customer-section-data")); 15235 } else { 15236 window.dispatchEvent(new CustomEvent(`setwishliststatus${productId}`, {detail: {status: false}})) 15237 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages( 15238 [{ 15239 type: "warning", 15240 text: "Product could not be added to the wishlist." 15241 }], 5000 15242 ); 15243 } 15244 }) 15245 } 15246 rocketWishlist.remove = (deleteParams, productId) => { 15247 deleteParams.data.isAjax = true; 15248 deleteParams.data.uenc = hyva.getUenc(); 15249 deleteParams.data.form_key = hyva.getFormKey(); 15250 15251 let postData = Object.keys(deleteParams.data).map(key => { 15252 return `${key}=${deleteParams.data[key]}`; 15253 }).join('&'); 15254 15255 fetch(deleteParams.action, { 15256 "headers": { 15257 "content-type": "application/x-www-form-urlencoded; charset=UTF-8", 15258 }, 15259 "body": postData, 15260 "method": "POST", 15261 "mode": "cors", 15262 "credentials": "include" 15263 }).then(async (response) => { 15264 await response; 15265 if (response.ok) { 15266 window.addEventListener('private-content-loaded', () => window.dispatchEvent(new CustomEvent(`setwishliststatus${productId}`, {detail: {status: false}})), {once: true}) 15267 window.dispatchEvent(new CustomEvent("change-counter-wishlist", { detail: { action: 'remove' }})); 15268 window.dispatchEvent(new CustomEvent("reload-customer-section-data")); 15269 } else { 15270 window.dispatchEvent(new CustomEvent(`setwishliststatus${productId}`, {detail: {status: true}})) 15271 typeof window.dispatchMessages !== "undefined" && window.dispatchMessages( 15272 [{ 15273 type: "warning", 15274 text: "Product could not be removed from the wishlist." 15275 }], 5000 15276 ); 15277 } 15278 }) 15279 } 15280 window.addEventListener('private-content-loaded', (e) => sendWishlistStatus(e)) 15281 }( window.rocketWishlist = window.rocketWishlist || {} )); 15282</script>
15282 15283<style> 15284 .ajax-btn-is-loading > :not(.loader) { 15285 visibility: hidden; 15286 } 15287</style>
15288<script> 15289 window.setSingleAjaxCart = (forward = true, selectors = '.product_addtocart_form,\u0020\u0023product_addtocart_form,\u0020.product\u002Ditem.card.card\u002Dinteractive', recursive = true) => { 15290 const forms = document.querySelectorAll(selectors); 15291 const form = (forward) ? forms[forms.length-1] : forms[0]; 15292 window.setAjaxCartEventListener(form, recursive) 15293 } 15294 15295 window.setAjaxCart = (selectors = '.product_addtocart_form,\u0020\u0023product_addtocart_form,\u0020.product\u002Ditem.card.card\u002Dinteractive', recursive = true) => { 15296 const forms = document.querySelectorAll(selectors); 15297 forms.forEach(form => { 15298 window.setAjaxCartEventListener(form, recursive) 15299 }); 15300 } 15301 window.setAjaxCartEventListener = (el, recursive = true) => { 15302 el.addEventListener('submit', async (e) => { 15303 e.preventDefault(); 15304 const formData = new URLSearchParams(new FormData(el)); 15305 const button = e.submitter instanceof HTMLButtonElement 15306 ? e.submitter 15307 : el.querySelector('button') 15308 ? el.querySelector('button') 15309 : document.getElementById('product-addtocart-button'); 15310 const loader = document.createElement('div'); 15311 15312 loader.className = 'absolute inset-0 flex justify-center items-center loader'; 15313 loader.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="animate-spin" width="24" height="24" role="img"><path d="M232,128a104,104,0,0,1-208,0c0-41,23.81-78.36,60.66-95.27a8,8,0,0,1,6.68,14.54C60.15,61.59,40,93.27,40,128a88,88,0,0,0,176,0c0-34.73-20.15-66.41-51.34-80.73a8,8,0,0,1,6.68-14.54C208.19,49.64,232,87,232,128Z"/><title>circle-notch</title></svg> 15314`; 15315 15316 button.prepend(loader); 15317 button.classList.add('relative', 'ajax-btn-is-loading'); 15318 button.disabled = true; 15319 15320 let removeLoader = () => { 15321 window.addEventListener('private-content-loaded', () => { 15322 button.classList.remove('ajax-btn-is-loading'); 15323 button.disabled = false; 15324 loader.remove() 15325 if (true) { 15326 window.dispatchEvent(new CustomEvent('clear-messages')); 15327 window.dispatchEvent(new CustomEvent('toggle-cart')); 15328 } 15329 }, {once: true}) 15330 15331 } 15332 15333 try { 15334 const response = await fetch(e.currentTarget.action, { 15335 method: 'POST', 15336 body: formData, 15337 headers: { 15338 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 15339 'X-Requested-With': 'XMLHttpRequest' 15340 } 15341 }); 15342 if (!response.ok) { 15343 return form.submit(); 15344 } 15345 15346 if (response.redirected) { 15347 return window.location.href = response.url; 15348 } 15349 15350 const data = await response.json(); 15351 15352 if (data.backUrl) { 15353 return window.location.href = data.backUrl; 15354 } 15355 15356 if (recursive) { 15357 window.dispatchEvent(new CustomEvent('product-addtocart-success')); 15358 } 15359 15360 removeLoader(); 15361 15362 return window.dispatchEvent(new CustomEvent('reload-customer-section-data')); 15363 } catch (err) { 15364 console.warn(err); 15365 window.dispatchEvent(new CustomEvent('product-addtocart-error')); 15366 removeLoader(); 15367 setMessage({ 15368 text:'There\u0020was\u0020a\u0020problem\u0020adding\u0020your\u0020item\u0020to\u0020the\u0020cart.', 15369 type: 'error' 15370 }); 15371 } finally { 15372 try { 15373 let messages = hyva.getCookie('mage-messages'); 15374 messages = messages ? JSON.parse(decodeURIComponent(messages).replace(/\+/g, ' ')) : []; 15375 document.cookie = 'mage-messages=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;'; 15376 } catch (error) { 15377 console.warn('Error parsing Cookie Messages:', error); 15378 return; 15379 } 15380 } 15381 }); 15382 } 15383 15384 /** 15385 * Set Message 15386 */ 15387 function setMessage(message) { 15388 typeof window.dispatchMessages !== "undefined" && 15389 window.dispatchMessages([message], 5000); 15390 } 15391 15392 /** Init on pageload */ 15393 window.setAjaxCart(); 15394</script>
vendor: 1 bytes, line 15394
15394
15395<script> 15396 'use strict'; 15397 15398 const grecaptchaV2LoadCallbacks = []; 15399 15400 function executeRecaptchaLoadCallbacks () { 15401 while (window.grecaptcha && grecaptchaV2LoadCallbacks.length > 0) { 15402 const callback = grecaptchaV2LoadCallbacks.pop(); 15403 typeof callback === 'string' ? window[callback]() : callback(); 15404 } 15405 } 15406 15407 (function() { 15408 const loadRecaptchaScript = (event) => { 15409 15410 if (window.grecaptcha || !event.target.form) { 15411 return; 15412 } 15413 15414 const url = 'https://www.google.com/recaptcha/api.js?onload=executeRecaptchaLoadCallbacks'; 15415 const siteKey = ''; 15416 const script = document.createElement('script'); 15417 script.type = 'text/javascript'; 15418 script.src = siteKey ? `${url}&render=${siteKey}` : `${url}&render=explicit`; 15419 script.async = true; 15420 document.head.appendChild(script); 15421 15422 script.addEventListener('load', () => { 15423 Array.from(document.querySelectorAll('button[data-recaptcha-btn]:disabled')).forEach(btn => btn.removeAttribute('disabled')); 15424 }); 15425 } 15426 15427 window.forceLoadRecaptchaScript = (form) => { 15428 loadRecaptchaScript({target: {form: form || 'dummy'}}); 15429 executeRecaptchaLoadCallbacks(); 15430 }; 15431 15432 document.body.addEventListener('input', loadRecaptchaScript, { once: true }); 15433 document.body.addEventListener('focus', loadRecaptchaScript, { once: true }); 15434 15435 }()); 15436 15437</script>
vendor: 1 bytes, line 15437
15437
15438<script type="application/ld+json"> 15439 { 15440 "@context": "https://schema.org", 15441 "@type": "BreadcrumbList", 15442 "itemListElement": [ 15443 { 15444 "@type": "ListItem", 15445 "position": 1, 15446 "name": "Inicio", 15447 "item": "https://www.serrats.com/es_es" 15448 }, 15449 { 15450 "@type": "ListItem", 15451 "position": 2, 15452 "name": "Bonito del Norte" 15453 } 15454 ] 15455}</script>
vendor: 1 bytes, line 15455
15455
15456<script> 15457 'use strict'; 15458 15459 (function () { 15460 const modals = []; 15461 const excludedFromFocusTrapping = new Set(); 15462 15463 function trapFocusInNextModalWithOverlay() { 15464 for (let idx = modals.length -1; idx >= 0; idx--) { 15465 const nextOnStack = modals[idx]; 15466 const nextDialogElement = nextOnStack.instance.$refs[nextOnStack.name]; 15467 if (! isOverlayDisabled(nextDialogElement)) { 15468 hyva.trapFocus(nextDialogElement); 15469 break; 15470 } 15471 } 15472 } 15473 15474 function focusables(dialogElement) { 15475 const selector = 'button, [href], input, textarea, select, details, [tabindex]:not([tabindex="-1"])'; 15476 return Array.from(dialogElement.querySelectorAll(selector)) 15477 .filter(el => !el.hasAttribute('disabled')); 15478 } 15479 15480 function firstVisible(elements) { 15481 const a = Array.from(elements); 15482 for (let i = 0; i < a.length; i++) { 15483 if (a[i].offsetWidth || a[i].offsetHeight || a[i].getClientRects().length) return a[i]; 15484 } 15485 return null; 15486 } 15487 15488 function isInViewport(element) { 15489 const rect = element && element.getBoundingClientRect(); 15490 return rect && 15491 rect.top >= 0 && 15492 rect.left >= 0 && 15493 rect.right <= window.innerWidth && 15494 rect.bottom <= window.innerHeight; 15495 } 15496 15497 function setFocusAfterTransition(dialogElement, duration) { 15498 const nested = Array.from(dialogElement.querySelectorAll('[role="dialog"]')); 15499 const candidates = Array.from(dialogElement.querySelectorAll('[x-focus-first]')); 15500 next: for (let candidate of candidates) { 15501 for (let child of nested) { 15502 if (child.contains(candidate)) continue next; 15503 } 15504 setTimeout(() => candidate.focus(), 50); 15505 break; 15506 } 15507 window.setTimeout(() => { 15508 const focusElement = firstVisible(dialogElement.querySelectorAll('[x-focus-first]')) || 15509 focusables(dialogElement)[0] || 15510 null; 15511 focusElement && isInViewport(focusElement) && focusElement.focus(); 15512 }, Math.max(1, duration)); 15513 } 15514 15515 function determineTrigger($refs, dialog, trigger) { 15516 if (typeof trigger === 'undefined' && typeof dialog === 'object' && dialog.target instanceof HTMLElement) { 15517 return dialog.target; 15518 } 15519 if (typeof dialog === 'string' && typeof trigger === 'object' && trigger.target instanceof HTMLElement) { 15520 return trigger.target; 15521 } 15522 if (typeof trigger === 'string') { 15523 try { 15524 return $refs[trigger] || document.querySelector(trigger) 15525 } catch (e) {} 15526 } 15527 if (trigger instanceof Element) { 15528 return trigger; 15529 } 15530 15531 return null; 15532 } 15533 15534 function isOverlayDisabled(dialog) { 15535 return dialog && dialog.hasAttribute('x-no-overlay') 15536 } 15537 15538 function areRemainingModalsWithoutOverlay(modals) 15539 { 15540 const overflowDisabled = modals.map(modal => modal.instance.$refs[modal.name]).filter(isOverlayDisabled); 15541 15542 return overflowDisabled.length === modals.length; 15543 } 15544 15545 window.hyva.modal = function(options = {}) { 15546 if (this.$el && this.$el.dataset && this.$el.dataset.options) { 15547 try { 15548 options = Object.assign(options, JSON.parse(this.$el.dataset.options || '{}')); 15549 } catch (e) { 15550 throw new Error('Cannot read the dialog options from the data-options attribute: not valid JSON'); 15551 } 15552 } 15553 15554 const config = Object.assign({ 15555 dialog: 'dialog', duration: 300, transitionEnter: 'transition ease-out duration-300', 15556 transitionEnterStart: 'opacity-0', 15557 transitionEnterEnd: 'opacity-100', 15558 transitionLeave: 'transition ease-in duration-300', 15559 transitionLeaveStart: 'opacity-100', 15560 transitionLeaveEnd: 'opacity-0', 15561 }, options); 15562 let lastHide = 0; 15563 15564 return { 15565 opened: {}, 15566 show(dialog, trigger) { 15567 const focusTargetAfterHide = determineTrigger(this.$refs, dialog, trigger); 15568 const name = typeof dialog === 'string' ? dialog : config.dialog; 15569 const dialogElement = this.$refs[name]; 15570 if (! dialogElement) { 15571 return; 15572 } 15573 const useOverlay = ! dialogElement.hasAttribute('x-no-overlay'); 15574 15575 dialogElement.scrollTop = 0; 15576 15577 if (this.opened[name]) { 15578 return; 15579 } 15580 15581 if (focusTargetAfterHide) { 15582 focusTargetAfterHide.setAttribute('aria-expanded', 'true'); 15583 } 15584 15585 this.opened[name] = true; 15586 useOverlay && this.$nextTick(() => hyva.trapFocus(dialogElement)); 15587 setFocusAfterTransition(dialogElement, config.duration); 15588 15589 const frame = {name, instance: this, focusTarget: focu
15589sTargetAfterHide, time: Date.now()}; 15590 15591 modals.push(frame); 15592 if (useOverlay) { 15593 document.body.classList.add('overflow-hidden'); 15594 } 15595 return new Promise(resolve => frame.resolve = resolve); 15596 }, 15597 cancel() { 15598 this.hide(false); 15599 }, 15600 ok() { 15601 this.hide(true); 15602 }, 15603 hide(value) { 15604 if (Date.now() - lastHide < config.duration) { 15605 return; 15606 } 15607 lastHide = Date.now(); 15608 15609 const modal = modals.pop() || {}; 15610 if (! modal.instance) { 15611 return; 15612 } 15613 15614 const name = modal.name; 15615 this.opened[name] = false; 15616 hyva.releaseFocus(modal.instance.$refs[modal.name]) 15617 trapFocusInNextModalWithOverlay(); 15618 15619 const nextFocusAfterHide = modal.focusTarget; 15620 nextFocusAfterHide && setTimeout(() => { 15621 nextFocusAfterHide.setAttribute('aria-expanded', 'false'); 15622 nextFocusAfterHide.focus() 15623 }, config.duration); 15624 15625 if (modals.length === 0 || areRemainingModalsWithoutOverlay(modals)) { 15626 document.body.classList.remove('overflow-hidden'); 15627 } 15628 15629 modal.resolve(value); 15630 }, 15631 overlay(dialog) { 15632 dialog = this.$el.dataset.dialogRefName || dialog; 15633 const name = typeof dialog === 'string' ? dialog : config.dialog; 15634 return { 15635 ['x-show']() { 15636 return this.opened[name] 15637 }, 15638 ['x-transition:enter']: config.transitionEnter, 15639 ['x-transition:enter-start']: config.transitionEnterStart, 15640 ['x-transition:enter-end']: config.transitionEnterEnd, 15641 ['x-transition:leave']: config.transitionLeave, 15642 ['x-transition:leave-start']: config.transitionLeaveStart, 15643 ['x-transition:leave-end']: config.transitionLeaveEnd, 15644 ['@hyva-modal-show.window'](event) { 15645 event.detail && event.detail.dialog === name && this.show(name, event.detail.focusAfterHide) 15646 } 15647 }; 15648 }, 15649 showDialogOnInit() { 15650 const parent = this.$el.closest('[data-dialog-ref-name]'); 15651 if (parent && parent.dataset.dialogRefName) { 15652 this.$dispatch('hyva-modal-show', {dialog: parent.dataset.dialogRefName}) 15653 } 15654 } 15655 }; 15656 } 15657 15658 window.hyva.modal.peek = () => modals.length > 0 && modals[modals.length -1] 15659 15660 window.hyva.modal.pop = function () { 15661 if (modals.length > 0) { 15662 const modal = modals[modals.length -1]; 15663 modal.instance.hide(); 15664 } 15665 } 15666 15667 window.hyva.modal.excludeSelectorsFromFocusTrap = function (selectors) { 15668 typeof selectors === 'string' || selectors instanceof String 15669 ? excludedFromFocusTrapping.add(selectors) 15670 : selectors.map(selector => excludedFromFocusTrapping.add(selector)); 15671 } 15672 15673 window.hyva.modal.eventListeners = { 15674 keydown: event => { 15675 if (event.key === 'Escape') { 15676 window.hyva.modal.pop(); 15677 } 15678 }, 15679 click: event => { 15680 if (modals.length > 0) { 15681 const modal = modals[modals.length -1]; 15682 const dialog = modal.instance.$refs[modal.name]; 15683 if (modal.time + 50 < Date.now() && // if last click processing is more than 50ms ago 15684 ! isOverlayDisabled(dialog) && // if dialog has overlay 15685 ! dialog.contains(event.target)) { // if click is outside of dialog 15686 modal.instance.hide(); 15687 } 15688 } 15689 } 15690 }; 15691 15692 document.addEventListener('keydown', window.hyva.modal.eventListeners.keydown); 15693 15694 document.addEventListener('click', window.hyva.modal.eventListeners.click); 15695 })(); 15696 window.addEventListener('alpine:init', () => { 15697 Alpine.data('hyvaModal', window.hyva.modal); 15698 }, {once: true}); 15699</script>
15699 15700
15701<script defer> 15702 'use strict'; 15703 15704 const TwIntersectObserver = { 15705 start() { 15706 if ('requestIdleCallback' in window) { 15707 requestIdleCallback(() => this.observe()); 15708 } else { 15709 setTimeout(() => this.observe(), 200); 15710 } 15711 }, 15712 15713 observe() { 15714 const selectors = [ 15715 '[class*=" intersect:"]', 15716 '[class*=":intersect:"]', 15717 '[class^="intersect:"]', 15718 '[class="intersect"]', 15719 '[class*=" intersect "]', 15720 '[class^="intersect "]', 15721 '[class$=" intersect"]' 15722 ]; 15723 15724 const observer = new IntersectionObserver(entries => { 15725 entries.forEach(entry => { 15726 const element = entry.target; 15727 if (!entry.isIntersecting && !this.isInitiallyVisible(element)) { 15728 element.setAttribute('no-intersect', ''); 15729 return; 15730 } 15731 15732 element.removeAttribute('no-intersect'); 15733 15734 if (element.classList.contains('intersect-once')) { 15735 observer.unobserve(element); 15736 } 15737 }); 15738 }); 15739 15740 document.querySelectorAll(selectors.join(',')).forEach(element => { 15741 if (!this.isInitiallyVisible(element)) { 15742 observer.observe(element); 15743 } else { 15744 element.setAttribute('no-intersect', ''); 15745 } 15746 }); 15747 }, 15748 15749 isInitiallyVisible(element) { 15750 const rect = element.getBoundingClientRect(); 15751 15752 return ( 15753 rect.top < (window.innerHeight || document.documentElement.clientHeight) && 15754 rect.bottom > 0 15755 ); 15756 }, 15757 15758 getThreshold(element) { 15759 if (element.classList.contains('intersect-full')) { 15760 return 0.99; 15761 } 15762 15763 if (element.classList.contains('intersect-half')) { 15764 return 0.5; 15765 } 15766 15767 return 0; 15768 }, 15769 }; 15770 15771 TwIntersectObserver.start(); 15772</script>
vendor: 1 bytes, line 15772
15772
15773<script> 15774 document.addEventListener('alpine:init', () => { 15775 Alpine.store('slidersRegistry', {}) 15776 }) 15777</script>
vendor: 1 bytes, line 15777
15777
15778<script> 15779 function setupHeaderObserver() { 15780 let header = document.querySelector('.js-page-header'), navigation = document.querySelector('#header'); 15781 let headerSize = null, navigationSize = null; 15782 15783 function updateSizes() { 15784 if (header.clientHeight !== headerSize) { 15785 headerSize = header.clientHeight; 15786 document.documentElement.style.setProperty('--header-size', headerSize + 'px'); 15787 } 15788 15789 if (navigation.clientHeight !== navigationSize) { 15790 navigationSize = navigation.clientHeight; 15791 document.documentElement.style.setProperty('--navigation-size', navigationSize + 'px'); 15792 } 15793 } 15794 15795 updateSizes(); 15796 15797 if (typeof ResizeObserver === 'function') { 15798 new ResizeObserver(updateSizes).observe(header); 15799 } 15800 15801 function fireEvent(stuck) { 15802 window.dispatchEvent(new CustomEvent("header-sticky-change", {detail: stuck})); 15803 } 15804 15805 const observer = new IntersectionObserver( 15806 ([e]) => fireEvent(e.intersectionRatio < 1), {threshold: [1]} 15807 ); 15808 15809 observer.observe(header); 15810 } 15811</script>
15811 15812
15813<script> 15814 function outdatedBrowserPopup() { 15815 return { 15816 elementId: 'outdated-browser-popup', 15817 closeElement: '[data-close-outdated-browser-popup]', 15818 cookieName: 'outdated_browser_popup', 15819 cookieValue: 'outdated_browser_popup_closed', 15820 cookieLifetime: 86400, 15821 opened: false, 15822 close: function() { 15823 let cookieExpires = this.cookieLifetime / 60 / 60 / 24; 15824 hyva.setCookie(this.cookieName, this.cookieValue, cookieExpires); 15825 this.opened = false; 15826 this.toggle(); 15827 }, 15828 isSupported: function() { 15829 let browser = {}; 15830 let unsupportedBrowsers = {"Chrome":"79","Firefox":"73","IE":"11","Edge":"18","Opera":"58","Safari":"12"}; 15831 15832 browser = (function () { 15833 let userAgent = navigator.userAgent, 15834 browserInfo, 15835 browserMatched = 15836 userAgent.match( 15837 /(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i 15838 ) || []; 15839 15840 if (/trident/i.test(browserMatched[1])) { 15841 browserInfo = /\brv[ :]+(\d+)/g.exec(userAgent) || []; 15842 return {name: "IE", version: browserInfo[1] || ""}; 15843 } 15844 15845 if (/msie/i.test(browserMatched[1])) { 15846 browserMatched[1] = "IE" 15847 } 15848 15849 if (browserMatched[1] === "Chrome") { 15850 browserInfo = userAgent.match(/\b(OPR|Edge)\/(\d+)/); 15851 15852 if (browserInfo) { 15853 return {name: browserInfo[1].replace("OPR", "Opera"), version: browserInfo[2]}; 15854 } 15855 } 15856 15857 if (/ucbrowser/i.test(userAgent)) { 15858 browserInfo = userAgent.match(/\b(UCBrowser)\/(\d+)/i); 15859 15860 if (browserInfo) { 15861 return {name: browserInfo[1], version: browserInfo[2]}; 15862 } 15863 } 15864 15865 if (/miuibrowser/i.test(userAgent)) { 15866 browserInfo = userAgent.match(/\b(MiuiBrowser)\/(\d+)/i); 15867 15868 if (browserInfo) { 15869 return {name: browserInfo[1], version: browserInfo[2]}; 15870 } 15871 } 15872 15873 if (/instagram/i.test(userAgent)) { 15874 return {name: "Instagram", version: 1}; 15875 } 15876 15877 browserMatched = browserMatched[2] ? [browserMatched[1], browserMatched[2]] 15878 : [navigator.appName, navigator.appVersion, "-?"]; 15879 15880 if ((browserInfo = userAgent.match(/version\/(\d+)/i))) { 15881 browserMatched.splice(1, 1, browserInfo[1]); 15882 } 15883 15884 return {name: browserMatched[0], version: browserMatched[1]}; 15885 })(); 15886 15887 return !unsupportedBrowsers[browser.name] || parseInt(browser.version) > parseInt(unsupportedBrowsers[browser.name]); 15888 }, 15889 init: function() { 15890 this.opened = !hyva.getCookie(this.cookieName) && !this.isSupported(); 15891 this.registerListeners(); 15892 this.toggle(); 15893 }, 15894 toggle: function() { 15895 if (this.opened) { 15896 document.getElementById(this.elementId).style.display = 'block'; 15897 } else { 15898 document.getElementById(this.elementId).style.display = 'none'; 15899 } 15900 }, 15901 registerListeners: function() { 15902 var self = this; 15903 var closeElements = document.querySelectorAll(''+this.closeElement+''); 15904 closeElements.forEach(function(element) { 15905 element.addEventListener('click', function() { 15906 self.close(); 15907 }); 15908 }); 15909 } 15910 } 15911 }; 15912 15913 document.addEventListener('DOMContentLoaded', function() { 15914 outdatedBrowserPopup().init(); 15915 }); 15916</script>
15916 15917<style> 15918 @media (min-width: 768px) { 15919 .outdated-browser-popup__zero-widh-space { 15920 vertical-align: middle; 15921 display: inline-block; 15922 height: 100vh; 15923 } 15924 } 15925 15926 @media (min-width: 768px) { 15927 .outdated-browser-popup__content { 15928 margin-top: 2rem; 15929 margin-bottom: 2rem; 15930 max-width: 42rem; 15931 justify-content: center; 15932 padding: 2rem; 15933 } 15934 } 15935 15936 @media (max-width: 768px) { 15937 .outdated-browser-popup__content { 15938 padding-top: 2.5rem; 15939 padding-bottom: 1rem; 15940 padding-left: 1rem; 15941 padding-right: 1rem; 15942 } 15943 } 15944</style> 15945 15946<div id="outdated-browser-popup" style="display:none;" aria-haspopup="true" aria-expanded="true"> 15947 <div style="overflow-y: auto; z-index: 40; top: 0; right: 0; left: 0; bottom: 0; position: fixed;" 15948 aria-labelledby="modal-title" 15949 aria-modal="true"> 15950 <div style="justify-content: center;align-items: center;min-height: 100vh; display: flex;"> 15951 <div data-close-outdated-browser-popup 15952 style="position: fixed;top: 0; bottom: 0; left: 0; right: 0; display: flex; background-color: rgb(22,23,26); opacity: 0.25;" 15953 aria-hidden="true"></div> 15954 15955 <span class="outdated-browser-popup__zero-widh-space" aria-hidden="true">​</span> 15956 15957 <div class="outdated-browser-popup__content" 15958 style="position: absolute; bottom: 0;display: flex; width: 100%; transform: translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); flex-direction: column; overflow: hidden; opacity: 1;background-color: rgb(255,255,255);transition-property: all; transition-timing-function: cubic-bezier(.4,0,.2,1); transition-duration: .15s;" 15959 mcclane-data="outdated-browser-content"> 15960 <button data-close-outdated-browser-popup aria-label="Close panel" 15961 style="position: absolute; top: 0; right: 0; padding: 1rem; color: black; transition: all 150ms ease-in-out;" 15962 mcclane-data="outdated-browser-close"> 15963 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-6 h-6" width="24" height="24" role="img"><path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"/><title>x</title></svg> 15964 </button> 15965 15966<div class="flex flex-col gap-2"> 15967 <div class="flex text-left items-center gap-2"> 15968 <div class="w-5 h-5"> 15969 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="w-full h-full" width="18" height="18" role="img"><path d="M225.9,102.8c-3.8-3.9-7.7-8-9.2-11.5s-1.4-8.7-1.5-14c-.1-9.7-.3-20.8-8-28.5s-18.8-7.9-28.5-8c-5.3-.1-10.7-.2-14-1.5s-7.6-5.4-11.5-9.2C146.3,23.5,138.4,16,128,16s-18.3,7.5-25.2,14.1c-3.9,3.8-8,7.7-11.5,9.2s-8.7,1.4-14,1.5c-9.7.1-20.8.3-28.5,8s-7.9,18.8-8,28.5c-.1,5.3-.2,10.7-1.5,14s-5.4,7.6-9.2,11.5C23.5,109.7,16,117.6,16,128s7.5,18.3,14.1,25.2c3.8,3.9,7.7,8,9.2,11.5s1.4,8.7,1.5,14c.1,9.7.3,20.8,8,28.5s18.8,7.9,28.5,8c5.3.1,10.7.2,14,1.5s7.6,5.4,11.5,9.2c6.9,6.6,14.8,14.1,25.2,14.1s18.3-7.5,25.2-14.1c3.9-3.8,8-7.7,11.5-9.2s8.7-1.4,14-1.5c9.7-.1,20.8-.3,28.5-8s7.9-18.8,8-28.5c.1-5.3.2-10.7,1.5-14s5.4-7.6,9.2-11.5c6.6-6.9,14.1-14.8,14.1-25.2S232.5,109.7,225.9,102.8Zm-11.6,39.3c-4.8,5-9.7,10.2-12.4,16.5s-2.6,13.1-2.7,19.8-.2,14.4-3.3,17.5-10.4,3.2-17.5,3.3-13.7.2-19.8,2.7-11.5,7.6-16.5,12.4S132,224,128,224s-9.1-4.9-14.1-9.7-10.2-9.7-16.5-12.4-13.1-2.6-19.8-2.7-14.4-.2-17.5-3.3-3.2-10.4-3.3-17.5-.2-13.7-2.7-19.8-7.6-11.5-12.4-16.5S32,132,32,128s4.9-9.1,9.7-14.1,9.7-10.2,12.4-16.5,2.6-13.1,2.7-19.8.2-14.4,3.3-17.5,10.4-3.2,17.5-3.3,13.7-.2,19.8-2.7,11.5-7.6,16.5-12.4S124,32,128,32s9.1,4.9,14.1,9.7,10.2,9.7,16.5,12.4,13.1,2.6,19.8,2.7,14.4.2,17.5,3.3,3.2,10.4,3.3,17.5.2,13.7,2.7,19.8,7.6,11.5,12.4,16.5S224,124,224,128,219.1,137.1,214.3,142.1ZM120,136V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z"/><title>circle-wavy-warning</title></svg> 15970 </div> 15971 <div class="text-sm italic text-gray-500"> 15972 </div> 15973 </div> 15974 <div class="flex flex-col gap-1 md:gap-2 w-full"> 15975 <div class="font-primary text-2xl md:text-4xl font-bold"> 15976 <p>
15976Actualice su navegador</p> 15977 </div 15978 <div class="font-primary text-md font-light"> 15979 <p>Esta versión del navegador es muy antigua, por lo que es posible que el contenido de este sitio web no se muestre correctamente.</p> 15980 </div> 15981 </div> 15982</div> 15983 </div> 15984 </div> 15985 </div> 15986</div> 15987
15988<script type="text/json" id="default-section-data"> 15989 {"messages":[],"customer":[],"compare-products":[],"last-ordered-items":[],"cart":[],"directory-data":{"AT":{"name":"Austria","regions":{"102":{"code":"BL","name":"Burgenland"},"99":{"code":"KN","name":"K\u00e4rnten"},"96":{"code":"NO","name":"Nieder\u00f6sterreich"},"97":{"code":"OO","name":"Ober\u00f6sterreich"},"98":{"code":"SB","name":"Salzburg"},"100":{"code":"ST","name":"Steiermark"},"101":{"code":"TI","name":"Tirol"},"103":{"code":"VB","name":"Vorarlberg"},"95":{"code":"WI","name":"Wien"}}},"BA":{"name":"Bosnia y Herzegovina"},"BE":{"name":"B\u00e9lgica","regions":{"620":{"code":"VAN","name":"Antwerpen"},"621":{"code":"WBR","name":"Brabant wallon"},"622":{"code":"BRU","name":"Brussels-Capital Region"},"623":{"code":"WHT","name":"Hainaut"},"625":{"code":"WLG","name":"Li\u00e8ge"},"624":{"code":"VLI","name":"Limburg"},"626":{"code":"WLX","name":"Luxembourg"},"627":{"code":"WNA","name":"Namur"},"628":{"code":"VOV","name":"Oost-Vlaanderen"},"629":{"code":"VBR","name":"Vlaams-Brabant"},"630":{"code":"VWV","name":"West-Vlaanderen"}}},"BG":{"name":"Bulgaria","regions":{"640":{"code":"BG-01","name":"Blagoevgrad"},"641":{"code":"BG-02","name":"Burgas"},"647":{"code":"BG-08","name":"Dobrich"},"646":{"code":"BG-07","name":"Gabrovo"},"665":{"code":"BG-26","name":"Haskovo"},"648":{"code":"BG-09","name":"Kardzhali"},"649":{"code":"BG-10","name":"Kyustendil"},"650":{"code":"BG-11","name":"Lovech"},"651":{"code":"BG-12","name":"Montana"},"652":{"code":"BG-13","name":"Pazardzhik"},"653":{"code":"BG-14","name":"Pernik"},"654":{"code":"BG-15","name":"Pleven"},"655":{"code":"BG-16","name":"Plovdiv"},"656":{"code":"BG-17","name":"Razgrad"},"657":{"code":"BG-18","name":"Ruse"},"666":{"code":"BG-27","name":"Shumen"},"658":{"code":"BG-19","name":"Silistra"},"659":{"code":"BG-20","name":"Sliven"},"660":{"code":"BG-21","name":"Smolyan"},"661":{"code":"BG-22","name":"Sofia City"},"662":{"code":"BG-23","name":"Sofia Province"},"663":{"code":"BG-24","name":"Stara Zagora"},"664":{"code":"BG-25","name":"Targovishte"},"642":{"code":"BG-03","name":"Varna"},"643":{"code":"BG-04","name":"Veliko Tarnovo"},"644":{"code":"BG-05","name":"Vidin"},"645":{"code":"BG-06","name":"Vratsa"},"667":{"code":"BG-28","name":"Yambol"}}},"CZ":{"name":"Chequia","regions":{"1373":{"code":"CZ-31","name":"Jiho\u010desk\u00fd kraj"},"1381":{"code":"CZ-64","name":"Jihomoravsk\u00fd kraj"},"1375":{"code":"CZ-41","name":"Karlovarsk\u00fd kraj"},"1380":{"code":"CZ-63","name":"Kraj Vyso\u010dina"},"1378":{"code":"CZ-52","name":"Kr\u00e1lov\u00e9hradeck\u00fd kraj"},"1377":{"code":"CZ-51","name":"Libereck\u00fd kraj"},"1384":{"code":"CZ-80","name":"Moravskoslezsk\u00fd kraj"},"1382":{"code":"CZ-71","name":"Olomouck\u00fd kraj"},"1379":{"code":"CZ-53","name":"Pardubick\u00fd kraj"},"1374":{"code":"CZ-32","name":"Plze\u0148sk\u00fd kraj"},"1371":{"code":"CZ-10","name":"Praha, Hlavn\u00ed m\u011bsto"},"1372":{"code":"CZ-20","name":"St\u0159edo\u010desk\u00fd kraj"},"1376":{"code":"CZ-42","name":"\u00dasteck\u00fd kraj"},"1383":{"code":"CZ-72","name":"Zl\u00ednsk\u00fd kraj"}}},"DE":{"name":"Alemania","regions":{"80":{"code":"BAW","name":"Baden-W\u00fcrttemberg"},"81":{"code":"BAY","name":"Bayern"},"82":{"code":"BER","name":"Berlin"},"83":{"code":"BRG","name":"Brandenburg"},"84":{"code":"BRE","name":"Bremen"},"85":{"code":"HAM","name":"Hamburg"},"86":{"code":"HES","name":"Hessen"},"87":{"code":"MEC","name":"Mecklenburg-Vorpommern"},"79":{"code":"NDS","name":"Niedersachsen"},"88":{"code":"NRW","name":"Nordrhein-Westfalen"},"89":{"code":"RHE","name":"Rheinland-Pfalz"},"90":{"code":"SAR","name":"Saarland"},"91":{"code":"SAS","name":"Sachsen"},"92":{"code":"SAC","name":"Sachsen-Anhalt"},"93":{"code":"SCN","name":"Schleswig-Holstein"},"94":{"code":"THE","name":"Th\u00fcringen"}}},"DK":{"name":"Dinamarca","regions":{"750":{"code":"DK-84","name":"Hovedstaden"},"751":{"code":"DK-82","name":"Midtjylland"},"752":{"code":"DK-81","name":"Nordjylland"},"753":{"code":"DK-85","name":"Sj\u00e6lland"},"754":{"code":"DK-83","name":"Syddanmark"}}},"EE":{"name":"Estonia","regions":{"340":{"code":"EE-37","name":"Harjumaa"},"341":{"code":"EE-39","name":"Hiiumaa"},"342":{"code":"EE-44","name":"Ida-Virumaa"}
15989,"344":{"code":"EE-51","name":"J\u00e4rvamaa"},"343":{"code":"EE-49","name":"J\u00f5gevamaa"},"346":{"code":"EE-59","name":"L\u00e4\u00e4ne-Virumaa"},"345":{"code":"EE-57","name":"L\u00e4\u00e4nemaa"},"348":{"code":"EE-67","name":"P\u00e4rnumaa"},"347":{"code":"EE-65","name":"P\u00f5lvamaa"},"349":{"code":"EE-70","name":"Raplamaa"},"350":{"code":"EE-74","name":"Saaremaa"},"351":{"code":"EE-78","name":"Tartumaa"},"352":{"code":"EE-82","name":"Valgamaa"},"353":{"code":"EE-84","name":"Viljandimaa"},"354":{"code":"EE-86","name":"V\u00f5rumaa"}}},"ES":{"name":"Espa\u00f1a","regions":{"130":{"code":"A Coru\u0441a","name":"A Coru\u00f1a"},"131":{"code":"Alava","name":"\u00c1lava"},"132":{"code":"Albacete","name":"Albacete"},"133":{"code":"Alicante","name":"Alicante"},"134":{"code":"Almeria","name":"Almer\u00eda"},"135":{"code":"Asturias","name":"Asturias"},"136":{"code":"Avila","name":"\u00c1vila"},"137":{"code":"Badajoz","name":"Badajoz"},"138":{"code":"Baleares","name":"Baleares"},"139":{"code":"Barcelona","name":"Barcelona"},"140":{"code":"Burgos","name":"Burgos"},"141":{"code":"Caceres","name":"C\u00e1ceres"},"142":{"code":"Cadiz","name":"C\u00e1diz"},"143":{"code":"Cantabria","name":"Cantabria"},"144":{"code":"Castellon","name":"Castell\u00f3n"},"145":{"code":"Ceuta","name":"Ceuta"},"146":{"code":"Ciudad Real","name":"Ciudad Real"},"147":{"code":"Cordoba","name":"C\u00f3rdoba"},"148":{"code":"Cuenca","name":"Cuenca"},"149":{"code":"Girona","name":"Girona"},"150":{"code":"Granada","name":"Granada"},"151":{"code":"Guadalajara","name":"Guadalajara"},"152":{"code":"Guipuzcoa","name":"Guip\u00fazcoa"},"153":{"code":"Huelva","name":"Huelva"},"154":{"code":"Huesca","name":"Huesca"},"155":{"code":"Jaen","name":"Ja\u00e9n"},"156":{"code":"La Rioja","name":"La Rioja"},"158":{"code":"Leon","name":"Le\u00f3n"},"159":{"code":"Lleida","name":"Lleida"},"160":{"code":"Lugo","name":"Lugo"},"161":{"code":"Madrid","name":"Madrid"},"162":{"code":"Malaga","name":"M\u00e1laga"},"163":{"code":"Melilla","name":"Melilla"},"164":{"code":"Murcia","name":"Murcia"},"165":{"code":"Navarra","name":"Navarra"},"166":{"code":"Ourense","name":"Ourense"},"167":{"code":"Palencia","name":"Palencia"},"168":{"code":"Pontevedra","name":"Pontevedra"},"169":{"code":"Salamanca","name":"Salamanca"},"171":{"code":"Segovia","name":"Segovia"},"172":{"code":"Sevilla","name":"Sevilla"},"173":{"code":"Soria","name":"Soria"},"174":{"code":"Tarragona","name":"Tarragona"},"175":{"code":"Teruel","name":"Teruel"},"176":{"code":"Toledo","name":"Toledo"},"177":{"code":"Valencia","name":"Valencia"},"178":{"code":"Valladolid","name":"Valladolid"},"179":{"code":"Vizcaya","name":"Vizcaya"},"180":{"code":"Zamora","name":"Zamora"},"181":{"code":"Zaragoza","name":"Zaragoza"}}},"FI":{"name":"Finlandia","regions":{"339":{"code":"Ahvenanmaa","name":"Ahvenanmaa"},"333":{"code":"Etel\u00e4-Karjala","name":"Etel\u00e4-Karjala"},"326":{"code":"Etel\u00e4-Pohjanmaa","name":"Etel\u00e4-Pohjanmaa"},"325":{"code":"Etel\u00e4-Savo","name":"Etel\u00e4-Savo"},"337":{"code":"It\u00e4-Uusimaa","name":"It\u00e4-Uusimaa"},"322":{"code":"Kainuu","name":"Kainuu"},"335":{"code":"Kanta-H\u00e4me","name":"Kanta-H\u00e4me"},"330":{"code":"Keski-Pohjanmaa","name":"Keski-Pohjanmaa"},"331":{"code":"Keski-Suomi","name":"Keski-Suomi"},"338":{"code":"Kymenlaakso","name":"Kymenlaakso"},"320":{"code":"Lappi","name":"Lappi"},"334":{"code":"P\u00e4ij\u00e4t-H\u00e4me","name":"P\u00e4ij\u00e4t-H\u00e4me"},"328":{"code":"Pirkanmaa","name":"Pirkanmaa"},"327":{"code":"Pohjanmaa","name":"Pohjanmaa"},"323":{"code":"Pohjois-Karjala","name":"Pohjois-Karjala"},"321":{"code":"Pohjois-Pohjanmaa","name":"Pohjois-Pohjanmaa"},"324":{"code":"Pohjois-Savo","name":"Pohjois-Savo"},"329":{"code":"Satakunta","name":"Satakunta"},"336":{"code":"Uusimaa","name":"Uusimaa"},"332":{"code":"Varsinais-Suomi","name":"Varsinais-Suomi"}}},"FR":{"name":"Francia","regions":{"182":{"code":"1","name":"Ain"},"183":{"code":"2","name":"Aisne"},"184":{"code":"3","name":"Allier"},"185":{"code":"4","name":"Alpes-de-Haute-Provence"}
15989,"187":{"code":"6","name":"Alpes-Maritimes"},"188":{"code":"7","name":"Ard\u00e8che"},"189":{"code":"8","name":"Ardennes"},"190":{"code":"9","name":"Ari\u00e8ge"},"191":{"code":"10","name":"Aube"},"192":{"code":"11","name":"Aude"},"193":{"code":"12","name":"Aveyron"},"249":{"code":"67","name":"Bas-Rhin"},"194":{"code":"13","name":"Bouches-du-Rh\u00f4ne"},"195":{"code":"14","name":"Calvados"},"196":{"code":"15","name":"Cantal"},"197":{"code":"16","name":"Charente"},"198":{"code":"17","name":"Charente-Maritime"},"199":{"code":"18","name":"Cher"},"200":{"code":"19","name":"Corr\u00e8ze"},"201":{"code":"2A","name":"Corse-du-Sud"},"203":{"code":"21","name":"C\u00f4te-d'Or"},"204":{"code":"22","name":"C\u00f4tes-d'Armor"},"205":{"code":"23","name":"Creuse"},"261":{"code":"79","name":"Deux-S\u00e8vres"},"206":{"code":"24","name":"Dordogne"},"207":{"code":"25","name":"Doubs"},"208":{"code":"26","name":"Dr\u00f4me"},"273":{"code":"91","name":"Essonne"},"209":{"code":"27","name":"Eure"},"210":{"code":"28","name":"Eure-et-Loir"},"211":{"code":"29","name":"Finist\u00e8re"},"212":{"code":"30","name":"Gard"},"214":{"code":"32","name":"Gers"},"215":{"code":"33","name":"Gironde"},"250":{"code":"68","name":"Haut-Rhin"},"202":{"code":"2B","name":"Haute-Corse"},"213":{"code":"31","name":"Haute-Garonne"},"225":{"code":"43","name":"Haute-Loire"},"234":{"code":"52","name":"Haute-Marne"},"252":{"code":"70","name":"Haute-Sa\u00f4ne"},"256":{"code":"74","name":"Haute-Savoie"},"269":{"code":"87","name":"Haute-Vienne"},"186":{"code":"5","name":"Hautes-Alpes"},"247":{"code":"65","name":"Hautes-Pyr\u00e9n\u00e9es"},"274":{"code":"92","name":"Hauts-de-Seine"},"216":{"code":"34","name":"H\u00e9rault"},"217":{"code":"35","name":"Ille-et-Vilaine"},"218":{"code":"36","name":"Indre"},"219":{"code":"37","name":"Indre-et-Loire"},"220":{"code":"38","name":"Is\u00e8re"},"221":{"code":"39","name":"Jura"},"222":{"code":"40","name":"Landes"},"223":{"code":"41","name":"Loir-et-Cher"},"224":{"code":"42","name":"Loire"},"226":{"code":"44","name":"Loire-Atlantique"},"227":{"code":"45","name":"Loiret"},"228":{"code":"46","name":"Lot"},"229":{"code":"47","name":"Lot-et-Garonne"},"230":{"code":"48","name":"Loz\u00e8re"},"231":{"code":"49","name":"Maine-et-Loire"},"232":{"code":"50","name":"Manche"},"233":{"code":"51","name":"Marne"},"235":{"code":"53","name":"Mayenne"},"236":{"code":"54","name":"Meurthe-et-Moselle"},"237":{"code":"55","name":"Meuse"},"238":{"code":"56","name":"Morbihan"},"239":{"code":"57","name":"Moselle"},"240":{"code":"58","name":"Ni\u00e8vre"},"241":{"code":"59","name":"Nord"},"242":{"code":"60","name":"Oise"},"243":{"code":"61","name":"Orne"},"257":{"code":"75","name":"Paris"},"244":{"code":"62","name":"Pas-de-Calais"},"245":{"code":"63","name":"Puy-de-D\u00f4me"},"246":{"code":"64","name":"Pyr\u00e9n\u00e9es-Atlantiques"},"248":{"code":"66","name":"Pyr\u00e9n\u00e9es-Orientales"},"251":{"code":"69","name":"Rh\u00f4ne"},"253":{"code":"71","name":"Sa\u00f4ne-et-Loire"},"254":{"code":"72","name":"Sarthe"},"255":{"code":"73","name":"Savoie"},"259":{"code":"77","name":"Seine-et-Marne"},"258":{"code":"76","name":"Seine-Maritime"},"275":{"code":"93","name":"Seine-Saint-Denis"},"262":{"code":"80","name":"Somme"},"263":{"code":"81","name":"Tarn"},"264":{"code":"82","name":"Tarn-et-Garonne"},"272":{"code":"90","name":"Territoire-de-Belfort"},"277":{"code":"95","name":"Val-d'Oise"},"276":{"code":"94","name":"Val-de-Marne"},"265":{"code":"83","name":"Var"},"266":{"code":"84","name":"Vaucluse"},"267":{"code":"85","name":"Vend\u00e9e"},"268":{"code":"86","name":"Vienne"},"270":{"code":"88","name":"Vosges"},"271":{"code":"89","name":"Yonne"},"260":{"code":"78","name":"Yvelines"}}},"GR":{"name":"Grecia","regions":{"792":{"code":"GR-69","name":"\u00c1gion \u00d3ros"},"779":{"code":"GR-A","name":"Anatolik\u00ed Makedon\u00eda kai Thr\u00e1ki"},"780":{"code":"GR-I","name":"Attik\u00ed"},"781":{"code":"GR-G","name":"Dytik\u00ed Ell\u00e1da"},"782":{"code":"GR-C","name":"Dytik\u00ed Makedon\u00eda"},"783":{"code":"GR-F","name":"Ion\u00eda N\u00edsia"},"784":{"code":"GR-D","name":"\u00cdpeiros"},"785":{"code":"GR-B","name":"Kentrik\u00ed Makedon\u00eda"},"786":{"code":"GR-M","name":"Kr\u00edti"},"787":{"code":"GR-L","name":"N\u00f3tio Aiga\u00edo"},"788":{"code":"GR-J","name":"Pelop\u00f3nnisos"},"789":{"code":"GR-H","name":"Stere\u00e1 Ell\u00e1da"}
15989,"790":{"code":"GR-E","name":"Thessal\u00eda"},"791":{"code":"GR-K","name":"V\u00f3reio Aiga\u00edo"}}},"HR":{"name":"Croacia","regions":{"554":{"code":"HR-07","name":"Bjelovarsko-bilogorska \u017eupanija"},"559":{"code":"HR-12","name":"Brodsko-posavska \u017eupanija"},"566":{"code":"HR-19","name":"Dubrova\u010dko-neretvanska \u017eupanija"},"568":{"code":"HR-21","name":"Grad Zagreb"},"565":{"code":"HR-18","name":"Istarska \u017eupanija"},"551":{"code":"HR-04","name":"Karlova\u010dka \u017eupanija"},"553":{"code":"HR-06","name":"Koprivni\u010dko-kri\u017eeva\u010dka \u017eupanija"},"549":{"code":"HR-02","name":"Krapinsko-zagorska \u017eupanija"},"556":{"code":"HR-09","name":"Li\u010dko-senjska \u017eupanija"},"567":{"code":"HR-20","name":"Me\u0111imurska \u017eupanija"},"561":{"code":"HR-14","name":"Osje\u010dko-baranjska \u017eupanija"},"558":{"code":"HR-11","name":"Po\u017ee\u0161ko-slavonska \u017eupanija"},"555":{"code":"HR-08","name":"Primorsko-goranska \u017eupanija"},"562":{"code":"HR-15","name":"\u0160ibensko-kninska \u017eupanija"},"550":{"code":"HR-03","name":"Sisa\u010dko-moslava\u010dka \u017eupanija"},"564":{"code":"HR-17","name":"Splitsko-dalmatinska \u017eupanija"},"552":{"code":"HR-05","name":"Vara\u017edinska \u017eupanija"},"557":{"code":"HR-10","name":"Viroviti\u010dko-podravska \u017eupanija"},"563":{"code":"HR-16","name":"Vukovarsko-srijemska \u017eupanija"},"560":{"code":"HR-13","name":"Zadarska \u017eupanija"},"548":{"code":"HR-01","name":"Zagreba\u010dka \u017eupanija"}}},"HU":{"name":"Hungr\u00eda"},"IE":{"name":"Irlanda","regions":{"1325":{"code":"IE-CW","name":"Carlow"},"1326":{"code":"IE-CN","name":"Cavan"},"1327":{"code":"IE-CE","name":"Clare"},"1328":{"code":"IE-CO","name":"Cork"},"1329":{"code":"IE-DL","name":"Donegal"},"1330":{"code":"IE-D","name":"Dublin"},"1331":{"code":"IE-G","name":"Galway"},"1332":{"code":"IE-KY","name":"Kerry"},"1333":{"code":"IE-KE","name":"Kildare"},"1334":{"code":"IE-KK","name":"Kilkenny"},"1335":{"code":"IE-LS","name":"Laois"},"1336":{"code":"IE-LM","name":"Leitrim"},"1337":{"code":"IE-LK","name":"Limerick"},"1338":{"code":"IE-LD","name":"Longford"},"1339":{"code":"IE-LH","name":"Louth"},"1340":{"code":"IE-MO","name":"Mayo"},"1341":{"code":"IE-MH","name":"Meath"},"1342":{"code":"IE-MN","name":"Monaghan"},"1343":{"code":"IE-OY","name":"Offaly"},"1344":{"code":"IE-RN","name":"Roscommon"},"1345":{"code":"IE-SO","name":"Sligo"},"1346":{"code":"IE-TA","name":"Tipperary"},"1347":{"code":"IE-WD","name":"Waterford"},"1348":{"code":"IE-WH","name":"Westmeath"},"1349":{"code":"IE-WX","name":"Wexford"},"1350":{"code":"IE-WW","name":"Wicklow"}}},"IT":{"name":"Italia","regions":{"811":{"code":"AG","name":"Agrigento"},"812":{"code":"AL","name":"Alessandria"},"813":{"code":"AN","name":"Ancona"},"814":{"code":"AO","name":"Aosta"},"816":{"code":"AR","name":"Arezzo"},"817":{"code":"AP","name":"Ascoli-Piceno"},"818":{"code":"AT","name":"Asti"},"819":{"code":"AV","name":"Avellino"},"820":{"code":"BA","name":"Bari"},"821":{"code":"BT","name":"Barletta-Andria-Trani"},"822":{"code":"BL","name":"Belluno"},"823":{"code":"BN","name":"Benevento"},"824":{"code":"BG","name":"Bergamo"},"825":{"code":"BI","name":"Biella"},"826":{"code":"BO","name":"Bologna"},"827":{"code":"BZ","name":"Bolzano"},"828":{"code":"BS","name":"Brescia"},"829":{"code":"BR","name":"Brindisi"},"830":{"code":"CA","name":"Cagliari"},"831":{"code":"CL","name":"Caltanissetta"},"832":{"code":"CB","name":"Campobasso"},"833":{"code":"CI","name":"Carbonia Iglesias"},"834":{"code":"CE","name":"Caserta"},"835":{"code":"CT","name":"Catania"},"836":{"code":"CZ","name":"Catanzaro"},"837":{"code":"CH","name":"Chieti"},"838":{"code":"CO","name":"Como"},"839":{"code":"CS","name":"Cosenza"},"840":{"code":"CR","name":"Cremona"},"841":{"code":"KR","name":"Crotone"},"842":{"code":"CN","name":"Cuneo"},"843":{"code":"EN","name":"Enna"},"844":{"code":"FM","name":"Fermo"},"845":{"code":"FE","name":"Ferrara"},"846":{"code":"FI","name":"Firenze"},"847":{"code":"FG","name":"Foggia"},"848":{"code":"FC","name":"Forli-Cesena"},"849":{"code":"FR","name":"Frosinone"},"850":{"code":"GE","name":"Genova"},"851":{"code":"GO","name":"Gorizia"},"852":{"code":"GR","name":"Grosseto"},"853":{"code":"IM","name":"Imperia"},"854":{"code":"IS","name":"Isernia"},"815":{"code":"AQ","name":"L'Aquila"},"855":{"code":"SP","name":"La-Spezia"},"856":{"code":"LT","name":"Latina"},"857":{"code":"LE","name":"Lecce"},"858":{"code":"LC","name":"Lecco"},"859":{"code":"LI","name":"Livorno"},"860":{"code":"LO","name":"Lodi"},"861":{"code":"LU","name":"Lucca"},"862":{"code":"MC","name":"Macerata"},"863":{"code":"MN","name":"Mantova"},"864":{"code":"MS","name":"Massa-Carrara"},"865":{"code":"MT","name":"Matera"},"866":{"code":"VS","name":"Medio Campidano"},"867":{"code":"ME","name":"Messina"},"868":{"code":"MI","name":"Milano"},"869":{"code":"MO","name":"Modena"},"870":{"code":"MB","name":"Monza-Brianza"},"871":{"code":"NA","name":"Napoli"},"872":{"code":"NO","name":"Novara"},"873":{"code":"NU","name":"Nuoro"},"874":{"code":"OG","name":"Ogliastra"},"875":{"code":"OT","name":"Olbia Tempio"},"876":{"code":"OR","name":"Oristano"},"877":{"code":"PD","name":"Padova"},"878":{"code":"PA","name":"Palermo"},"879":{"code":"PR","name":"Parma"},"880":{"code":"PV","name":"Pavia"},"881":{"code":"PG","name":"Perugia"},"882":{"code":"PU","name":"Pesaro-Urbino"},"883":{"code":"PE","name":"Pescara"},"884":{"code":"PC","name":"Piacenza"},"885":{"code":"PI","name":"Pisa"},"886":{"code":"PT","name":"Pistoia"},"887":{"code":"PN","name":"Pordenone"},"888":{"code":"PZ","name":"Potenza"},"889":{"code":"PO","name":"Prato"},"890":{"code":"RG","name":"Ragusa"},"891":{"code":"RA","name":"Ravenna"},"892":{"code":"RC","name":"Reggio-Calabria"},"893":{"code":"RE","name":"Reggio-Emilia"},"894":{"code":"RI","name":"Rieti"},"895":{"code":"RN","name":"Rimini"},"896":{"code":"RM","name":"Roma"},"897":{"code":"RO","name":"Rovigo"},"898":{"code":"SA","name":"Salerno"},"899":{"code":"SS","name":"Sassari"},"900":{"code":"SV","name":"Savona"},"901":{"code":"SI","name":"Siena"},"902":{"code":"SR","name":"Siracusa"},"903":{"code":"SO","name":"Sondrio"},"904":{"code":"TA","name":"Taranto"},"905":{"code":"TE","name":"Teramo"},"906":{"code":"TR","name":"Terni"},"907":{"code":"TO","name":"Torino"},"908":{"code":"TP","name":"Trapani"},"909":{"code":"TN","name":"Trento"},"910":{"code":"TV","name":"Treviso"},"911":{"code":"TS","name":"Trieste"},"912":{"code":"UD","name":"Udine"},"913":{"code":"VA","name":"Varese"},"914":{"code":"VE","name":"Venezia"},"915":{"code":"VB","name":"Verbania"},"916":{"code":"VC","name":"Vercelli"},"917":{"code":"VR","name":"Verona"}
15989,"918":{"code":"VV","name":"Vibo-Valentia"},"919":{"code":"VI","name":"Vicenza"},"920":{"code":"VT","name":"Viterbo"}}},"LT":{"name":"Lituania","regions":{"475":{"code":"LT-AL","name":"Alytaus Apskritis"},"476":{"code":"LT-KU","name":"Kauno Apskritis"},"477":{"code":"LT-KL","name":"Klaip\u0117dos Apskritis"},"478":{"code":"LT-MR","name":"Marijampol\u0117s Apskritis"},"479":{"code":"LT-PN","name":"Panev\u0117\u017eio Apskritis"},"480":{"code":"LT-SA","name":"\u0160iauli\u0173 Apskritis"},"481":{"code":"LT-TA","name":"Taurag\u0117s Apskritis"},"482":{"code":"LT-TE","name":"Tel\u0161i\u0173 Apskritis"},"483":{"code":"LT-UT","name":"Utenos Apskritis"},"484":{"code":"LT-VL","name":"Vilniaus Apskritis"}}},"LU":{"name":"Luxemburgo"},"LV":{"name":"Letonia","regions":{"471":{"code":"\u0100da\u017eu novads","name":"\u0100da\u017eu novads"},"366":{"code":"Aglonas novads","name":"Aglonas novads"},"367":{"code":"LV-AI","name":"Aizkraukles novads"},"368":{"code":"Aizputes novads","name":"Aizputes novads"},"369":{"code":"Akn\u012bstes novads","name":"Akn\u012bstes novads"},"370":{"code":"Alojas novads","name":"Alojas novads"},"371":{"code":"Alsungas novads","name":"Alsungas novads"},"372":{"code":"LV-AL","name":"Al\u016bksnes novads"},"373":{"code":"Amatas novads","name":"Amatas novads"},"374":{"code":"Apes novads","name":"Apes novads"},"375":{"code":"Auces novads","name":"Auces novads"},"376":{"code":"Bab\u012btes novads","name":"Bab\u012btes novads"},"377":{"code":"Baldones novads","name":"Baldones novads"},"378":{"code":"Baltinavas novads","name":"Baltinavas novads"},"379":{"code":"LV-BL","name":"Balvu novads"},"380":{"code":"LV-BU","name":"Bauskas novads"},"381":{"code":"Bever\u012bnas novads","name":"Bever\u012bnas novads"},"382":{"code":"Broc\u0113nu novads","name":"Broc\u0113nu novads"},"383":{"code":"Burtnieku novads","name":"Burtnieku novads"},"384":{"code":"Carnikavas novads","name":"Carnikavas novads"},"387":{"code":"LV-CE","name":"C\u0113su novads"},"385":{"code":"Cesvaines novads","name":"Cesvaines novads"},"386":{"code":"Ciblas novads","name":"Ciblas novads"},"388":{"code":"Dagdas novads","name":"Dagdas novads"},"355":{"code":"LV-DGV","name":"Daugavpils"},"389":{"code":"LV-DA","name":"Daugavpils novads"},"390":{"code":"LV-DO","name":"Dobeles novads"},"391":{"code":"Dundagas novads","name":"Dundagas novads"},"392":{"code":"Durbes novads","name":"Durbes novads"},"393":{"code":"Engures novads","name":"Engures novads"},"472":{"code":"\u0112rg\u013cu novads","name":"\u0112rg\u013cu novads"},"394":{"code":"Garkalnes novads","name":"Garkalnes novads"},"395":{"code":"Grobi\u0146as novads","name":"Grobi\u0146as novads"},"396":{"code":"LV-GU","name":"Gulbenes novads"},"397":{"code":"Iecavas novads","name":"Iecavas novads"},"398":{"code":"Ik\u0161\u0137iles novads","name":"Ik\u0161\u0137iles novads"},"399":{"code":"Il\u016bkstes novads","name":"Il\u016bkstes novads"},"400":{"code":"In\u010dukalna novads","name":"In\u010dukalna novads"},"401":{"code":"Jaunjelgavas novads","name":"Jaunjelgavas novads"},"402":{"code":"Jaunpiebalgas novads","name":"Jaunpiebalgas novads"},"403":{"code":"Jaunpils novads","name":"Jaunpils novads"},"357":{"code":"J\u0113kabpils","name":"J\u0113kabpils"},"405":{"code":"LV-JK","name":"J\u0113kabpils novads"},"356":{"code":"LV-JEL","name":"Jelgava"},"404":{"code":"LV-JL","name":"Jelgavas novads"},"358":{"code":"LV-JUR","name":"J\u016brmala"},"406":{"code":"Kandavas novads","name":"Kandavas novads"},"412":{"code":"K\u0101rsavas novads","name":"K\u0101rsavas novads"},"473":{"code":"\u0136eguma novads","name":"\u0136eguma novads"},"474":{"code":"\u0136ekavas novads","name":"\u0136ekavas novads"},"407":{"code":"Kokneses novads","name":"Kokneses novads"},"410":{"code":"LV-KR","name":"Kr\u0101slavas novads"},"408":{"code":"Krimuldas novads","name":"Krimuldas novads"},"409":{"code":"Krustpils novads","name":"Krustpils novads"},"411":{"code":"LV-KU","name":"Kuld\u012bgas novads"},"413":{"code":"Lielv\u0101rdes novads","name":"Lielv\u0101rdes novads"},"359":{"code":"LV-LPX","name":"Liep\u0101ja"},"360":{"code":"LV-LE","name":"Liep\u0101jas novads"},"417":{"code":"L\u012bgatnes novads","name":"L\u012bgatnes novads"},"414":{"code":"LV-LM","name":"Limba\u017eu novads"},"418":{"code":"L\u012bv\u0101nu novads","name":"L\u012bv\u0101nu novads"},"415":{"code":"Lub\u0101nas novads","name":"Lub\u0101nas novads"},"416":{"code":"LV-LU","name":"Ludzas novads"},"419":{"code":"LV-MA","name":"Madonas novads"},"421":{"code":"M\u0101lpils novads","name":"M\u0101lpils novads"},"422":{"code":"M\u0101rupes novads","name":"M\u0101rupes novads"},"420":{"code":"Mazsalacas novads","name":"Mazsalacas novads"},"423":{"code":"Nauk\u0161\u0113nu novads","name":"Nauk\u0161\u0113nu novads"},"424":{"code":"Neretas novads","name":"Neretas novads"},"425":{"code":"N\u012bcas novads","name":"N\u012bcas novads"},"426":{"code":"LV-OG","name":"Ogres novads"},"427":{"code":"Olaines novads","name":"Olaines novads"},"428":{"code":"Ozolnieku novads","name":"Ozolnieku novads"},"432":{"code":"P\u0101rgaujas novads","name":"P\u0101rgaujas novads"},"433":{"code":"P\u0101vilostas novads","name":"P\u0101vilostas novads"},"434":{"code":"P\u013cavi\u0146u novads","name":"P\u013cavi\u0146u novads"},"429":{"code":"LV-PR","name":"Prei\u013cu novads"},"430":{"code":"Priekules novads","name":"Priekules novads"},"431":{"code":"Prieku\u013cu novads","name":"Prieku\u013cu novads"},"435":{"code":"Raunas novads","name":"Raunas novads"},"361":{"code":"LV-REZ","name":"R\u0113zekne"},"442":{"code":"LV-RE","name":"R\u0113zeknes novads"},"436":{"code":"Riebi\u0146u novads","name":"Riebi\u0146u novads"},"362":{"code":"LV-RIX","name":"R\u012bga"},"363":{"code":"LV-RI","name":"R\u012bgas novads"},"437":{"code":"Rojas novads","name":"Rojas novads"},"438":{"code":"Ropa\u017eu novads","name":"Ropa\u017eu novads"},"439":{"code":"Rucavas novads","name":"Rucavas novads"},"440":{"code":"Rug\u0101ju novads","name":"Rug\u0101ju novads"},"443":{"code":"R\u016bjienas novads","name":"R\u016bjienas novads"},"441":{"code":"Rund\u0101les novads","name":"Rund\u0101les novads"},"444":{"code":"Salacgr\u012bvas novads","name":"Salacgr\u012bvas novads"},"445":{"code":"Salas novads","name":"Salas novads"},"446":{"code":"Salaspils novads","name":"Salaspils novads"},"447":{"code":"LV-SA","name":"Saldus novads"},"448":{"code":"Saulkrastu novads","name":"Saulkrastu novads"},"455":{"code":"S\u0113jas novads","name":"S\u0113jas novads"},"449":{"code":"Siguldas novads","name":"Siguldas novads"}
15989,"451":{"code":"Skr\u012bveru novads","name":"Skr\u012bveru novads"},"450":{"code":"Skrundas novads","name":"Skrundas novads"},"452":{"code":"Smiltenes novads","name":"Smiltenes novads"},"453":{"code":"Stopi\u0146u novads","name":"Stopi\u0146u novads"},"454":{"code":"Stren\u010du novads","name":"Stren\u010du novads"},"456":{"code":"LV-TA","name":"Talsu novads"},"458":{"code":"T\u0113rvetes novads","name":"T\u0113rvetes novads"},"457":{"code":"LV-TU","name":"Tukuma novads"},"459":{"code":"Vai\u0146odes novads","name":"Vai\u0146odes novads"},"460":{"code":"LV-VK","name":"Valkas novads"},"364":{"code":"Valmiera","name":"Valmiera"},"461":{"code":"LV-VM","name":"Valmieras novads"},"462":{"code":"Varak\u013c\u0101nu novads","name":"Varak\u013c\u0101nu novads"},"469":{"code":"V\u0101rkavas novads","name":"V\u0101rkavas novads"},"463":{"code":"Vecpiebalgas novads","name":"Vecpiebalgas novads"},"464":{"code":"Vecumnieku novads","name":"Vecumnieku novads"},"365":{"code":"LV-VEN","name":"Ventspils"},"465":{"code":"LV-VE","name":"Ventspils novads"},"466":{"code":"Vies\u012btes novads","name":"Vies\u012btes novads"},"467":{"code":"Vi\u013cakas novads","name":"Vi\u013cakas novads"},"468":{"code":"Vi\u013c\u0101nu novads","name":"Vi\u013c\u0101nu novads"},"470":{"code":"Zilupes novads","name":"Zilupes novads"}}},"NL":{"name":"Pa\u00edses Bajos"},"NO":{"name":"Noruega","regions":{"1351":{"code":"NO-42","name":"Agder"},"1352":{"code":"NO-34","name":"Innlandet"},"1353":{"code":"NO-22","name":"Jan Mayen"},"1354":{"code":"NO-15","name":"M\u00f8re og Romsdal"},"1355":{"code":"NO-18","name":"Nordland"},"1356":{"code":"NO-03","name":"Oslo"},"1357":{"code":"NO-11","name":"Rogaland"},"1358":{"code":"NO-21","name":"Svalbard"},"1359":{"code":"NO-54","name":"Troms og Finnmark"},"1360":{"code":"NO-50","name":"Tr\u00f8ndelag"},"1361":{"code":"NO-38","name":"Vestfold og Telemark"},"1362":{"code":"NO-46","name":"Vestland"},"1363":{"code":"NO-30","name":"Viken"}}},"PL":{"name":"Polonia","regions":{"997":{"code":"PL-02","name":"dolno\u015bl\u0105skie"},"998":{"code":"PL-04","name":"kujawsko-pomorskie"},"999":{"code":"PL-06","name":"lubelskie"},"1000":{"code":"PL-08","name":"lubuskie"},"1003":{"code":"PL-14","name":"mazowieckie"},"1002":{"code":"PL-12","name":"ma\u0142opolskie"},"1004":{"code":"PL-16","name":"opolskie"},"1005":{"code":"PL-18","name":"podkarpackie"},"1006":{"code":"PL-20","name":"podlaskie"},"1007":{"code":"PL-22","name":"pomorskie"},"1008":{"code":"PL-24","name":"\u015bl\u0105skie"},"1009":{"code":"PL-26","name":"\u015bwi\u0119tokrzyskie"},"1010":{"code":"PL-28","name":"warmi\u0144sko-mazurskie"},"1011":{"code":"PL-30","name":"wielkopolskie"},"1012":{"code":"PL-32","name":"zachodniopomorskie"},"1001":{"code":"PL-10","name":"\u0142\u00f3dzkie"}}},"PT":{"name":"Portugal","regions":{"1013":{"code":"PT-01","name":"Aveiro"},"1014":{"code":"PT-02","name":"Beja"},"1015":{"code":"PT-03","name":"Braga"},"1016":{"code":"PT-04","name":"Bragan\u00e7a"},"1017":{"code":"PT-05","name":"Castelo Branco"},"1018":{"code":"PT-06","name":"Coimbra"},"1019":{"code":"PT-07","name":"\u00c9vora"},"1020":{"code":"PT-08","name":"Faro"},"1021":{"code":"PT-09","name":"Guarda"},"1022":{"code":"PT-10","name":"Leiria"},"1023":{"code":"PT-11","name":"Lisboa"},"1024":{"code":"PT-12","name":"Portalegre"},"1025":{"code":"PT-13","name":"Porto"},"1032":{"code":"PT-30","name":"Regi\u00e3o Aut\u00f3noma da Madeira"},"1031":{"code":"PT-20","name":"Regi\u00e3o Aut\u00f3noma dos A\u00e7ores"},"1026":{"code":"PT-14","name":"Santar\u00e9m"},"1027":{"code":"PT-15","name":"Set\u00fabal"},"1028":{"code":"PT-16","name":"Viana do Castelo"},"1029":{"code":"PT-17","name":"Vila Real"},"1030":{"code":"PT-18","name":"Viseu"}}},"RO":{"name":"Ruman\u00eda","regions":{"278":{"code":"AB","name":"Alba"},"279":{"code":"AR","name":"Arad"},"280":{"code":"AG","name":"Arge\u015f"},"281":{"code":"BC","name":"Bac\u0103u"},"282":{"code":"BH","name":"Bihor"},"283":{"code":"BN","name":"Bistri\u0163a-N\u0103s\u0103ud"},"284":{"code":"BT","name":"Boto\u015fani"},"286":{"code":"BR","name":"Br\u0103ila"},"285":{"code":"BV","name":"Bra\u015fov"},"287":{"code":"B","name":"Bucure\u015fti"},"288":{"code":"BZ","name":"Buz\u0103u"},"290":{"code":"CL","name":"C\u0103l\u0103ra\u015fi"},"289":{"code":"CS","name":"Cara\u015f-Severin"},"291":{"code":"CJ","name":"Cluj"},"292":{"code":"CT","name":"Constan\u0163a"},"293":{"code":"CV","name":"Covasna"},"294":{"code":"DB","name":"D\u00e2mbovi\u0163a"},"295":{"code":"DJ","name":"Dolj"},"296":{"code":"GL","name":"Gala\u0163i"},"297":{"code":"GR","name":"Giurgiu"},"298":{"code":"GJ","name":"Gorj"},"299":{"code":"HR","name":"Harghita"},"300":{"code":"HD","name":"Hunedoara"},"301":{"code":"IL","name":"Ialomi\u0163a"},"302":{"code":"IS","name":"Ia\u015fi"},"303":{"code":"IF","name":"Ilfov"},"304":{"code":"MM","name":"Maramure\u015f"},"305":{"code":"MH","name":"Mehedin\u0163i"},"306":{"code":"MS","name":"Mure\u015f"},"307":{"code":"NT","name":"Neam\u0163"},"308":{"code":"OT","name":"Olt"},"309":{"code":"PH","name":"Prahova"},"311":{"code":"SJ","name":"S\u0103laj"},"310":{"code":"SM","name":"Satu-Mare"},"312":{"code":"SB","name":"Sibiu"},"313":{"code":"SV","name":"Suceava"},"314":{"code":"TR","name":"Teleorman"},"315":{"code":"TM","name":"Timi\u015f"},"316":{"code":"TL","name":"Tulcea"},"318":{"code":"VL","name":"V\u00e2lcea"},"317":{"code":"VS","name":"Vaslui"},"319":{"code":"VN","name":"Vrancea"}}},"RS":{"name":"Serbia"},"SE":{"name":"Suecia","regions":{"1043":{"code":"SE-K","name":"Blekinge l\u00e4n"}
15989,"1044":{"code":"SE-W","name":"Dalarnas l\u00e4n"},"1046":{"code":"SE-X","name":"G\u00e4vleborgs l\u00e4n"},"1045":{"code":"SE-I","name":"Gotlands l\u00e4n"},"1047":{"code":"SE-N","name":"Hallands l\u00e4n"},"1048":{"code":"SE-Z","name":"J\u00e4mtlands l\u00e4n"},"1049":{"code":"SE-F","name":"J\u00f6nk\u00f6pings l\u00e4n"},"1050":{"code":"SE-H","name":"Kalmar l\u00e4n"},"1051":{"code":"SE-G","name":"Kronobergs l\u00e4n"},"1052":{"code":"SE-BD","name":"Norrbottens l\u00e4n"},"1062":{"code":"SE-T","name":"\u00d6rebro l\u00e4n"},"1063":{"code":"SE-E","name":"\u00d6sterg\u00f6tlands l\u00e4n"},"1053":{"code":"SE-M","name":"Sk\u00e5ne l\u00e4n"},"1055":{"code":"SE-D","name":"S\u00f6dermanlands l\u00e4n"},"1054":{"code":"SE-AB","name":"Stockholms l\u00e4n"},"1056":{"code":"SE-C","name":"Uppsala l\u00e4n"},"1057":{"code":"SE-S","name":"V\u00e4rmlands l\u00e4n"},"1058":{"code":"SE-AC","name":"V\u00e4sterbottens l\u00e4n"},"1059":{"code":"SE-Y","name":"V\u00e4sternorrlands l\u00e4n"},"1060":{"code":"SE-U","name":"V\u00e4stmanlands l\u00e4n"},"1061":{"code":"SE-O","name":"V\u00e4stra G\u00f6talands l\u00e4n"}}},"SI":{"name":"Eslovenia"},"SK":{"name":"Eslovaquia"},"data_id":1790284162},"captcha":[],"loggedAsCustomer":[],"review":[],"wishlist":{"items":[]},"ammessages":[],"hyva_checkout":[],"hyva_commerce_messages":[],"rewards":[],"multisafepay-payment-request":[],"rocket_checkout_cart_actions":[],"customer_klaviyo":[],"recently_viewed_product":[],"recently_compared_product":[],"product_data_storage":[],"paypal-billing-agreement":[],"rocket_datalayer":[]}</script>
vendor: 1 bytes, line 15989
15989
15990<script> 15991 window.processSectionDataBeforeDispatch && (window.processSectionDataBeforeDispatch = new Proxy(window.processSectionDataBeforeDispatch, { 15992 apply(target, thisArg, [data]) { 15993 data.hyva_commerce_messages = data.hyva_commerce_messages || {}; 15994 return target.call(thisArg, data); 15995 } 15996 })); 15997</script>
15997 15998</div></body> 15999</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.