1<!doctype html><html class="no-js" lang="en"> 2 <head> 3 4
5<script type="application/vnd.locksmith+json" data-locksmith>{"version":"v346","locked":false,"initialized":true,"scope":"cart","access_granted":true,"access_denied":false,"requires_customer":false,"manual_lock":false,"remote_lock":false,"has_timeout":false,"remote_rendered":null,"hide_resource":false,"hide_links_to_resource":false,"hide_price":false,"hide_add_to_cart":false,"transparent":true,"locks":{"all":[],"opened":[]},"keys":[],"keys_signature":"a6111dc4847a5059d4622e3d27b184dd5cbae461b5d6fc459feab12efb47932d","state":{"template":"cart","theme":151830298694,"product":null,"collection":null,"page":null,"blog":null,"article":null,"app":null},"now":1791103105,"path":"\/cart","locale_root_url":"\/","canonical_url":"https:\/\/printroom.co\/cart","customer_id":null,"customer_id_signature":"a6111dc4847a5059d4622e3d27b184dd5cbae461b5d6fc459feab12efb47932d","cart":null}</script>
5<script data-locksmith>!function(){undefined;!function(){var s=window.Locksmith={},e=document.querySelector('script[type="application/vnd.locksmith+json"]'),n=e&&e.innerHTML;if(s.state={},s.util={},s.loading=!1,n)try{s.state=JSON.parse(n)}catch(d){}if(document.addEventListener&&document.querySelector){var o,a,i,t=[76,79,67,75,83,77,73,84,72,49,49],c=function(){a=t.slice(0)},l="style",r=function(e){e&&27!==e.keyCode&&"click"!==e.type||(document.removeEventListener("keydown",r),document.removeEventListener("click",r),o&&document.body.removeChild(o),o=null)};c(),document.addEventListener("keyup",function(e){if(e.keyCode===a[0]){if(clearTimeout(i),a.shift(),0<a.length)return void(i=setTimeout(c,1e3));c(),r(),(o=document.createElement("div"))[l].width="50%",o[l].maxWidth="1000px",o[l].height="85%",o[l].border="1px rgba(0, 0, 0, 0.2) solid",o[l].background="rgba(255, 255, 255, 0.99)",o[l].borderRadius="4px",o[l].position="fixed",o[l].top="50%",o[l].left="50%",o[l].transform="translateY(-50%) translateX(-50%)",o[l].boxShadow="0 2px 5px rgba(0, 0, 0, 0.3), 0 0 100vh 100vw rgba(0, 0, 0, 0.5)",o[l].zIndex="2147483645";var t=document.createElement("textarea");t.value=JSON.stringify(JSON.parse(n),null,2),t[l].border="none",t[l].display="block",t[l].boxSizing="border-box",t[l].width="100%",t[l].height="100%",t[l].background="transparent",t[l].padding="22px",t[l].fontFamily="monospace",t[l].fontSize="14px",t[l].color="#333",t[l].resize="none",t[l].outline="none",t.readOnly=!0,o.appendChild(t),document.body.appendChild(o),t.addEventListener("click",function(e){e.stopImmediatePropagation()}),t.select(),document.addEventListener("keydown",r),document.addEventListener("click",r)}})}s.isEmbedded=-1!==window.location.search.indexOf("_ab=0&_fd=0&_sc=1"),s.path=s.state.path||window.location.pathname,s.basePath=s.state.locale_root_url.concat("/apps/locksmith").replace(/^\/\//,"/"),s.reloading=!1,s.util.console=window.console||{log:function(){},error:function(){}},s.util.makeUrl=function(e,t){var n,o=s.basePath+e,a=[],i=s.cache();for(n in i)a.push(n+"="+encodeURIComponent(i[n]));for(n in t)a.push(n+"="+encodeURIComponent(t[n]));return s.state.customer_id&&(a.push("customer_id="+encodeURIComponent(s.state.customer_id)),a.push("customer_id_signature="+encodeURIComponent(s.state.customer_id_signature))),o+=(-1===o.indexOf("?")?"?":"&")+a.join("&")},s._initializeCallbacks=[],s.on=function(e,t){if("initialize"!==e)throw'Locksmith.on() currently only supports the "initialize" event';s._initializeCallbacks.push(t)},s.initializeSession=function(e){if(!s.isEmbedded){var t=!1,n=!0,o=!0;(e=e||{}).silent&&(o=n=!(t=!0)),s.ping({silent:t,spinner:n,reload:o,callback:function(){s._initializeCallbacks.forEach(function(e){e()})}})}},s.cache=function(e){var t={};try{var n=function a(e){return(document.cookie.match("(^|; )"+e+"=([^;]*)")||0)[2]};t=JSON.parse(decodeURIComponent(n("locksmith-params")||"{}"))}catch(d){}if(e){for(var o in e)t[o]=e[o];document.cookie="locksmith-params=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/",document.cookie="locksmith-params="+encodeURIComponent(JSON.stringify(t))+"; path=/"}return t},s.cache.cart=s.state.cart,s.cache.cartLastSaved=null,s.params=s.cache(),s.util.reload=function(){s.reloading=!0;try{window.location.href=window.location.href.replace(/#.*/,"")}catch(d){s.util.console.error("Preferred reload method failed",d),window.location.reload()}},s.cache.saveCart=function(e){if(!s.cache.cart||s.cache.cart===s.cache.cartLastSaved)return e?e():null;var t=s.cache.cartLastSaved;s.cache.cartLastSaved=s.cache.cart,fetch("/cart/update.js",{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({attributes:{locksmith:s.cache.cart}})}).then(function(e){if(!e.ok)throw new Error("Cart update failed: "+e.status);return e.json()}).then(function(){e&&e()})["catch"](function(e){if(s.cache.cartLastSaved=t,!s.reloading)throw e})},s.util.spinnerHTML='<style>body{background:#FFF}@keyframes spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}#loading{display:flex;width:100%;height:50vh;
5color:#777;align-items:center;justify-content:center}#loading .spinner{display:block;animation:spin 600ms linear infinite;position:relative;width:50px;height:50px}#loading .spinner-ring{stroke:currentColor;stroke-dasharray:100%;stroke-width:2px;stroke-linecap:round;fill:none}</style><div id="loading"><div class="spinner"><svg width="100%" height="100%"><svg preserveAspectRatio="xMinYMin"><circle class="spinner-ring" cx="50%" cy="50%" r="45%"></circle></svg></svg></div></div>',s.util.clobberBody=function(e){document.body.innerHTML=e},s.util.clobberDocument=function(e){e.responseText&&(e=e.responseText),document.documentElement&&document.removeChild(document.documentElement);var t=document.open("text/html","replace");t.writeln(e),t.close(),setTimeout(function(){var e=t.querySelector("[autofocus]");e&&e.focus()},100)},s.util.serializeForm=function(e){if(e&&"FORM"===e.nodeName){var t,n,o={};for(t=e.elements.length-1;0<=t;t-=1)if(""!==e.elements[t].name)switch(e.elements[t].nodeName){case"INPUT":switch(e.elements[t].type){default:case"text":case"hidden":case"password":case"button":case"reset":case"submit":o[e.elements[t].name]=e.elements[t].value;break;case"checkbox":case"radio":e.elements[t].checked&&(o[e.elements[t].name]=e.elements[t].value);break;case"file":}break;case"TEXTAREA":o[e.elements[t].name]=e.elements[t].value;break;case"SELECT":switch(e.elements[t].type){case"select-one":o[e.elements[t].name]=e.elements[t].value;break;case"select-multiple":for(n=e.elements[t].options.length-1;0<=n;n-=1)e.elements[t].options[n].selected&&(o[e.elements[t].name]=e.elements[t].options[n].value)}break;case"BUTTON":switch(e.elements[t].type){case"reset":case"submit":case"button":o[e.elements[t].name]=e.elements[t].value}}return o}},s.util.on=function(e,i,s,t){t=t||document;var c="locksmith-"+e+i,n=function(e){var t=e.target,n=e.target.parentElement,o=t&&t.className&&(t.className.baseVal||t.className)||"",a=n&&n.className&&(n.className.baseVal||n.className)||"";("string"==typeof o&&-1!==o.split(/\s+/).indexOf(i)||"string"==typeof a&&-1!==a.split(/\s+/).indexOf(i))&&!e[c]&&(e[c]=!0,s(e))};t.attachEvent?t.attachEvent(e,n):t.addEventListener(e,n,!1)},s.util.enableActions=function(e){s.util.on("click","locksmith-action",function(e){e.preventDefault();var t=e.target;t.dataset.confirmWith&&!confirm(t.dataset.confirmWith)||(t.disabled=!0,t.innerText=t.dataset.disableWith,s.post("/action",t.dataset.locksmithParams,{spinner:!1,type:"text",success:function(e){(e=JSON.parse(e.responseText)).message&&alert(e.message),s.util.reload()}}))},e)},s.util.inject=function(e,t){var n=["data","locksmith","append"];if(-1!==t.indexOf(n.join("-"))){var o=document.createElement("div");o.innerHTML=t,e.appendChild(o)}else e.innerHTML=t;var a,i,s=e.querySelectorAll("script");for(i=0;i<s.length;++i){a=s[i];var c=document.createElement("script");if(a.type&&(c.type=a.type),a.src)c.src=a.src;else{var l=document.createTextNode(a.innerHTML);c.appendChild(l)}e.appendChild(c)}var r=e.querySelector("[autofocus]");r&&r.focus()},s.post=function(e,t,n){!1!==(n=n||{}).spinner&&s.util.clobberBody(s.util.spinnerHTML);var o={};n.container===document?(o.layout=1,n.success=function(e){s.util.clobberDocument(e)}):n.container&&(o.layout=0,n.success=function(e){var t="string"==typeof n.container?document.getElementById(n.container):n.container;t&&(s.util.inject(t,e),t.id===t.firstChild.id&&t.parentElement.replaceChild(t.firstChild,t))}),n.form_type&&(t.form_type=n.form_type),n.include_layout_classes!==undefined&&(t.include_layout_classes=n.include_layout_classes),n.lock_id!==undefined&&(t.lock_id=n.lock_id),s.loading=!0;var a=s.util.makeUrl(e,o),i="json"===n.type||"text"===n.type;fetch(a,{method:"POST",headers:{"Content-Type":"application/json",Accept:i?"application/json":"text/html"},body:JSON.stringify(t)}).then(function(e){if(!e.ok)throw new Error("Request failed: "+e.status);return e.text()}).then(function(e){var t=n.success||s.util.clobberDocument;t(i?{responseText:e}:e)})["catch"](function(e){if(!s.reloading)if("dashboard.weglot.com"!==window.location.host){if(!n.silent)throw alert("Something went wrong! Please refresh and try again."),e;console.error(e)}else console.error(e)})["finally"](function(){s.loading=!1})},s.postResource=function(e,t){e.path=s.path,e.search=window.location.search,e.state=s.state,e.passcode&&(e.passcode=e.passcode.trim()),e.email&&(e.email=e.email.trim()),e.state.cart=s.cache.cart,e.locksmith_json=s.jsonTag,e.locksmith_json_signature=s.jsonTagSignature,s.post("/resource",e,t)},s.ping=function(t){if(!s.isEmbedded){t=t||{};var n=function(){t.reload?s.util.reload():"function"==typeof t.callback&&t.callback()};s.post("/ping",{path:s.path,search:window.location.search,state:s.state},{spinner:!!t.spinner,silent:"undefined"==typeof t.silent||t.silent,type:"text",success:function(e){e&&e.responseText?((e=JSON.parse(e.responseText)).messages&&0<e.messages.length&&s.showMessages(e.messages),e.cart&&s.cache.cart!==e.cart?(s.cache.cart=e.cart,s.cache.saveCart(function(){e.cart&&e.cart.match(/^.+:/)?(t.reload||"function"!=typeof t.callback||t.callback(),s.util.reload()):n()})):n()):console.error("[Locksmith] Invalid result in ping callback:",e)}})}},s.timeoutMonitor=function(){var e=s.cache.cart;s.ping({callback:function(){e!==s.cache.cart||setTimeout(function(){s.timeoutMonitor()},6e4)}})},s.showMessages=function(e){var t=document.createElement("div");t.style.position="fixed",t.style.left=0,t.style.right=0,t.style.bottom="-50px",t.style.opacity=0,t.style.background="#191919",t.style.color="#ddd",t.style.transition="bottom 0.2s, opacity 0.2s",t.style.zIndex=999999,t.innerHTML=["<style>"," .locksmith-ab .locksmith-b { display: none; }"," .locksmith-ab.toggled .locksmith-b { display: flex; }"," .locksmith-ab.toggled .locksmith-a { display: none; }"," .locksmith-flex { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; padding: 10px 20px; }"," .locksmith-message + .locksmith-message { border-top: 1px #555 solid; }"," .locksmith-message a { color: inherit; font-weight: bold; }"," .locksmith-message a:hover { color: inherit; opacity: 0.8; }"," a.locksmith-ab-toggle { font-weight: inherit; text-decoration: underline; }"," .locksmith-text { flex-grow: 1; }"," .locksmith-cta { flex-grow: 0; text-align: right; }"," .locksmith-cta button { transform: scale(0.8); transform-origin: left; }"," .locksmith-cta > * { display: block; }"," .locksmith-cta > * + * { margin-top: 10px; }"," .locksmith-message a.locksmith-close { flex-grow: 0; text-decoration: none; margin-left: 15px; font-size: 30px; font-family: monospace; display: block; padding: 2px 10px; }"," @media screen and (max-width: 600px) {"," .locksmith-wide-only { display: none !important; }"," .locksmith-flex { padding: 0 15px; }"," .locksmith-flex > * { margin-top: 5px; margin-bottom: 5px; }"," .locksmith-cta { text-align: left; }"," }"," @media screen and (min-width: 601px) {"," .locksmith-narrow-only { display: none !important; }"," }","</style>"].join("")+e.map(function(e){return'<div class="locksmith-message">'+e+"</div>"}).join(""),document.body.appendChild(t),document.body.style.position="relative",document.body.parentElement.style.paddingBottom=t.offsetHeight+"px",setTimeout(function(){t.style.bottom=0,t.style.opacity=1},50),s.util.on("click","locksmith-ab-toggle",function(e){e.preventDefault();for(var t=e.target.parentElement;-1===t.className.split(" ").indexOf("locksmith-ab");)t=t.parentElement;-1!==t.className.split(" ").indexOf("toggled")?t.className=t.className.replace("toggled",""):t.className=t.className+" toggled"}),s.util.enableActions(t)}}()}();</script>
5 6
6<script data-locksmith>Locksmith.cache.cart=null</script>
6 7 8
8<script data-locksmith>Locksmith.jsonTag="{\"version\":\"v346\",\"locked\":false,\"initialized\":true,\"scope\":\"cart\",\"access_granted\":true,\"access_denied\":false,\"requires_customer\":false,\"manual_lock\":false,\"remote_lock\":false,\"has_timeout\":false,\"remote_rendered\":null,\"hide_resource\":false,\"hide_links_to_resource\":false,\"hide_price\":false,\"hide_add_to_cart\":false,\"transparent\":true,\"locks\":{\"all\":[],\"opened\":[]},\"keys\":[],\"keys_signature\":\"a6111dc4847a5059d4622e3d27b184dd5cbae461b5d6fc459feab12efb47932d\",\"state\":{\"template\":\"cart\",\"theme\":151830298694,\"product\":null,\"collection\":null,\"page\":null,\"blog\":null,\"article\":null,\"app\":null},\"now\":1791103105,\"path\":\"\\\/cart\",\"locale_root_url\":\"\\\/\",\"canonical_url\":\"https:\\\/\\\/printroom.co\\\/cart\",\"customer_id\":null,\"customer_id_signature\":\"a6111dc4847a5059d4622e3d27b184dd5cbae461b5d6fc459feab12efb47932d\",\"cart\":null}";Locksmith.jsonTagSignature="e2e651e29dd1fb1874f2b86b720ffa803111aef2e71e8306d891ec937891e2d5"</script>
8 9<meta name="google-site-verification" content="r89mOlbEOfEjECOwEHOd5jrv5jGOJeGHPXM78LaGLXY" /> 10 11 <meta charset="utf-8"> 12 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 13 <meta name="viewport" content="width=device-width,initial-scale=1"> 14 <meta name="theme-color" content="">
15<script> 16 window.dataLayer = window.dataLayer || []; 17 window.dataLayer.push({ 18 store_access: 'public', 19 store_type: 'main', 20 page_template: "cart" 21 }); 22 window.prTrackLead = window.prTrackLead || function (detail) { 23 try { 24 detail = detail || {}; 25 var ud = detail.user_data || {}; 26 var email = (ud.email || '').toString().trim().toLowerCase(); 27 var phone = (ud.phone_number || '').toString().replace(/[^0-9+]/g, ''); 28 window.dataLayer.push({ 29 event: 'generate_lead', 30 lead_type: detail.lead_type || 'unknown', 31 form_id: detail.form_id || null, 32 page_path: window.location.pathname, 33 /* Enhanced Conversions for Leads â GTM's user-provided-data variable reads 34 user_data.{email,phone_number}; Google hashes (SHA-256) client-side. 35 Same key shape as the quote/book-a-call pushes in global.bundle.js so ONE 36 GTM variable covers every lead type. */ 37 user_data: { 38 email: email || undefined, 39 phone_number: phone || undefined 40 } 41 }); 42 } catch (e) {} 43 }; 44 </script>
44<script> 45 if (!window.__prGtmLoaded) { 46 window.__prGtmLoaded = true;
vendor: 455 bytes, lines 46-56
46 47 (function (w, d, s, l, i) { 48 w[l] = w[l] || []; 49 w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' }); 50 var f = d.getElementsByTagName(s)[0], 51 j = d.createElement(s), 52 dl = l != 'dataLayer' ? '&l=' + l : ''; 53 j.async = true; 54 j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; 55 f.parentNode.insertBefore(j, f); 56 })(window, document, 'script', 'dataLayer', '
56GTM-W9DFFGB
vendor: 8 bytes, lines 56-57
56'); 57
57} 58 </script>
58 59 60 <link rel="canonical" href="https://printroom.co/cart"> 61 <meta name="robots" content="noindex, follow"> 62 63 64 65 <link rel="preconnect" href="https://cdn.shopify.com" crossorigin> 66 67
67<script> 68(function() { 69 'use strict'; 70 var observer = new MutationObserver(function(mutations) { 71 mutations.forEach(function(mutation) { 72 mutation.addedNodes.forEach(function(node) { 73 if (node.tagName === 'SCRIPT' && node.src && node.src.includes('popt.in')) { 74 node.remove(); 75 } 76 }); 77 }); 78 }); 79 observer.observe(document.documentElement, { childList: true, subtree: true }); 80})(); 81</script>
81<script> 82document.addEventListener('DOMContentLoaded', function() { 83 var scripts = document.querySelectorAll('script[data-block-script]'); 84 if (!scripts.length) return; 85 if (window.Shopify && window.Shopify.designMode) { 86 scripts.forEach(function(s) { 87 var real = document.createElement('script'); 88 real.textContent = s.textContent; 89 s.parentNode.replaceChild(real, s); 90 }); 91 return; 92 } 93 var io = new IntersectionObserver(function(entries) { 94 entries.forEach(function(entry) { 95 if (!entry.isIntersecting) return; 96 io.unobserve(entry.target); 97 var pending = entry.target.querySelector('script[data-block-script]'); 98 if (pending) { 99 var real = document.createElement('script'); 100 real.textContent = pending.textContent; 101 pending.parentNode.replaceChild(real, pending); 102 } 103 }); 104 }, { rootMargin: '300px' }); 105 scripts.forEach(function(s) { 106 var block = s.closest('[data-ai-block]') || s.parentElement; 107 io.observe(block); 108 }); 109}); 110</script>
110<script> 111setTimeout(function() { 112 'use strict'; 113 114 // Google Tag Manager loads early + reliably via the 'gtm-head' snippet 115 // (settings.gtm_container_id). The old "remove existing GTM then re-inject after 116 // 3s" hack saved ~922ms but delayed the Ads Conversion Linker (breaking gclid 117 // attribution) and dropped fast-bounce visitors from analytics. Do NOT re-add it. 118 119 // LAZY LOAD THIRD-PARTY ANALYTICS 120 var loadThirdPartyScripts = function() { 121 if (typeof fbq === 'undefined') { 122 !function(f,b,e,v,n,t,s){ 123 if(f.fbq)return;n=f.fbq=function(){n.callMethod? 124 n.callMethod.apply(n,arguments):n.queue.push(arguments)}; 125 if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; 126 n.queue=[];t=b.createElement(e);t.async=!0; 127 t.src=v;s=b.getElementsByTagName(e)[0]; 128 s.parentNode.insertBefore(t,s) 129 }(window,document,'script','https://connect.facebook.net/en_US/fbevents.js'); 130 } 131 if (typeof clarity === 'undefined' && window.clarityCode) { 132 (function(c,l,a,r,i,t,y){ 133 c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)}; 134 t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i; 135 y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y); 136 })(window,document,"clarity","script",window.clarityCode); 137 } 138 }; 139 if ('requestIdleCallback' in window) { 140 requestIdleCallback(loadThirdPartyScripts, { timeout: 5000 }); 141 } else { 142 setTimeout(loadThirdPartyScripts, 5000); 143 } 144 145 // LINK PREFETCH ON HOVER 146 var NO_PREFETCH = ['/cart','/checkout','/account','/admin','/password','/challenge','/apps/','/tools/','/services/']; 147 var prefetched = {}; 148 var hoverTimer = null; 149 150 function shouldPrefetch(href) { 151 try { 152 var url = new URL(href, location.origin); 153 if (url.origin !== location.origin) return false; 154 if (url.pathname === location.pathname) return false; 155 if (prefetched[url.pathname]) return false; 156 if (navigator.connection && navigator.connection.saveData) return false; 157 for (var i = 0; i < NO_PREFETCH.length; i++) { 158 if (url.pathname.indexOf(NO_PREFETCH[i]) === 0) return false; 159 } 160 var ext = url.pathname.split('.').pop(); 161 if (['jpg','jpeg','png','gif','svg','webp','pdf','zip','css','js'].indexOf(ext) !== -1) return false; 162 return true; 163 } catch (e) { 164 return false; 165 } 166 } 167 168 function prefetchUrl(href) { 169 var url = new URL(href, location.origin); 170 if (prefetched[url.pathname]) return; 171 prefetched[url.pathname] = true; 172 var link = document.createElement('link'); 173 link.rel = 'prefetch'; 174 link.href = href; 175 link.as = 'document'; 176 document.head.appendChild(link); 177 } 178 179 document.addEventListener('pointerenter', function(e) { 180 var a = e.target.closest ? e.target.closest('a[href]') : null; 181 if (!a || !shouldPrefetch(a.href)) return; 182 var delay = e.pointerType === 'mouse' ? 65 : 0; 183 hoverTimer = setTimeout(function() { prefetchUrl(a.href); }, delay); 184 }, { capture: true, passive: true }); 185 186 document.addEventListener('pointerleave', function() { 187 if (hoverTimer) { clearTimeout(hoverTimer); hoverTimer = null; } 188 }, { capture: true, passive: true }); 189 190 if ('requestIdleCallback' in window) { 191 requestIdleCallback(function() { 192 var navLinks = document.querySelectorAll('nav a[href], [data-theme-header] a[href]'); 193 var count = 0; 194 navLinks.forEach(function(a) { 195 if (count < 5 && shouldPrefetch(a.href)) { 196 prefetchUrl(a.href); 197 count++; 198 } 199 }); 200 }, { timeout: 3000 }); 201 } 202 203 // BFCACHE SUPPORT 204 window.addEventListener('pageshow', function(event) { 205 if (event.persisted) { 206 fetch('/cart.js').then(function(r) { return r.json(); }).then(function(data) { 207 document.querySelectorAll('[data-cart-count]').forEach(function(el) { 208 el.textContent = data.item_count; 209 }); 210 if (window.Alpine && window.Alpine.store && window.Alpine.store('cartCount')) { 211 window.Alpine.store('cartCount').count = data.item_count; 212 } 213 }).catch(function() {}); 214 } 215 }); 216}, 0); 217</script>
217<script type="speculationrules"> 218{ 219 "prerender": [{ 220 "where": { 221 "and": [ 222 { "href_matches": "/*" }, 223 { "not": { "href_matches": [ 224 "/cart", "/cart/*", 225 "/checkout", "/checkout/*", 226 "/account", "/account/*", 227 "/admin/*", 228 "/password", 229 "/challenge/*", 230 "/apps/*", 231 "/tools/*", 232 "/services/*" 233 ] } }, 234 { "not": { "selector_matches": "[target=_blank]" } } 235 ] 236 }, 237 "eagerness": "moderate" 238 }], 239 "prefetch": [{ 240 "where": { 241 "and": [ 242 { "href_matches": "/*" }, 243 { "not": { "href_matches": [ 244 "/cart", "/cart/*", 245 "/checkout", "/checkout/*", 246 "/account", "/account/*" 247 ] } } 248 ] 249 }, 250 "eagerness": "moderate" 251 }] 252} 253</script>
253 254 255 256<style> 257 .hero-image, [data-hero-image] { aspect-ratio: 16/9; width: 100%; height: auto; background-color: #f0f0f0; } 258 .product-image { aspect-ratio: 1/1; background-color: #fafafa; } 259 header, .header { min-height: 60px; } 260 main { min-height: 100vh; } 261 .skeleton { animation: skeleton-loading 1.5s infinite ease-in-out; background: linear-gradient(90deg,#f0f0f0 25%,#e0e0e0 50%,#f0f0f0 75%); background-size: 200% 100%; } 262 @keyframes skeleton-loading { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } 263 @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } } 264 @media (max-width: 1023px) { .hero-image-mobile, [data-hero-image-mobile] { aspect-ratio: 9/16; } } 265 </style><link 266 rel="icon" 267 type="image/png" 268 href="//printroom.co/cdn/shop/files/pr_branding_logo_favicon_flag-01_11ede80e-5ae5-41fe-8eb2-87dee0e48e14.png?crop=center&height=32&v=1646960588&width=32" 269 ><link rel="preconnect" href="https://fonts.shopifycdn.com" crossorigin> 270 271 272 273 274 <!-- default to true --><!-- pageTitleTemplate: %% page_title %% --> 275 <!-- pageTitleToParse": Your Shopping Cart --> 276 <!-- pageTitleTruncateApplicable: true --> 277 278 <!-- pluginseo_pageTitleTemplateApplyToAll: true --> 279 <!-- pageTitleTruncateApplicable: true --><!-- Custom page title: Yes --><title>Your Shopping Cart | The Print Room</title> <!-- default to true --><!-- metaDescriptionTemplate: %% page_description %% --> 280 <!-- metaDescriptionToParse": --> 281 <!-- metaDescriptionTruncateApplicable: true --> 282 283 <!-- pluginseo_metaDescriptionTemplateApplyToAll: true --> 284 <!-- metaDescriptionTruncateApplicable: true --><!-- Yes -->
284<script data-desc="seo-organization" type="application/ld+json"> 285 { 286 "@context": "http://schema.org", 287 "@type": "Organization", 288 "additionalType": "https://schema.org/OnlineStore", 289 "@id": "https://printroom.co#organization", 290 "name": "The Print Room", 291 "url": "https://printroom.co", 292 "description": "NZâs experts in custom t-shirt printing, tote bags, uniforms, and branded merchandise. Print Room offers high-quality screen printing and embroidery using eco-friendly inks. Fast turnaround, sustainable production, and trusted by leading New Zealand brands.","logo": { 293 "type": "ImageObject", 294 "url": "https://printroom.co/cdn/shop/t/59/assets/pluginseo_structuredDataLogo_small.png?v=39003" 295 }, 296 "image": "https://printroom.co/cdn/shop/t/59/assets/pluginseo_structuredDataLogo_small.png?v=39003","areaServed": [{ "@type": "Country", "name": "Australia" }, 297 { "@type": "Country", "name": "New Zealand" }], 298 "sameAs": ["https://www.linkedin.com/company/theprintroom"] 299 } 300</script>
300<script data-desc="seo-website" type="application/ld+json"> 301 { 302 "@context": "http://schema.org", 303 "@type": "WebSite", 304 "name": "The Print Room", 305 "url": "https://printroom.co", 306 "inLanguage": "en", 307 "potentialAction": { 308 "@type": "SearchAction", 309 "target": "https://printroom.co/search?q={search_term_string}", 310 "query-input": "required name=search_term_string" 311 } 312 } 313</script>
313<meta name="pluginseo" content="Plug in SEO Plus" data-ptf="s-te_df-ap" data-mdf="s-te_df" /> 314 315 316
316<script type="esms-options"> 317 { 318 "noLoadEventRetriggers": true 319 } 320</script>
320 321
322<script> 323 if ( 324 !(HTMLScriptElement.supports && HTMLScriptElement.supports('importmap')) 325 ) { 326 const importMapShimScriptEl = document.createElement('script'); 327 importMapShimScriptEl.src = '//printroom.co/cdn/shop/t/59/assets/es-module-shims.bundle.min.js?v=98603786603752121101787098437' 328 importMapShimScriptEl.async = true; 329 330 document.currentScript.after(importMapShimScriptEl); 331 } 332</script>
vendor: 1 bytes, line 332
332
333<script async crossorigin fetchpriority="high" src="/cdn/shopifycloud/importmap-polyfill/es-modules-shim.2.4.0.js"></script>
vendor: 1 bytes, line 333
333
334<script type="importmap"> 335 { 336 "imports": { 337 "vendor": "//printroom.co/cdn/shop/t/59/assets/vendor.bundle.min.js?v=124729801276099409011787098433", 338 "deferrable-data": "//printroom.co/cdn/shop/t/59/assets/deferrable-data.bundle.js?v=160370895301608380811787098437", 339 "@supabase/supabase-js": "//printroom.co/cdn/shop/t/59/assets/supabase-js.bundle.js?v=151185893978749678631787098436", 340 "product": "//printroom.co/cdn/shop/t/59/assets/island-product.bundle.js?v=53162399053546849101790733316", 341 "quick-buy": "//printroom.co/cdn/shop/t/59/assets/island-quick-buy.bundle.js?v=147469616221971819701787098437", 342 "ai-chatbot": "//printroom.co/cdn/shop/t/59/assets/ai-chatbot.bundle.js?v=114215721854634402901788472409", 343 "leavers-quote-builder": "//printroom.co/cdn/shop/t/59/assets/leavers-quote-builder.bundle.js?v=140741536858912509621787098436", 344 "leavers-product-grid": "//printroom.co/cdn/shop/t/59/assets/leavers-product-grid.bundle.js?v=101839867699394922961787098435" 345 } 346 } 347</script>
347 348
349<script> 350 (function() { 351 var _originalAlert = window.alert; 352 window.alert = function(message) { 353 if (message && message.toLowerCase().includes('personalized text')) { 354 message = 'This field is required to place an order.'; 355 } 356 _originalAlert.call(window, message); 357 }; 358 })(); 359 </script>
359 360 361
361<script>window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.start');</script>
361<meta name="google-site-verification" content="r89mOlbEOfEjECOwEHOd5jrv5jGOJeGHPXM78LaGLXY"> 362<meta id="shopify-digital-wallet" name="shopify-digital-wallet" content="/7054289/digital_wallets/dialog"> 363<meta id="in-context-paypal-metadata" data-shop-id="7054289" data-venmo-supported="false" data-environment="production" data-locale="en_US" data-paypal-v4="true" data-currency="USD"> 364<link rel="ucp" href="/.well-known/ucp" version="2026-08-25"><link rel="alternate" hreflang="x-default" href="https://theprintroom.nz/cart"> 365<link rel="alternate" hreflang="en" href="https://theprintroom.nz/cart"> 366<link rel="alternate" hreflang="en-AU" href="https://printroom.co/en-au/cart"> 367<link rel="alternate" hreflang="en-CN" href="https://printroom.co/cart"> 368<link rel="alternate" hreflang="en-FR" href="https://printroom.co/cart"> 369<link rel="alternate" hreflang="en-GB" href="https://printroom.co/cart"> 370<link rel="alternate" hreflang="en-US" href="https://printroom.co/cart">
371<script async="async" src="/checkouts/internal/preloads.js?locale=en-US&default_configuration_id=488013894"></script>
371 372<link rel="preconnect" href="https://shop.app" crossorigin="anonymous">
373<script async="async" src="https://shop.app/checkouts/internal/preloads.js?locale=en-US&default_configuration_id=488013894&shop_id=7054289" crossorigin="anonymous"></script>
vendor: 1 bytes, line 373
373
374<script id="apple-pay-shop-capabilities" type="application/json">{"shopId":7054289,"countryCode":"NZ","currencyCode":"USD","merchantCapabilities":["supports3DS"],"merchantId":"gid:\/\/shopify\/Shop\/7054289","merchantName":"The Print Room","requiredBillingContactFields":["postalAddress","email","phone"],"requiredShippingContactFields":["postalAddress","email","phone"],"shippingType":"shipping","supportedNetworks":["visa","masterCard","amex","jcb"],"total":{"type":"pending","label":"The Print Room","amount":"1.00"},"shopifyPaymentsEnabled":true,"supportsSubscriptions":true}</script>
vendor: 1 bytes, line 374
374
375<script id="shopify-features" type="application/json">{"accessToken":"0a03320998ce9cf7ffe404a489cfebbd","betas":["rich-media-storefront-analytics"],"domain":"printroom.co","predictiveSearch":true,"shopId":7054289,"locale":"en"}</script>
vendor: 1 bytes, line 375
375
376<script>var Shopify = Shopify || {}; 377Shopify.shop = "the-print-room.myshopify.com"; 378Shopify.locale = "en"; 379Shopify.currency = {"active":"USD","rate":"0.57265452"}; 380Shopify.country = "US"; 381Shopify.theme = {"name":"Print_Room_Co","id":151830298694,"schema_name":"Baseline","schema_version":"3.3.1","theme_store_id":null,"role":"main"}; 382Shopify.theme.handle = "null"; 383Shopify.theme.style = {"id":null,"handle":null}; 384Shopify.cdnHost = "printroom.co/cdn"; 385Shopify.routes = Shopify.routes || {}; 386Shopify.routes.root = "/"; 387Shopify.shopJsCdnBaseUrl = "https://cdn.shopify.com/shopifycloud/shop-js"; 388Shopify.SignInWithShop = Shopify.SignInWithShop || {}; 389Shopify.SignInWithShop.User = Shopify.SignInWithShop.User || {}; 390Shopify.SignInWithShop.User.recognized = false;</script>
vendor: 1 bytes, line 390
390
391<script type="module">!function(o){(o.Shopify=o.Shopify||{}).modules=!0}(window);</script>
vendor: 1 bytes, line 391
391
392<script>!function(o){function n(){var o=[];function n(){o.push(Array.prototype.slice.apply(arguments))}return n.q=o,n}var t=o.Shopify=o.Shopify||{};t.loadFeatures=n(),t.autoloadFeatures=n()}(window);</script>
vendor: 1 bytes, line 392
392
393<script> 394 window.ShopifyPay = window.ShopifyPay || {}; 395 window.ShopifyPay.apiHost = "shop.app\/pay"; 396 window.ShopifyPay.redirectState = null; 397</script>
vendor: 1 bytes, line 397
397
398<script> 399 window.Shopify = window.Shopify || {}; 400 window.Shopify.SignInWithShop = window.Shopify.SignInWithShop || {}; 401 window.Shopify.SignInWithShop.assetMetrics = { sampleRate: 0.25 }; 402 window.Shopify.SignInWithShop.eligible = true; 403</script>
vendor: 1 bytes, line 403
403
404<script id="shop-js-analytics" type="application/json">{"pageType":"cart"}</script>
vendor: 1 bytes, line 404
404
405<script defer="defer" async type="module" src="https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.init-shop-cart-sync.en.esm.js"></script>
vendor: 1 bytes, line 405
405
406<script type="module"> 407 await import("https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.init-shop-cart-sync.en.esm.js"); 408 409 window.Shopify.SignInWithShop?.initShopCartSync?.({"fedCMEnabled":true,"windoidEnabled":true}); 410 411</script>
vendor: 1 bytes, line 411
411
412<script> 413 window.Shopify = window.Shopify || {}; 414 if (!window.Shopify.featureAssets) window.Shopify.featureAssets = {}; 415 window.Shopify.featureAssets['shop-js'] = {"avatar":["modules/v2/loader.avatar.en.esm.js"],"checkout-modal":["modules/v2/loader.checkout-modal.en.esm.js"],"init-customer-accounts-sign-up":["modules/v2/loader.init-customer-accounts-sign-up.en.esm.js"],"init-customer-accounts":["modules/v2/loader.init-customer-accounts.en.esm.js"],"init-fed-cm":["modules/v2/loader.init-fed-cm.en.esm.js"],"init-shop-cart-sync":["modules/v2/loader.init-shop-cart-sync.en.esm.js"],"init-shop-email-lookup-coordinator":["modules/v2/loader.init-shop-email-lookup-coordinator.en.esm.js"],"init-shop-for-new-customer-accounts":["modules/v2/loader.init-shop-for-new-customer-accounts.en.esm.js"],"init-shop-user-recognition":["modules/v2/loader.init-shop-user-recognition.en.esm.js"],"init-windoid":["modules/v2/loader.init-windoid.en.esm.js"],"lead-capture":["modules/v2/loader.lead-capture.en.esm.js"],"listener":["modules/v2/loader.listener.en.esm.js"],"pay-button":["modules/v2/loader.pay-button.en.esm.js"],"payment-terms":["modules/v2/loader.payment-terms.en.esm.js"],"shop-button":["modules/v2/loader.shop-button.en.esm.js"],"shop-cart-sync":["modules/v2/loader.shop-cart-sync.en.esm.js"],"shop-cash-offers":["modules/v2/loader.shop-cash-offers.en.esm.js"],"shop-follow-button":["modules/v2/loader.shop-follow-button.en.esm.js"],"shop-login-button":["modules/v2/loader.shop-login-button.en.esm.js"],"shop-login":["modules/v2/loader.shop-login.en.esm.js"],"shop-toast-manager":["modules/v2/loader.shop-toast-manager.en.esm.js"],"shop-user-recognition":["modules/v2/loader.shop-user-recognition.en.esm.js"]}; 416</script>
vendor: 1 bytes, line 416
416
417<script>(function() { 418 var isLoaded = false; 419 function asyncLoad() { 420 if (isLoaded) return; 421 isLoaded = true; 422 var urls = ["\/\/d1liekpayvooaz.cloudfront.net\/apps\/customizery\/customizery.js?shop=the-print-room.myshopify.com","https:\/\/app.carboncheckout.com\/assets\/api\/shopify.min.js?shop=the-print-room.myshopify.com","https:\/\/static.klaviyo.com\/onsite\/js\/klaviyo.js?company_id=WkJ8Uf\u0026shop=the-print-room.myshopify.com","https:\/\/cdn.nfcube.com\/instafeed-dfc514f941e0dbcfd9799eba509c69d2.js?shop=the-print-room.myshopify.com","\/\/d1liekpayvooaz.cloudfront.net\/apps\/uploadery\/uploadery.js?shop=the-print-room.myshopify.com","https:\/\/cdn.grw.reputon.com\/assets\/widget.js?shop=the-print-room.myshopify.com","https:\/\/chimpstatic.com\/mcjs-connected\/js\/users\/3ec9f5a684c36f6bf11dc30fc\/1a983ba3b184a8fb5b6da3882.js?shop=the-print-room.myshopify.com","https:\/\/cdn.hextom.com\/js\/quickannouncementbar.js?shop=the-print-room.myshopify.com","https:\/\/app.popt.in\/pixel.js?id=e7ff5c60e84fb\u0026shop=the-print-room.myshopify.com"]; 423 for (var i = 0; i < urls.length; i++) { 424 var s = document.createElement('script'); 425 s.type = 'text/javascript'; 426 s.async = true; 427 s.src = urls[i]; 428 var x = document.getElementsByTagName('script')[0]; 429 x.parentNode.insertBefore(s, x); 430 } 431 }; 432 if(window.attachEvent) { 433 window.attachEvent('onload', asyncLoad); 434 } else { 435 window.addEventListener('load', asyncLoad, false); 436 } 437})();</script>
vendor: 1 bytes, line 437
437
438<script id="__st">var __st={"a":7054289,"offset":46800,"reqid":"75a7c00c-de80-4178-96de-a80299f317cf-1791103105","pageurl":"printroom.co\/cart","u":"6d6a63147c90","p":"cart"};</script>
vendor: 1 bytes, line 438
438
439<script>window.ShopifyPaypalV4VisibilityTracking = true;</script>
vendor: 1 bytes, line 439
439
440<script id="captcha-bootstrap">!function(){'use strict';const t='contact',e='account',n='new_comment',o=[[t,t],['blogs',n],['comments',n],[t,'customer']],c=[[e,'customer_login'],[e,'guest_login'],[e,'recover_customer_password'],[e,'create_customer']],r=t=>t.map((([t,e])=>`form[action*='/${t}']:not([data-nocaptcha='true']) input[name='form_type'][value='${e}']`)).join(','),a=t=>()=>t?[...document.querySelectorAll(t)].map((t=>t.form)):[];function s(){const t=[...o],e=r(t);return a(e)}const i='password',u='form_key',d=['recaptcha-v3-token','g-recaptcha-response','h-captcha-response',i],f=()=>{try{return window.sessionStorage}catch{return}},m='__shopify_v',_=t=>t.elements[u];function p(t,e,n=!1){try{const o=window.sessionStorage,c=JSON.parse(o.getItem(e)),{data:r}=function(t){const{data:e,action:n}=t;return t[m]||n?{data:e,action:n}:{data:t,action:n}}(c);for(const[e,n]of Object.entries(r))t.elements[e]&&(t.elements[e].value=n);n&&o.removeItem(e)}catch(o){console.error('form repopulation failed',{error:o})}}const l='form_type',E='cptcha';function T(t){t.dataset[E]=!0}const w=window,h=w.document,L='Shopify',v='ce_forms',y='captcha';let A=!1;((t,e)=>{const n=(g='f06e6c50-85a8-45c8-87d0-21a2b65856fe',I='https://cdn.shopify.com/shopifycloud/storefront-forms-hcaptcha/ce_storefront_forms_captcha_hcaptcha.v1.5.3.iife.js',D={infoText:'Protected by hCaptcha',privacyText:'Privacy',termsText:'Terms'},(t,e,n)=>{const o=w[L][v],c=o.bindForm;if(c)return c(t,g,e,D).then(n);var r;o.q.push([[t,g,e,D],n]),r=I,A||(h.body.append(Object.assign(h.createElement('script'),{id:'captcha-provider',async:!0,src:r})),A=!0)});var g,I,D;w[L]=w[L]||{},w[L][v]=w[L][v]||{},w[L][v].q=[],w[L][y]=w[L][y]||{},w[L][y].protect=function(t,e){n(t,void 0,e),T(t)},Object.freeze(w[L][y]),function(t,e,n,w,h,L){const[v,y,A,g]=function(t,e,n){const i=e?o:[],u=t?c:[],d=[...i,...u],f=r(d),m=r(i),_=r(d.filter((([t,e])=>n.includes(e))));return[a(f),a(m),a(_),s()]}(w,h,L),I=t=>{const e=t.target;return e instanceof HTMLFormElement?e:e&&e.form},D=t=>v().includes(t);t.addEventListener('submit',(t=>{const e=I(t);if(!e)return;const n=D(e)&&!e.dataset.hcaptchaBound&&!e.dataset.recaptchaBound,o=_(e),c=g().includes(e)&&(!o||!o.value);(n||c)&&t.preventDefault(),c&&!n&&(function(t){try{if(!f())return;!function(t){const e=f();if(!e)return;const n=_(t);if(!n)return;const o=n.value;o&&e.removeItem(o)}(t);const e=Array.from(Array(32),(()=>Math.random().toString(36)[2])).join('');!function(t,e){_(t)||t.append(Object.assign(document.createElement('input'),{type:'hidden',name:u})),t.elements[u].value=e}(t,e),function(t,e){const n=f();if(!n)return;const o=[...t.querySelectorAll(`input[type='${i}']`)].map((({name:t})=>t)),c=[...d,...o],r={};for(const[a,s]of new FormData(t).entries())c.includes(a)||(r[a]=s);n.setItem(e,JSON.stringify({[m]:1,action:t.action,data:r}))}(t,e)}catch(e){console.error('failed to persist form',e)}}(e),e.submit())}));const S=(t,e)=>{t&&!t.dataset[E]&&(n(t,e.some((e=>e===t))),T(t))};for(const o of['focusin','change'])t.addEventListener(o,(t=>{const e=I(t);D(e)&&S(e,y())}));const B=e.get('form_key'),M=e.get(l),P=B&&M;t.addEventListener('DOMContentLoaded',(()=>{const t=y();if(P)for(const e of t)e.elements[l].value===M&&p(e,B);[...new Set([...A(),...v().filter((t=>'true'===t.dataset.shopifyCaptcha))])].forEach((e=>S(e,t)))}))}(h,new URLSearchParams(w.location.search),n,t,e,['guest_login'])})(!0,!0)}();</script>
vendor: 1 bytes, line 440
440
441<script integrity="sha256-JjoPp5ZfB1sSAs5SQaol1x1GgvveM+BgmRzyDexInEQ=" data-source-attribution="shopify.loadfeatures" defer="defer" src="//printroom.co/cdn/shopifycloud/storefront/assets/storefront/load_feature-1bd60354.js" crossorigin="anonymous"></script>
vendor: 1 bytes, line 441
441
442<script>(function () {var userAgent = navigator.userAgent;var platform = navigator.platform;var maxTouchPoints = navigator.maxTouchPoints || 0;var isIOS = /iPad|iPhone|iPod/.test(platform) || (platform === 'MacIntel' && maxTouchPoints > 1);var isMacSafari = platform.indexOf('Mac') === 0 && /Safari/.test(userAgent) && !/Chrome|Chromium|CriOS|FxiOS|Edg|OPR|Android/.test(userAgent);var isAppleSafari = isIOS || isMacSafari;if (isAppleSafari) {fetch('/sf_private_access_tokens' + location.search).catch(function () {});}function browserMajorVersion(pattern) {var match = userAgent.match(pattern);return match ? parseInt(match[1], 10) : null;}function shouldLoadAutosizesPolyfill() {if (!window.PerformanceObserver?.supportedEntryTypes?.includes('paint')) {return false;}var chromeVersion = browserMajorVersion(/Chrome\/(\d+)/);if (chromeVersion !== null) {return chromeVersion < 126;}var firefoxVersion = browserMajorVersion(/Firefox\/(\d+)/);if (firefoxVersion !== null) {return firefoxVersion < 150;}var safariVersion = isAppleSafari ? browserMajorVersion(/Version\/(\d+).*Safari\//) : null;if (safariVersion !== null) {return safariVersion < 27;}return true;}if (shouldLoadAutosizesPolyfill()) {var autosizesScript = document.createElement('script');autosizesScript.async = true;autosizesScript.crossOrigin = 'anonymous';autosizesScript.src = "//printroom.co/cdn/shopifycloud/storefront/assets/storefront/autosizes-84416378.js";(document.head || document.documentElement).appendChild(autosizesScript);}window.ShopifyAnalytics = window.ShopifyAnalytics || {};window.ShopifyAnalytics.performance = window.ShopifyAnalytics.performance || {};(function () {var LONG_FRAME_THRESHOLD = 50;var longAnimationFrames = [];var activeRafId = null;function collectLongFrames() {var previousTime = null;function rafMonitor(now) {if (activeRafId === null) {return;}var delta = now - previousTime;if (delta > LONG_FRAME_THRESHOLD) {longAnimationFrames.push({startTime: previousTime,endTime: now,});}previousTime = now;activeRafId = requestAnimationFrame(rafMonitor);}previousTime = performance.now();activeRafId = requestAnimationFrame(rafMonitor);}if (!window.PerformanceObserver?.supportedEntryTypes?.includes('long-animation-frame')) {collectLongFrames();var timeoutId = setTimeout(function () {cancelAnimationFrame(activeRafId);}, 10000);window.ShopifyAnalytics.performance.getLongAnimationFrames = function (stopCollection) {if (stopCollection === undefined) {stopCollection = false;}if (stopCollection) {clearTimeout(timeoutId);cancelAnimationFrame(activeRafId);}return longAnimationFrames;};}})();})();</script>
442<script crossorigin="anonymous" defer="defer" src="//printroom.co/cdn/shopifycloud/storefront/assets/shopify_pay/storefront-616277c7.js?v=20250812"></script>
vendor: 1 bytes, line 442
442
443<script id="shopify-origin-trials" async="async" integrity="sha256-qJbe/jEZBHtr5W/BlA2cKAz3vkXu6vJQyLjgvgCC86g=" src="//cdn.shopify.com/shopifycloud/storefront/assets/storefront/origin_trials-318ab40a.js" crossorigin="anonymous" onload="window.__shopifyOriginTrialsDone = true" onerror="window.__shopifyOriginTrialsDone = true"></script>
vendor: 1 bytes, line 443
443
444<script> 445 window.Shopify = window.Shopify || {}; 446 window.Shopify.MCP = window.Shopify.MCP || {}; 447 window.Shopify.MCP.enabled = true; 448 window.Shopify.MCP.shop = "the-print-room.myshopify.com"; 449 window.Shopify.MCP.mcpEndpoint = "https:\/\/printroom.co\/api\/mcp"; 450 window.Shopify.MCP.tools = [{"name":"search_shop_policies_and_faqs","description":"Used to get facts about the stores policies, products, or services.\nSome examples of questions you can ask are:\n - What is your return policy?\n - What is your shipping policy?\n - What is your phone number?\n - What are your hours of operation?\"\n","inputSchema":{"$schema":"https:\/\/json-schema.org\/draft\/2020-12\/schema","type":"object","properties":{"query":{"type":"string","description":"A natural language query."},"context":{"type":"string","description":"Additional information about the request such as user demographics, mood, location, or other relevant details that could help in tailoring the response appropriately."}},"required":["query"]}}]; 451</script>
vendor: 1 bytes, line 451
451
452<script>(()=>{var d="shopify:webmcp_adapter_loaded",n=Symbol.for("shopify.webmcp_adapter_loading");function s(c,a,{win:r=window,doc:o=document}={}){function p(){try{return r.localStorage.getItem(d)==="true"}catch{return!1}}function l(){try{r.localStorage.setItem(d,"true")}catch{}}function u(){return typeof(o.modelContext||r.navigator?.modelContext)?.registerTool=="function"}function f(){if(r[n]||!u())return;let t=o.head||o.getElementsByTagName("head")[0];if(!t)return;let e=o.createElement("script");e.type="module",e.crossOrigin="anonymous",a&&(e.integrity=a),e.src=c,e.addEventListener("load",l,{once:!0}),e.addEventListener("error",()=>{r[n]=!1},{once:!0}),t.appendChild(e),r[n]=!0}function _(t){let e=o.getElementById("shopify-origin-trials");if(!e||r.__shopifyOriginTrialsDone){t();return}e.addEventListener("load",t,{once:!0}),e.addEventListener("error",t,{once:!0})}function i(){_(()=>r.setTimeout(f,0))}function m(){o.addEventListener("DOMContentLoaded",i,{once:!0})}p()?i():m()}s("\/\/printroom.co\/cdn\/shopifycloud\/storefront\/assets\/storefront\/webmcp-c6b62ece.js","sha256-ke4DDuBjdvea3vxLWxHc9E9nq8zihuG4IfYEGbb77ys=");})(); 453</script>
vendor: 1 bytes, line 453
453
454<script data-source-attribution="shopify.dynamic_checkout.dynamic.init">var Shopify=Shopify||{};Shopify.PaymentButton=Shopify.PaymentButton||{isStorefrontPortableWallets:!0,init:function(){window.Shopify.PaymentButton.init=function(){};var t=document.createElement("script");t.src="https://printroom.co/cdn/shopifycloud/portable-wallets/latest/portable-wallets.en.js",t.type="module",document.head.appendChild(t)}}; 455</script>
vendor: 1 bytes, line 455
455
456<script data-source-attribution="shopify.dynamic_checkout.buyer_consent"> 457 function portableWalletsHideBuyerConsent(e){var t=document.getElementById("shopify-buyer-consent"),n=document.getElementById("shopify-subscription-policy-button");t&&n&&(t.classList.add("hidden"),t.setAttribute("aria-hidden","true"),n.removeEventListener("click",e))}function portableWalletsShowBuyerConsent(e){var t=document.getElementById("shopify-buyer-consent"),n=document.getElementById("shopify-subscription-policy-button");t&&n&&(t.classList.remove("hidden"),t.removeAttribute("aria-hidden"),n.addEventListener("click",e))}window.Shopify?.PaymentButton&&(window.Shopify.PaymentButton.hideBuyerConsent=portableWalletsHideBuyerConsent,window.Shopify.PaymentButton.showBuyerConsent=portableWalletsShowBuyerConsent); 458</script>
vendor: 1 bytes, line 458
458
459<script data-source-attribution="shopify.dynamic_checkout.cart.bootstrap">document.addEventListener("DOMContentLoaded",(function(){function t(){return document.querySelector("shopify-accelerated-checkout-cart, shopify-accelerated-checkout")}if(t())Shopify.PaymentButton.init();else{new MutationObserver((function(e,n){t()&&(Shopify.PaymentButton.init(),n.disconnect())})).observe(document.body,{childList:!0,subtree:!0})}})); 460</script>
460 461<link id="shopify-accelerated-checkout-styles" rel="stylesheet" media="screen" href="https://printroom.co/cdn/shopifycloud/portable-wallets/latest/accelerated-checkout-backwards-compat.css" crossorigin="anonymous"> 462<style id="shopify-accelerated-checkout-cart"> 463 #shopify-buyer-consent { 464 margin-top: 1em; 465 display: inline-block; 466 width: 100%; 467} 468 469#shopify-buyer-consent.hidden { 470 display: none; 471} 472 473#shopify-subscription-policy-button { 474 background: none; 475 border: none; 476 padding: 0; 477 text-decoration: underline; 478 font-size: inherit; 479 cursor: pointer; 480} 481 482#shopify-subscription-policy-button::before { 483 box-shadow: none; 484} 485 486 </style> 487
488<script id="shopify-cfh-end">window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.end');</script>
488 489 490 491 492 493 <link 494 rel="preload" 495 as="font" 496 href="//printroom.co/cdn/fonts/dm_sans/dmsans_n5.8a0f1984c77eb7186ceb87c4da2173ff65eb012e.woff2" 497 type="font/woff2" 498 crossorigin 499 > 500 501 502 503 <link 504 rel="preload" 505 as="font" 506 href="//printroom.co/cdn/fonts/dm_sans/dmsans_n4.ec80bd4dd7e1a334c969c265873491ae56018d72.woff2" 507 type="font/woff2" 508 crossorigin 509 > 510 511 512 513<style data-shopify> 514 @font-face { 515 font-family: "DM Sans"; 516 font-weight: 400; 517 font-style: normal; 518 font-display: swap; 519 src: url("//printroom.co/cdn/fonts/dm_sans/dmsans_n4.ec80bd4dd7e1a334c969c265873491ae56018d72.woff2") format("woff2"), 520 url("//printroom.co/cdn/fonts/dm_sans/dmsans_n4.87bdd914d8a61247b911147ae68e754d695c58a6.woff") format("woff"); 521} 522 523 @font-face { 524 font-family: "DM Sans"; 525 font-weight: 500; 526 font-style: normal; 527 font-display: swap; 528 src: url("//printroom.co/cdn/fonts/dm_sans/dmsans_n5.8a0f1984c77eb7186ceb87c4da2173ff65eb012e.woff2") format("woff2"), 529 url("//printroom.co/cdn/fonts/dm_sans/dmsans_n5.9ad2e755a89e15b3d6c53259daad5fc9609888e6.woff") format("woff"); 530} 531 532@font-face { 533 font-family: "DM Sans"; 534 font-weight: 700; 535 font-style: normal; 536 font-display: swap; 537 src: url("//printroom.co/cdn/fonts/dm_sans/dmsans_n7.97e21d81502002291ea1de8aefb79170c6946ce5.woff2") format("woff2"), 538 url("//printroom.co/cdn/fonts/dm_sans/dmsans_n7.af5c214f5116410ca1d53a2090665620e78e2e1b.woff") format("woff"); 539} 540@font-face { 541 font-family: "DM Sans"; 542 font-weight: 400; 543 font-style: italic; 544 font-display: swap; 545 src: url("//printroom.co/cdn/fonts/dm_sans/dmsans_i4.b8fe05e69ee95d5a53155c346957d8cbf5081c1a.woff2") format("woff2"), 546 url("//printroom.co/cdn/fonts/dm_sans/dmsans_i4.403fe28ee2ea63e142575c0aa47684d65f8c23a0.woff") format("woff"); 547} 548@font-face { 549 font-family: "DM Sans"; 550 font-weight: 700; 551 font-style: italic; 552 font-display: swap; 553 src: url("//printroom.co/cdn/fonts/dm_sans/dmsans_i7.52b57f7d7342eb7255084623d98ab83fd96e7f9b.woff2") format("woff2"), 554 url("//printroom.co/cdn/fonts/dm_sans/dmsans_i7.d5e14ef18a1d4a8ce78a4187580b4eb1759c2eda.woff") format("woff"); 555} 556@font-face { 557 font-family: "DM Sans"; 558 font-weight: 700; 559 font-style: normal; 560 font-display: swap; 561 src: url("//printroom.co/cdn/fonts/dm_sans/dmsans_n7.97e21d81502002291ea1de8aefb79170c6946ce5.woff2") format("woff2"), 562 url("//printroom.co/cdn/fonts/dm_sans/dmsans_n7.af5c214f5116410ca1d53a2090665620e78e2e1b.woff") format("woff"); 563} 564</style> 565 566<style>:root { 567 568 --font-size-xs: 0.64rem; 569 --font-size-sm: 0.8rem; 570 --font-size-base: 1rem; 571 --font-size-lg: 1.25rem; 572 --font-size-xl: 1.563rem; 573 --font-size-2xl: 1.953rem; 574 --font-size-3xl: 2.441rem; 575 --font-size-4xl: 3.052rem; 576 --font-size-5xl: 3.815rem; 577 --font-size-6xl: 4.768rem; 578 --font-size-7xl: 5.96rem; 579 --font-size-8xl: 7.451rem; 580 --font-size-9xl: 9.313rem; 581 582 --type-scale-n-2: var(--font-size-xs); 583 --type-scale-n-1: var(--font-size-sm); 584 --type-scale-n0: var(--font-size-base); 585 --type-scale-n1: var(--font-size-lg); 586 --type-scale-n2: var(--font-size-xl); 587 --type-scale-n3: var(--font-size-2xl); 588 --type-scale-n4: var(--font-size-3xl); 589 --type-scale-n5: var(--font-size-4xl); 590 --type-scale-n6: var(--font-size-5xl); 591 --type-scale-n7: var(--font-size-6xl); 592 --type-scale-n8: var(--font-size-7xl); 593 --type-scale-n9: var(--font-size-8xl); 594 --type-scale-n10: var(--font-size-9xl); 595 596 --base-font-size: 93.75%; 597 --base-font-size-from-settings: 15; 598 --base-line-height: 1.2; 599 --heading-line-height: 1; 600 601 font-size: var(--base-font-size); 602 line-height: var(--base-line-height); 603 604 --heading-font-stack: "DM Sans", sans-serif; 605 --heading-font-weight: 500; 606 --heading-font-style: normal; 607 608 609 --body-font-stack: "DM Sans", sans-serif; 610 --body-font-weight: 400; 611 --body-font-bold: FontDrop; 612 --body-font-bold-italic: FontDrop; 613 614 --color-gridline: 30 35 38; 615 --gridline-width: 0px; 616 617 --text-border-width: 1px; 618 --checkbox-width: 1px; 619 620 --font-heading: "DM Sans", sans-serif; 621 --font-body: "DM Sans", sans-serif; 622 --font-body-weight: 400; 623 --font-body-style: normal; 624 --font-body-bold-weight: bold; 625 626 --heading-letterspacing: -0.025em; 627 --heading-capitalize: none; 628 --heading-decoration: none; 629 630 --standard-heading-size: var(--type-scale-n3); 631 --feature-heading-size: var(--type-scale-n4); 632 --secondary-heading-size: var(--type-scale-n2); 633 634 --body-copy-transform: none; 635 636 --wrapperWidth: 100vw; 637 --gutter: 0px; 638 --rowHeight: calc((var(--wrapperWidth) - (11 * var(--gutter))) / 12); 639 640 --global-scrolling-items-speed-multiplier: 1; 641 642 --add-to-cart-button-height: 44px; 643 --checkout-button-height: 44px; 644 645 --spacing: 1rem; 646 --spacing-double: 2rem; 647 --spacing-half: 0.5rem; 648 649 /* Equivalent to px-2 */ 650 --section-horizontal-spacing-mobile: 0.5rem; 651 /* Equivalent to px-4 */ 652 --section-horizontal-spacing-desktop: 1rem; 653 654 --section-horizontal-spacing: var(--section-horizontal-spacing-mobile); 655 656 --icon-thickness: 1.5; 657 658 /** 659 * Buttons 660 */ 661 --button-text-transform: none; 662 --button-after-content: '\00a0\2192'; 663 --button-border-radius: 9999px; 664 665 /** 666 * Links 667 */ 668 --links-bottom-border-width: var(--text-border-width); 669 --links-bottom-padding: 0.25rem; 670 --links-text-transform: none; 671 --links-after-content: '\00a0\2192'; 672 --links-before-content: '\2190\00a0'; 673 674 background-color: rgb(var(--color-scheme-background)); 675 color: rgb(var(--color-scheme-text)); 676 } 677 678 @media (min-width: 1024px) { 679 :root { 680 --standard-heading-size: var(--type-scale-n5); 681 --feature-heading-size: var(--type-scale-n6); 682 --secondary-heading-size: var(--type-scale-n3); 683 684 --section-horizontal-spacing: var(--section-horizontal-spacing-desktop); 685 } 686 } 687 688 :root, 689 690 [data-color-scheme="scheme1"] { 691 --color-scheme-text: 43 57 144; 692 --color-scheme-background: 255 255 255; 693 --color-scheme-accent: 248 250 244; 694 --color-scheme-accent-contrast: 43 57 144; 695 --color-scheme-secondary: 30 35 38; 696 } 697 698 [data-color-scheme="scheme2"] { 699 --color-scheme-text: 30 35 38; 700 --color-scheme-background: 241 255 165; 701 --color-scheme-accent: 194 194 194; 702 --color-scheme-accent-contrast: 30 35 38; 703 --color-scheme-secondary: 30 35 38; 704 } 705 706 [data-color-scheme="scheme3"] { 707 --color-scheme-text: 248 250 244; 708 --color-scheme-background: 43 57 144; 709 --color-scheme-accent: 248 250 244; 710 --color-scheme-accent-contrast: 241 255 165; 711 --color-scheme-secondary: 43 57 144; 712 } 713 714 [data-color-scheme="scheme4"] { 715 --color-scheme-text: 248 250 244; 716 --color-scheme-background: 30 35 38; 717 --color-scheme-accent: 248 250 244; 718 --color-scheme-accent-contrast: 30 35 38; 719 --color-scheme-secondary: 248 250 244; 720 } 721 722 [data-color-scheme="scheme5"] { 723 --color-scheme-text: 30 35 38; 724 --color-scheme-background: 255 255 255; 725 --color-scheme-accent: 30 35 38; 726 --color-scheme-accent-contrast: 255 255 255; 727 --color-scheme-secondary: 30 35 38; 728 } 729 730 [data-color-scheme="scheme-62a93d7b-1ea3-42af-a18d-30461b13240a"] { 731 --color-scheme-text: 255 255 255; 732 --color-scheme-background: 255 255 255; 733 --color-scheme-accent: 255 255 255; 734 --color-scheme-accent-contrast: 255 255 255; 735 --color-scheme-secondary: 255 255 255; 736 } 737 738 [data-color-scheme="scheme-7c315ead-1873-415d-a1a8-a7722419ef69"] { 739 --color-scheme-text: 43 57 144; 740 --color-scheme-background: 255 255 255; 741 --color-scheme-accent: 30 35 38; 742 --color-scheme-accent-contrast: 30 35 38; 743 --color-scheme-secondary: 30 35 38; 744 } 745 746 [data-color-scheme="scheme-6641fd8c-0fdd-4ed9-bd94-b490824d6125"] { 747 --color-scheme-text: 30 35 38; 748 --color-scheme-background: 72 127 249; 749 --color-scheme-accent: 248 250 244; 750 --color-scheme-accent-contrast: 30 35 38; 751 --color-scheme-secondary: 30 35 38; 752 } 753 754 755 [data-color-scheme] { 756 --payment-terms-background-color: rgb(var(--color-scheme-background)); 757 758 --button-color-border: var(--color-scheme-text); 759 --button-color-background: var(--color-scheme-accent); 760 --button-color-text: var(--color-scheme-accent-contrast); 761 --button-color-border-hover: var(--color-scheme-text); 762 --button-color-background-hover: var(--color-scheme-text); 763 --button-color-text-hover: var(--color-scheme-background); 764 } 765 766 ::selection { 767 background-color: rgb(var(--color-scheme-accent)); 768 color: rgb(var(--color-scheme-accent-contrast)); 769 } 770
771 @keyframes scrolling-items { 772 0% { 773 transform: translate3d(0, 0, 0); 774 } 775 776 100% { 777 transform: translate3d(-50%, 0, 0); 778 } 779 } 780</style> 781 782<style id="generated-critical-css"> 783image-with-placeholder{display:block}.theme-button,.theme-button--secondary{cursor:pointer;font-size:var(--font-size-base);line-height:var(--base-line-height);overflow-wrap:anywhere;padding:.5rem 2rem;text-transform:var(--button-text-transform);word-break:normal}.theme-button--secondary:after,.theme-button:after{--tw-content:var(--button-after-content);content:var(--tw-content)}.theme-button{--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1;background-color:rgb(var(--button-color-background)/var(--tw-bg-opacity,1));border-color:rgb(var(--button-color-border)/var(--tw-border-opacity,1));border-radius:var(--button-border-radius);border-width:var(--text-border-width);color:rgb(var(--button-color-text)/var(--tw-text-opacity,1))}@media (hover:hover) and (pointer:fine){.theme-button:hover{--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1;background-color:rgb(var(--button-color-background-hover)/var(--tw-bg-opacity,1));border-color:rgb(var(--button-color-border-hover)/var(--tw-border-opacity,1));color:rgb(var(--button-color-text-hover)/var(--tw-text-opacity,1))}}.theme-button--secondary{--tw-border-opacity:1;--tw-bg-opacity:1;--tw-text-opacity:1;background-color:rgb(var(--color-scheme-background)/var(--tw-bg-opacity,1));border-color:rgb(var(--color-scheme-text)/var(--tw-border-opacity,1));border-radius:var(--button-border-radius);border-width:var(--text-border-width);color:rgb(var(--color-scheme-text)/var(--tw-text-opacity,1))}[data-color-scheme] .theme-button--secondary.rte a:hover,[data-color-scheme].theme-button--secondary .rte a:hover,[data-color-scheme].theme-button--secondary.rte a:hover{color:rgb(var(--color-scheme-accent));text-decoration-color:rgb(var(--color-scheme-accent))}[data-color-scheme] .theme-button--secondary.rte blockquote,[data-color-scheme].theme-button--secondary .rte blockquote,[data-color-scheme].theme-button--secondary.rte blockquote{background:rgb(var(--color-scheme-text));color:rgb(var(--color-scheme-background))}@media (hover:hover) and (pointer:fine){.theme-button--secondary:hover{--tw-border-opacity:1;--tw-text-opacity:1;border-color:rgb(var(--color-scheme-accent)/var(--tw-border-opacity,1));color:rgb(var(--color-scheme-accent)/var(--tw-text-opacity,1))}}[data-shopify-xr-hidden]{display:none}.block{display:block}.inline-block{display:inline-block}.hidden{display:none}.shopify-payment-button__button--hidden{display:none!important}.splide:not(.is-active) .\[\.splide\:not\(\.is-active\)_\&\]\:pointer-events-none{pointer-events:none}.splide:not(.is-active) .\[\.splide\:not\(\.is-active\)_\&\]\:invisible{visibility:hidden}.splide:not(.is-active) .\[\.splide\:not\(\.is-active\)_\&\]\:\!flex{display:flex!important}.splide:not(.is-active) .\[\.splide\:not\(\.is-active\)_\&\]\:gap-gridline{gap:var(--gridline-width)}@media not all and (min-width:1024px){.splide:not(.is-active) .max-lg\:\[\.splide\:not\(\.is-active\)_\&\]\:hidden{display:none}} 784</style> 785<style id="manual-critical-css"> 786 html { 787 background-color: rgb(var(--color-primary-background)); 788 color: rgb(var(--color-primary-text)); 789 font-size: var(--base-font-size); 790 line-height: var(--base-line-height); 791 } 792 793 [x-cloak] { 794 display: none; 795 } 796 797 data-island { 798 display: block; 799 } 800 801 html.no-js [x-cloak].no-js-undo-cloak { 802 display: revert; 803 } 804 805 body { 806 display: flex; 807 flex-direction: column; 808 min-height: 100vh; 809 } 810 811 @media (min-width: 768px) { 812 [md\:undo-x-cloak-block] { 813 display: block; 814 } 815 } 816 817 @media (max-width: 767px) { 818 [max-md\:undo-x-cloak-block] { 819 display: block; 820 } 821 } 822</style> 823 824 <style> 825 :root { 826 /* ââ Colors ââ */ 827 --pr-blue: #2B3990; 828 --pr-blue-hover: #232e75; 829 --pr-bright-blue: #487FF9; /* matches product-page volume-pricing table */ 830 --pr-bright-blue-hover: #3D6CD4; 831 --pr-bright-blue-rgb: 72 127 249; 832 --pr-bright-blue-hover-rgb: 61 108 212; 833 --dusky-purple: #4B4D72; 834 --dusky-purple-hover: #3d3f5e; 835 --slider-green: #658a6a; 836 --off-white: #FBFBF6; 837 --pill-bg: #EEE; 838 --pill-bg-hover: #e2e2e2; 839 --cant-find-bg: #EFFE9C; 840 841 /* ââ Typography ââ */ 842 --font-family: 'DM Sans', sans-serif;
843 --title-modal-size: 2.75rem; /* 44px */ 844 --title-modal-tracking: -0.05em; /* -2.2px */ 845 --title-drawer-size: 41px; 846 --title-drawer-tracking: -2px; 847 --body-size: 0.9375rem; /* 15px */ 848 --label-size: 0.8125rem; /* 13px */ 849 --pill-font-size: 0.66rem; /* ~10.65px */ 850 --cta-font-size: 1.5rem; /* 24px */ 851 --submit-font-size: 1.5rem; /* 24px */ 852 --input-font-size: 0.875rem; /* 14px */ 853 854 /* ââ Borders ââ */ 855 --border-modal: 2px solid black; 856 --border-drawer-left: 2px solid black; 857 --border-pill: 0.666px solid black; 858 --border-input: 1px solid black; 859 --border-cta: 2px solid var(--dusky-purple); 860 --border-chip: 0.4px solid black; 861 862 /* ââ Radii ââ */ 863 --radius-modal: 27px; 864 --radius-pill: 9999px; 865 --radius-input: 9999px; 866 --radius-textarea: 10px; 867 --radius-submit: 50px; 868 --radius-cta: 40px; 869 --radius-chip: 24px; 870 --radius-popover: 16px; 871 872 /* ââ Shadows ââ */ 873 --shadow-modal: 0 4px 13px 2px rgba(0, 0, 0, 0.1); 874 --shadow-popover: 0 10px 25px rgba(0, 0, 0, 0.1); 875 --shadow-slider-thumb: 0 2px 6px rgba(0, 0, 0, 0.15); 876 --shadow-focus: 0 0 0 3px rgba(43, 57, 144, 0.1); 877 878 /* ââ Sizing ââ */ 879 --product-image-drawer: 90px; 880 --product-image-modal: 53px; 881 --pill-height: 23px; 882 --submit-height: 70px; 883 --submit-max-width: 351px; 884 --start-quote-height: 79px; 885 --input-min-height: 2.75rem; /* 44px */ 886 --slider-thumb-size: 24px; 887 --slider-track-height: 6px; 888 --cta-width: 153px; 889 --cta-height: 47px; 890 --chip-width: 90px; 891 --chip-height: 21px; 892 893 /* ââ Aliases (backward compat) ââ */ 894 --color-quote-accent: var(--pr-blue); 895 } 896</style> 897 898 899 <link rel="preload" href="//printroom.co/cdn/shop/t/59/assets/base.bundle.css?v=77867960145098054751787098434" as="style" onload="this.onload=null;this.rel='stylesheet'"> 900 <noscript><link rel="stylesheet" href="//printroom.co/cdn/shop/t/59/assets/base.bundle.css?v=77867960145098054751787098434"></noscript> 901 902 <link rel="preload" href="//printroom.co/cdn/shop/t/59/assets/styles.css?v=1691680456440492591789529106" as="style" onload="this.onload=null;this.rel='stylesheet'"> 903 <noscript><link rel="stylesheet" href="//printroom.co/cdn/shop/t/59/assets/styles.css?v=1691680456440492591789529106"></noscript> 904 905<meta property="og:site_name" content="The Print Room"> 906<meta property="og:locale" content="en"><meta property="og:locale:alternate" content="en_NZ"><meta property="og:url" content="https://printroom.co/cart"><meta property="og:title" content=" 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921Your Shopping Cart 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937| The Print Room 938"> 939<meta property="og:type" content="website"> 940<meta property="og:description" content="NZâs experts in custom t-shirt printing, tote bags, uniforms, and branded merchandise. Print Room offers high-quality screen printing and embroidery using eco-friendly inks. Fast turnaround, sustainable production, and trusted by leading New Zealand brands."> 941<meta property="og:image" content="https://printroom.co/cdn/shop/files/PrintRoomNovember2024-13_507c1311-d6fa-40ae-ae11-a74b59c4faec.jpg?v=1753319129"> 942<meta 943 property="og:image:secure_url" 944 content="https://printroom.co/cdn/shop/files/PrintRoomNovember2024-13_507c1311-d6fa-40ae-ae11-a74b59c4faec.jpg?v=1753319129" 945 > 946 <meta property="og:image:width" content="2048"> 947 <meta property="og:image:height" content="1367"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content=" 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962Your Shopping Cart 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978| The Print Room 979"> 980<meta name="twitter:description" content="NZâs experts in custom t-shirt printing, tote bags, uniforms, and branded merchandise. Print Room offers high-quality screen printing and embroidery using eco-friendly inks. Fast turnaround, sustainable production, and trusted by leading New Zealand brands.">
981<script> 982 window.THEMENAME = 'Baseline'; 983 window.THEMEVERSION = '3.0.0'; 984 985 document.documentElement.className = document.documentElement.className.replace('no-js', 'js'); 986 987 function debounce(fn, wait) { 988 let t; 989 return (...args) => { 990 clearTimeout(t); 991 t = setTimeout(() => fn.apply(this, args), wait); 992 }; 993 } 994 995 window.theme = { 996 strings: { 997 loading: "Loading", 998 itemCountOne: "{{ count }} item", 999 itemCountOther: "{{ count }} items", 1000 addToCart: "Add to cart", 1001 soldOut: "Sold out", 1002 unavailable: "Unavailable", 1003 regularPrice: "Regular price", 1004 salePrice: "Sale price", 1005 sale: "Sale", 1006 unitPrice: "Unit price", 1007 unitPriceSeparator: "per", 1008 cartEmpty: "Your cart is currently empty.", 1009 cartCookies: "Enable cookies to use the shopping cart", 1010 update: "Update", 1011 quantity: "Quantity", 1012 discountedTotal: "Discounted total", 1013 regularTotal: "Regular total", 1014 priceColumn: "See Price column for discount details.", 1015 addedToCart: "Added to Cart!", 1016 cartError: "There was an error while updating your cart. Please try again.", 1017 cartAddError: "All {{ title }} are in your cart.", 1018 shippingCalculatorResultsTitleOne: "There is 1 rate:",
1019 shippingCalculatorResultsTitleMany: "There are {{ count }} rates:", 1020 }, 1021 routes: { 1022 root_url: "\/", 1023 predictive_search_url: "\/search\/suggest", 1024 cart_url: "\/cart", 1025 cart_add_url: "\/cart\/add", 1026 cart_change_url: "\/cart\/change", 1027 cart_update_url: "\/cart\/update", 1028 cart_clear_url: "\/cart\/clear", 1029 }, 1030 moneyFormat: "${{amount}}", 1031 moneyWithCurrencyFormat: "${{amount}} USD", 1032 get defaultMoneyFormat() { 1033 return this.moneyFormat; 1034 }, 1035 cartItemCount: 0, 1036 settings: { 1037 cartType: "page", 1038 openDrawerOnAddToCart: false 1039 }, 1040 info: { 1041 name: 'Baseline', 1042 } 1043 }; 1044</script>
vendor: 1 bytes, line 1044
1044
1045<script src="//printroom.co/cdn/shop/t/59/assets/utils.js?v=84782252304122448471787098437" defer></script>
1045 1046
1046<script src="//printroom.co/cdn/shop/t/59/assets/images.js?v=56710371490645595961787098434" defer></script>
1046 1047
1047<script> 1048 window.themeEventsDebugMode = false; 1049 </script>
1049 1050
1050<script src="//printroom.co/cdn/shop/t/59/assets/theme-events.js?v=133344252210966700221787098437" defer></script>
1050 1051 1052 1053 1054 1055 1056 <!-- "snippets/shogun-head.liquid" was not rendered, the associated app was uninstalled --> 1057
1057<script type="text/javascript"> 1058window.PunchoutSettings = { 1059 "cloud_url": "https://cloud.punchoutexpress.com", 1060 "token": "ba56ba1530c75285dc7e1f854b4ad1a1", 1061 "checkout_selector": "#main-cart-footer div.items-center", 1062 "checkout_text": "Transfer Cart", 1063 "cancel_selector": "#main-cart-footer div.items-center", 1064 "cancel_text": "Cancel", 1065 "hide_selector": "*[name=\"checkout\"],.shopify-payment-button,.additional-checkout-buttons,.additional-checkout-button, #main-cart-footer button.theme-button--secondary, #main-cart-footer button.text-button", 1066 "cart_container_selector": "#CartContainer,#CartDrawer,#ajaxifyModal" 1067 }; 1068</script>
1068 1069 1070 <!-- Punchout Cloud -->
1071<script src="https://cdn.cloud.punchoutexpress.com/cloud/assets-shopify/0.2.0/punchout.min.js?v5_24_0" defer="defer"></script>
1071 1072<style type="text/css">.btn-punchout-cancel {margin-left: 10px;}</style> 1073<!-- /Punchout Cloud --> 1074 1075 1076
1077<script> 1078(function() { 1079 console.log('[TWOA Punchout] Script loaded'); 1080 1081 // Check if we're on the Te Wananga page and Locksmith is present 1082 const isTWOAPage = window.location.pathname.includes('te-wananga-o-aotearoa'); 1083 console.log('[TWOA Punchout] Is TWOA page:', isTWOAPage); 1084 console.log('[TWOA Punchout] Current path:', window.location.pathname); 1085 1086 if (isTWOAPage) { 1087 // Check if punchout session is already active 1088 const urlParams = new URLSearchParams(window.location.search); 1089 const hasPunchoutSession = urlParams.has('punchout_sess_id'); 1090 console.log('[TWOA Punchout] Has punchout session:', hasPunchoutSession); 1091 1092 if (!hasPunchoutSession) { 1093 console.log('[TWOA Punchout] No punchout session detected, will auto-activate'); 1094 1095 // Wait for page to fully load, then activate punchout 1096 window.addEventListener('load', function() { 1097 // Check if there's a Locksmith password form visible 1098 const hasPasswordForm = document.querySelector('form[data-locksmith-form], input[type="password"][name*="lock"]'); 1099 1100 console.log('[TWOA Punchout] Page loaded - Has password form:', !!hasPasswordForm); 1101 1102 if (!hasPasswordForm) { 1103 // No password form = user has access, activate punchout immediately 1104 console.log('[TWOA Punchout] â Access granted - activating punchout session'); 1105 const punchoutId = Date.now().toString() + Math.random().toString(36).substring(2, 15); 1106 const newUrl = new URL(window.location.href); 1107 newUrl.searchParams.set('punchout_sess_id', punchoutId); 1108 1109 // Store in sessionStorage to persist across page navigation 1110 sessionStorage.setItem('twoa_punchout_active', 'true'); 1111 sessionStorage.setItem('twoa_punchout_id', punchoutId); 1112 console.log('[TWOA Punchout] Session ID:', punchoutId); 1113 1114 // Redirect with punchout parameter 1115 console.log('[TWOA Punchout] Redirecting to:', newUrl.toString()); 1116 window.location.href = newUrl.toString(); 1117 } else { 1118 console.log('[TWOA Punchout] Password form detected, waiting for login...'); 1119 1120 // Watch for form submission / successful login 1121 const checkForAccess = setInterval(function() { 1122 const formStillVisible = document.querySelector('form[data-locksmith-form], input[type="password"][name*="lock"]'); 1123 1124 if (!formStillVisible) { 1125 console.log('[TWOA Punchout] â Password form disappeared - activating punchout'); 1126 clearInterval(checkForAccess); 1127 1128 const punchoutId = Date.now().toString() + Math.random().toString(36).substring(2, 15); 1129 sessionStorage.setItem('twoa_punchout_active', 'true'); 1130 sessionStorage.setItem('twoa_punchout_id', punchoutId); 1131 1132 const newUrl = new URL(window.location.href); 1133 newUrl.searchParams.set('punchout_sess_id', punchoutId); 1134 window.location.href = newUrl.toString(); 1135 } 1136 }, 500); 1137 1138 // Stop after 30 seconds 1139 setTimeout(() => clearInterval(checkForAccess), 30000); 1140 } 1141 }); 1142 } else { 1143 // If punchout is already active, store it in session 1144 console.log('[TWOA Punchout] Punchout already active, storing in session'); 1145 sessionStorage.setItem('twoa_punchout_active', 'true'); 1146 sessionStorage.setItem('twoa_punchout_id', urlParams.get('punchout_sess_id')); 1147 } 1148 } 1149 1150 // Apply punchout session to all pages if Te Wananga session is active 1151 const storedPunchoutActive = sessionStorage.getItem('twoa_punchout_active'); 1152 const storedPunchoutId = sessionStorage.getItem('twoa_punchout_id'); 1153 console.log('[TWOA Punchout] Session storage - Active:', storedPunchoutActive, 'ID:', storedPunchoutId); 1154 1155 if (storedPunchoutActive === 'true' && storedPunchoutId) { 1156 const urlParams = new URLSearchParams(window.location.search); 1157 if (!urlParams.has('punchout_sess_id')) { 1158 console.log('[TWOA Punchout] Applying stored punchout session to current page'); 1159 const newUrl = new URL(window.location.href); 1160 newUrl.searchParams.set('punchout_sess_id', storedPunchoutId); 1161 window.history.replaceState({}, '', newUrl.toString()); 1162 console.log('[TWOA Punchout] URL updated:', newUrl.toString()); 1163 1164 // Reinitialize punchout if the script is loaded 1165 if (window.PunchoutCloud && window.PunchoutCloud.init) { 1166 console.log('[TWOA Punchout] Reinitializing PunchoutCloud'); 1167 window.PunchoutCloud.init(); 1168 } 1169 } 1170 } 1171})(); 1172</script>
1172 1173 1174<!-- BEGIN app block: shopify://apps/one-tree-planted/blocks/index/1cbac389-d687-4afb-9e8a-26b6535fa1c2 -->
1174<script src="https://cdn.shopify.com/extensions/01a0f89b-d3f4-7fbc-a0d8-5474ae165888/reforestation-app-16/assets/script.js" defer></script>
1174 1175<!-- END app block -->
1175<script src="https://cdn.shopify.com/extensions/019d45d2-6a70-7eed-8da1-d1e8fd0fae86/fulfillment-fee-app-100/assets/fulfillment-fee-manager.js" type="text/javascript" defer="defer"></script>
1175 1176<link href="https://monorail-edge.shopifysvc.com" rel="dns-prefetch">
1177<script>(function(){if ("sendBeacon" in navigator && "performance" in window) {try {var session_token_from_headers = performance.getEntriesByType('navigation')[0].serverTiming.find(x => x.name == '_s').description;} catch {var session_token_from_headers = undefined;}var session_cookie_matches = document.cookie.match(/_shopify_s=([^;]*)/);var session_token_from_cookie = session_cookie_matches && session_cookie_matches.length === 2 ? session_cookie_matches[1] : "";var session_token = session_token_from_headers || session_token_from_cookie || "";function handle_abandonment_event(e) {var entries = performance.getEntries().filter(function(entry) {return /monorail-edge.shopifysvc.com/.test(entry.name);});if (!window.abandonment_tracked && entries.length === 0) {window.abandonment_tracked = true;var currentMs = Date.now();var navigation_start = performance.timing.navigationStart;var payload = {shop_id: 7054289,url: window.location.href,navigation_start,duration: currentMs - navigation_start,session_token,page_type: "cart"};window.navigator.sendBeacon("https://monorail-edge.shopifysvc.com/v1/produce", JSON.stringify({schema_id: "online_store_buyer_site_abandonment/1.1",payload: payload,metadata: {event_created_at_ms: currentMs,event_sent_at_ms: currentMs}}));}}window.addEventListener('pagehide', handle_abandonment_event);}}());</script>
vendor: 1 bytes, line 1177
1177
1178<script> 1179 window.__TREKKIE_SHIM_QUEUE = window.__TREKKIE_SHIM_QUEUE || []; 1180</script>
vendor: 1 bytes, line 1180
1180
1181<script>(function(){var wpmLoader=function(){"use strict";var e=/Googlebot|Storebot-Google|bingbot|Baiduspider|YandexBot|DuckDuckBot|Slurp|facebookexternalhit|Twitterbot|LinkedInBot|Applebot|AdsBot-Google|Mediapartners-Google|APIs-Google|PetalBot|SemrushBot|AhrefsBot|MJ12bot|DotBot|Acunetix|PerplexityBot|Perplexity-User/i,t=/bytedance/i;function i(){try{var e=document.cookie;if(!e||"string"!=typeof e)return;for(var t=0,i=e.split(";");t<i.length;t++){var n=i[t],r=n.indexOf("=");if(-1!==r){var o=n.slice(0,r).trim();if(o){var a=void 0;try{a=decodeURIComponent(o)}catch(e){a=o}if("_shopify_s"===a){var d=n.slice(r+1).trim();try{return decodeURIComponent(d)}catch(e){return d}}}}}return}catch(e){return}}function n(e){try{"undefined"!=typeof console&&"function"==typeof console.warn&&console.warn(e)}catch(e){}}function r(e,t){return"string"==typeof e&&e.length>0&&e.length<=t?e:void 0}function o(e){var t;switch(null==(t=null==e?void 0:e.navigation)?void 0:t.type){case 0:return"navigate";case 1:return"reload";case 2:return"back_forward";default:return}}function a(){var e,t,i;try{var n=null==(i=null==(t=null==(e=self.ShopifyAnalytics)?void 0:e.lib)?void 0:t.trekkie)?void 0:i.state;return"awaiting-consent"===n||"initialized"===n?n:void 0}catch(e){return}}return function(d,s,u,l){var c=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};try{var p=c.trekkieShim;!0!==p&&"true"!==p||null!=window.__TREKKIE_SHIM_QUEUE||(window.__TREKKIE_SHIM_QUEUE=[])}catch(e){}var f,v,h,y,g=(v=(f={modern:/Edge?\/(1{2}[4-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Firefox\/(1{2}[4-9]|1[2-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Chrom(ium|e)\/(9{2}|\d{3,})\.\d+(\.\d+|)|(Maci|X1{2}).+ Version\/(15\.\d+|(1[6-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( \(\w+\)|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(9{2}|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(15[._]\d+|(1[6-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Android.+Firefox\/(15\d|1[6-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|SamsungBrowser\/([2-9]\d|\d{3,})\.\d+/,legacy:/Edge?\/(1[6-9]|[2-9]\d|\d{3,})\.\d+(\.\d+|)|Firefox\/(5[4-9]|[6-9]\d|\d{3,})\.\d+(\.\d+|)|Chrom(ium|e)\/(5[1-9]|[6-9]\d|\d{3,})\.\d+(\.\d+|)([\d.]+$|.*Safari\/(?![\d.]+ Edge\/[\d.]+$))|(Maci|X1{2}).+ Version\/(10\.\d+|(1[1-9]|[2-9]\d|\d{3,})\.\d+)([,.]\d+|)( \(\w+\)|)( Mobile\/\w+|) Safari\/|Chrome.+OPR\/(3[89]|[4-9]\d|\d{3,})\.\d+\.\d+|(CPU[ +]OS|iPhone[ +]OS|CPU[ +]iPhone|CPU IPhone OS|CPU iPad OS)[ +]+(10[._]\d+|(1[1-9]|[2-9]\d|\d{3,})[._]\d+)([._]\d+|)|Android:?[ /-](14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})(\.\d+|)(\.\d+|)|Mobile Safari.+OPR\/([89]\d|\d{3,})\.\d+\.\d+|Android.+Firefox\/(15\d|1[6-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+Chrom(ium|e)\/(14[89]|1[5-9]\d|[2-9]\d{2}|\d{4,})\.\d+(\.\d+|)|Android.+(UC? ?Browser|UCWEB|U3)[ /]?(15\.([5-9]|\d{2,})|(1[6-9]|[2-9]\d|\d{3,})\.\d+)\.\d+|SamsungBrowser\/(5\.\d+|([6-9]|\d{2,})\.\d+)|Android.+MQ{2}Browser\/(14(\.(9|\d{2,})|)|(1[5-9]|[2-9]\d|\d{3,})(\.\d+|))(\.\d+|)|K[Aa][Ii]OS\/(3\.\d+|([4-9]|\d{2,})\.\d+)(\.\d+|)/}).modern,h=f.legacy,(y=navigator.userAgent).match(e)?"bot":y.match(v)?"modern":y.match(h)?"legacy":y.match(t)?"bot":"unknown"),m=function(e){var t,i,n=r(e,128);try{var a=window.performance,d=null==(t=null==a?void 0:a.getEntriesByType)?void 0:t.call(a,"navigation")[0];if(!d)return{requestId:n,navigationType:o(a)};var s="type"in d?r(d.type,64):void 0,u="serverTiming"in d&&Array.isArray(d.serverTiming)?d.serverTiming:[];return{requestId:null!=n?n:r(null==(i=u.find(function(e){return"requestID"===e.name}))?void 0:i.description,128),navigationType:s}}catch(e){return{requestId:n}}}(c.requestId),w=function(e){var t=e.version,r=e.browserTarget,o=e.surface,a=e.shopId,d=e.monorailEndpoint,s=window.location.href;return{emit:function(e){var u=e.status,l=e.errorMsg,c=e.failureReason,p=e.useKeepaliveFallback,f=void 0!==p&&p,v=e.navigationType,h=e.pagehidePersisted,y=e.requestId,g=e.trekkieState;if(d){var m,w;try{var b=(new Date).getTime();m=JSON.stringify({metadata:{event_sent_at_ms:b},events:[{schema_id:"web_pixels_manager_load/3.3",payload:{version:t,bundle_target:r,page_url:s,status:u,surface:o,error_msg:l,failure_reason:c,navigation_type:v,pagehide_persisted:h,request_id:y,trekkie_state:g,shop_id:a,visit_token:i()},metadata:{event_created_at_ms:b}}]})}catch(e){return}try{if("function"==typeof window.navigator.sendBeacon&&-1===(w=window.navigator.userAgent).indexOf("iPhone; CPU iPhone OS 12_")&&-1===w.indexOf("iPad; CPU OS 12_")&&-1===w.indexOf("iPod touch; CPU iPhone OS 12_")&&window.navigator.sendBeacon.bind(window.navigator)(d,m))return}catch(e){}if(f)try{"function"==typeof window.fetch&&window.fetch(d,{method:"POST",headers:{"Content-Type":"text/plain"},body:m,keepalive:!0}
1181).catch(function(){})}catch(e){}else try{var _=new XMLHttpRequest;_.open("POST",d,!0),_.setRequestHeader("Content-Type","text/plain"),_.send(m)}catch(e){n("[Web Pixels Manager] Got an unhandled error while logging to Monorail.")}}else n("[Web Pixels Manager] No Monorail endpoint provided, skipping logging.")}}}({version:u,browserTarget:g,surface:d.surface,shopId:d.shopId,monorailEndpoint:d.monorailEndpoint});if(Boolean(null==(_=null==(b=window.Shopify)?void 0:b.analytics)?void 0:_.replayQueue))w.emit({status:"setup-skipped",errorMsg:"replay queue already initialized."});else{var b,_;w.emit({status:"setup-started"}),window.Shopify=window.Shopify||{};var S=window.Shopify;S.analytics=S.analytics||{};var P=S.analytics;P.replayQueue=[],P.publish=function(e,t,i){return P.replayQueue.push([e,t,i]),!0};try{self.performance.mark("wpm:start")}catch(e){}var k,C="modern"===g?"modern":"legacy",E=(null!=l?l:{modern:"",legacy:""})[C],I=[(k={baseUrl:s,hashVersion:u,buildTarget:C}).baseUrl,"/wpm","/b",k.hashVersion,"modern"===k.buildTarget?"m":"l",".js"].join(""),O=!1,T=!1;try{c.browserTarget=g,function(){O=!0;try{window.addEventListener("pagehide",M)}catch(e){O=!1}}(),R(function(){try{R(x)}catch(e){D(e)}}),w.emit({status:"loading",requestId:m.requestId,navigationType:m.navigationType,trekkieState:a()})}catch(e){D(e)}}function U(){var e;if(q(),!function(){var e,t;return Boolean(null==(t=null==(e=window.Shopify)?void 0:e.analytics)?void 0:t.initialized)}()){var t,i,n;try{if("function"!=typeof(null==(e=window.webPixelsManager)?void 0:e.init))return void A();if(!(null!==(n=i=t=window.webPixelsManager.init(d))&&"function"!=typeof n&&Object(n)===n&&"publish"in i&&"function"==typeof i.publish&&"publishCustomEvent"in i&&"function"==typeof i.publishCustomEvent&&"visitor"in i&&"function"==typeof i.visitor))return void A()}catch(e){return void A(e)}var r=window.Shopify.analytics;r.replayQueue.forEach(function(e){var i=e[0],n=e[1],r=e[2];t.publishCustomEvent(i,n,r)}),r.replayQueue=[],r.publish=t.publishCustomEvent,r.visitor=t.visitor,r.initialized=!0}}function A(e){B("manager_api_unavailable",void 0===e?void 0:Q(e))}function x(){B("script_load_failed","".concat(I," has failed to load"))}function B(e,t){T||(T=!0,q(),w.emit({status:"failed",errorMsg:t,failureReason:e,requestId:m.requestId,navigationType:m.navigationType,trekkieState:a()}))}function M(e){O&&(q(),w.emit({status:"pagehide-while-loading",useKeepaliveFallback:!0,pagehidePersisted:e.persisted,requestId:m.requestId,navigationType:m.navigationType,trekkieState:a()}))}function q(){O=!1;try{window.removeEventListener("pagehide",M)}catch(e){}}function R(e){var t;!function(e){var t=e.src,i=e.async,n=void 0===i||i,r=e.onload,o=e.onerror,a=e.sri,d=e.scriptDataAttributes,s=void 0===d?{}:d,u=document.createElement("script"),l=document.querySelector("head"),c=document.querySelector("body");if(u.async=n,u.src=t,a&&(u.integrity=a,u.crossOrigin="anonymous"),s)for(var p in s)if(Object.prototype.hasOwnProperty.call(s,p))try{u.dataset[p]=String(s[p])}catch(e){}if(r&&u.addEventListener("load",r),o&&u.addEventListener("error",o),l)l.appendChild(u);else{if(!c)throw new Error("Did not find a head or body element to append the script");c.appendChild(u)}}({src:I,async:!0,onload:U,onerror:e,sri:(t=E,"string"==typeof t&&/^sha384-[A-Za-z0-9+/=]+$/.test(t)?E:""),scriptDataAttributes:c})}function D(e){B("script_append_failed",Q(e))}function Q(e){return e instanceof Error?e.message:"Unknown error"}}}();wpmLoader({shopId: 7054289,storefrontBaseUrl: "https://printroom.co",extensionsBaseUrl: "https://extensions.shopifycdn.com/cdn/shopifycloud/web-pixels-manager",monorailEndpoint: "https://printroom.co/.well-known/shopify/monorail/unstable/produce_batch",surface: "storefront-renderer",enabledBetaFlags: ["4c64608a","16072cab","8450a54b","7ee89bf1"],webPixelsConfigList: [{"id":"2246574150","configuration":"{\"accountID\":\"SWPcHh\",\"webPixelConfig\":\"eyJlbmFibGVBZGRlZFRvQ2FydEV2ZW50cyI6IHRydWV9\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"c63c5b72c8d77be5f2d27d14c081da38","type":"APP","apiClientId":123074,"privacyPurposes":["ANALYTICS","MARKETING"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":[]},"dataSharingState":"optimized","enabledFlags":["9a3ed68a"]},{"id":"2207776838","configuration":"{\"tagID\":\"2612346888626\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"7ae565e198624b39e0856d352b9a6b4c","type":"APP","apiClientId":3009811,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized"}
1181,{"id":"1975877702","configuration":"{\"mailchimp_store_id\":\"store_sgk5l8njdgd17w61safe\", \"mailchimp_user_id\":\"33995925\",\"mailchimp_list_id\":\"ef9b0a5c04\"}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"e357a49eadeb6216a959d63fa3fb8f55","type":"APP","apiClientId":2585307,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized","enabledFlags":["9a3ed68a"]},{"id":"462651462","configuration":"{\"config\":\"{\\\"google_tag_ids\\\":[\\\"G-7N7TTE08E9\\\",\\\"GT-KD7KB7H4\\\"],\\\"target_country\\\":\\\"ZZ\\\",\\\"gtag_events\\\":[{\\\"type\\\":\\\"search\\\",\\\"action_label\\\":\\\"G-7N7TTE08E9\\\"},{\\\"type\\\":\\\"begin_checkout\\\",\\\"action_label\\\":\\\"G-7N7TTE08E9\\\"},{\\\"type\\\":\\\"remove_from_cart\\\",\\\"action_label\\\":\\\"G-7N7TTE08E9\\\"},{\\\"type\\\":\\\"view_item\\\",\\\"action_label\\\":[\\\"G-7N7TTE08E9\\\",\\\"MC-1HQ5JHVSZ0\\\"]},{\\\"type\\\":\\\"purchase\\\",\\\"action_label\\\":[\\\"G-7N7TTE08E9\\\",\\\"MC-1HQ5JHVSZ0\\\"]},{\\\"type\\\":\\\"add_shipping_info\\\",\\\"action_label\\\":\\\"G-7N7TTE08E9\\\"},{\\\"type\\\":\\\"page_view\\\",\\\"action_label\\\":[\\\"G-7N7TTE08E9\\\",\\\"MC-1HQ5JHVSZ0\\\"]},{\\\"type\\\":\\\"view_item_list\\\",\\\"action_label\\\":\\\"G-7N7TTE08E9\\\"},{\\\"type\\\":\\\"add_payment_info\\\",\\\"action_label\\\":\\\"G-7N7TTE08E9\\\"},{\\\"type\\\":\\\"add_to_cart\\\",\\\"action_label\\\":\\\"G-7N7TTE08E9\\\"},{\\\"type\\\":\\\"view_cart\\\",\\\"action_label\\\":\\\"G-7N7TTE08E9\\\"}],\\\"enable_monitoring_mode\\\":false}\"}","eventPayloadVersion":"v1","runtimeContext":"OPEN","scriptVersion":"a3321ca85cf5aaf6b57585fcd8d67b3a","type":"APP","apiClientId":1780363,"privacyPurposes":[],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized","enabledFlags":["9a3ed68a"]},{"id":"171573318","configuration":"{\"pixel_id\":\"1516354578649796\",\"pixel_type\":\"facebook_pixel\",\"metaapp_system_user_token\":\"-\"}","eventPayloadVersion":"v1","runtimeContext":"OPEN","scriptVersion":"96420dbe9ea96c426a1b7f364f977719","type":"APP","apiClientId":2329312,"privacyPurposes":["ANALYTICS","MARKETING","SALE_OF_DATA"],"dataSharingAdjustments":{"protectedCustomerApprovalScopes":["read_customer_address","read_customer_email","read_customer_name","read_customer_personal_data","read_customer_phone"],"dataSharingControls":["share_all_events"]},"dataSharingState":"optimized","enabledFlags":["9a3ed68a"]},{"id":"shopify-app-pixel","configuration":"{}","eventPayloadVersion":"v1","runtimeContext":"STRICT","scriptVersion":"0530","apiClientId":"shopify-pixel","type":"APP","privacyPurposes":["ANALYTICS","MARKETING"]},{"id":"shopify-custom-pixel","eventPayloadVersion":"v1","runtimeContext":"LAX","scriptVersion":"0530","apiClientId":"shopify-pixel","type":"CUSTOM","privacyPurposes":["ANALYTICS","MARKETING"]}],isMerchantRequest: false,initData: {"shop":{"name":"The Print Room","paymentSettings":{"currencyCode":"NZD"},"myshopifyDomain":"the-print-room.myshopify.com","countryCode":"NZ","storefrontUrl":"https:\/\/printroom.co"},"customer":null,"cart":null,"checkout":null,"productVariants":[],"products":[],"purchasingCompany":null},},"https://printroom.co/cdn","5982071ew7ea472e3p69b68784m2150dfea",{"modern":"","legacy":""},{"trekkieShim":true,"agentContext":true,"apiClientId":"580111","facebookCapiEnabled":"false","themeId":"151830298694","themePublished":"true","eventMetadataId":"88381ba8-5b9d-4643-8282-ab6f2c15516c","pageType":"cart","shopId":"7054289","storefrontBaseUrl":"https:\/\/printroom.co","extensionBaseUrl":"https:\/\/extensions.shopifycdn.com\/cdn\/shopifycloud\/web-pixels-manager","surface":"storefront-renderer","enabledBetaFlags":"[\"4c64608a\", \"16072cab\", \"8450a54b\", \"7ee89bf1\"]","isMerchantRequest":"false","hashVersion":"5982071ew7ea472e3p69b68784m2150dfea","publish":"custom","events":"[[\"page_viewed\",{}]]"});})();</script>
1181<script> 1182 window.ShopifyAnalytics = window.ShopifyAnalytics || {}; 1183 window.ShopifyAnalytics.meta = window.ShopifyAnalytics.meta || {}; 1184 window.ShopifyAnalytics.meta.currency = 'USD'; 1185 var meta = {"page":{"pageType":"cart","requestId":"75a7c00c-de80-4178-96de-a80299f317cf-1791103105"}}; 1186 for (var attr in meta) { 1187 window.ShopifyAnalytics.meta[attr] = meta[attr]; 1188 } 1189</script>
vendor: 1 bytes, line 1189
1189
1190<script class="analytics"> 1191 (function () { 1192 var customDocumentWrite = function(content) { 1193 var jquery = null; 1194 1195 if (window.jQuery) { 1196 jquery = window.jQuery; 1197 } else if (window.Checkout && window.Checkout.$) { 1198 jquery = window.Checkout.$; 1199 } 1200 1201 if (jquery) { 1202 jquery('body').append(content); 1203 } 1204 }; 1205 1206 var hasLoggedConversion = function(token) { 1207 if (token) { 1208 return document.cookie.indexOf('loggedConversion=' + token) !== -1; 1209 } 1210 return false; 1211 } 1212 1213 var setCookieIfConversion = function(token) { 1214 if (token) { 1215 var twoMonthsFromNow = new Date(Date.now()); 1216 twoMonthsFromNow.setMonth(twoMonthsFromNow.getMonth() + 2); 1217 1218 document.cookie = 'loggedConversion=' + token + '; expires=' + twoMonthsFromNow; 1219 } 1220 } 1221 1222 var trekkie = window.ShopifyAnalytics.lib = window.trekkie = window.trekkie || []; 1223 window.ShopifyAnalytics.lib.trekkie = window.trekkie; 1224 if (trekkie.integrations) { 1225 return; 1226 } 1227 trekkie.methods = [ 1228 'identify', 1229 'page', 1230 'ready', 1231 'track', 1232 'trackForm', 1233 'trackLink' 1234 ]; 1235 trekkie.factory = function(method) { 1236 return function() { 1237 var args = Array.prototype.slice.call(arguments); 1238 args.unshift(method); 1239 trekkie.push(args); 1240 if (method == 'track' || method == 'page') { 1241 var pageUrl; 1242 try { 1243 pageUrl = window.location.href; 1244 } catch (e) {} 1245 var pageReferrer; 1246 try { 1247 pageReferrer = document.referrer; 1248 } catch (e) {} 1249 try { 1250 if (window.__TREKKIE_SHIM_QUEUE == null) { 1251 window.__TREKKIE_SHIM_QUEUE = []; 1252 } 1253 window.__TREKKIE_SHIM_QUEUE.push({ 1254 from: 'trekkie-stub', 1255 method: method, 1256 args: args.slice(1), 1257 pageContext: { 1258 url: pageUrl, 1259 referrer: pageReferrer 1260 } 1261 }); 1262 } catch (e) { 1263 // no-op 1264 } 1265 } 1266 return trekkie; 1267 }; 1268 }; 1269 for (var i = 0; i < trekkie.methods.length; i++) { 1270 var key = trekkie.methods[i]; 1271 trekkie[key] = trekkie.factory(key); 1272 } 1273 trekkie.load = function(config) { 1274 trekkie.config = config || {}; 1275 trekkie.config.initialDocumentCookie = document.cookie; 1276 var first = document.getElementsByTagName('script')[0]; 1277var script = document.createElement('script'); 1278script.type = 'text/javascript'; 1279script.onerror = function(e) { 1280 var scriptFallback = document.createElement('script'); 1281 scriptFallback.type = 'text/javascript'; 1282 scriptFallback.onerror = function(error) { 1283 var Monorail = { 1284 produce: function produce(monorailDomain, schemaId, payload) { 1285 var currentMs = new Date().getTime(); 1286 var event = { 1287 schema_id: schemaId, 1288 payload: payload, 1289 metadata: { 1290 event_created_at_ms: currentMs, 1291 event_sent_at_ms: currentMs 1292 } 1293 }; 1294 return Monorail.sendRequest("https://" + monorailDomain + "/v1/produce", JSON.stringify(event)); 1295 }, 1296 sendRequest: function sendRequest(endpointUrl, payload) { 1297 // Try the sendBeacon API 1298 if (window && window.navigator && typeof window.navigator.sendBeacon === 'function' && typeof window.Blob === 'function' && !Monorail.isIos12()) { 1299 var blobData = new window.Blob([payload], { 1300 type: 'text/plain' 1301 }); 1302 1303 if (window.navigator.sendBeacon(endpointUrl, blobData)) { 1304 return true; 1305 } // sendBeacon was not successful 1306 1307 } // XHR beacon 1308 1309 var xhr = new XMLHttpRequest(); 1310 1311 try { 1312 xhr.open('POST', endpointUrl); 1313 xhr.setRequestHeader('Content-Type', 'text/plain'); 1314 xhr.send(payload); 1315 } catch (e) { 1316 console.log(e); 1317 } 1318 1319 return false; 1320 }, 1321 isIos12: function isIos12() { 1322 return window.navigator.userAgent.lastIndexOf('iPhone; CPU iPhone OS 12_') !== -1 || window.navigator.userAgent.lastIndexOf('iPad; CPU OS 12_') !== -1; 1323 } 1324 }; 1325 Monorail.produce('monorail-edge.shopifysvc.com', 1326 'trekkie_storefront_load_errors/1.1', 1327 {shop_id: 7054289, 1328 theme_id: 151830298694, 1329 app_name: "storefront", 1330 context_url: window.location.href, 1331 source_url: "//printroom.co/cdn/s/trekkie.storefront.2f6d7d7ede7d24234881a9cd5f47e679642fa1f6.min.js"}); 1332 1333 }; 1334 scriptFallback.async = true; 1335 scriptFallback.src = '//printroom.co/cdn/s/trekkie.storefront.2f6d7d7ede7d24234881a9cd5f47e679642fa1f6.min.js'; 1336 first.parentNode.insertBefore(scriptFallback, first); 1337}; 1338script.async = true; 1339script.src = '//printroom.co/cdn/s/trekkie.storefront.2f6d7d7ede7d24234881a9cd5f47e679642fa1f6.min.js'; 1340first.parentNode.insertBefore(script, first); 1341 1342 }; 1343 trekkie.load( 1344 {"Trekkie":{"appName":"storefront","development":false,"defaultAttributes":{"shopId":7054289,"isMerchantRequest":null,"themeId":151830298694,"themeCityHash":"18288446332362764096","contentLanguage":"en","currency":"USD","eventMetadataId":"88381ba8-5b9d-4643-8282-ab6f2c15516c"},"isServerSideCookieWritingEnabled":true,"monorailRegion":"shop_domain","enabledBetaFlags":["764d78cb","8450a54b","7ee89bf1","4c64608a"]},"Session Attribution":{},"S2S":{"facebookCapiEnabled":false,"source":"trekkie-storefront-renderer","apiClientId":580111}} 1345 ); 1346 1347 var loaded = false;
1348 trekkie.ready(function() { 1349 if (loaded) return; 1350 loaded = true; 1351 1352 window.ShopifyAnalytics.lib = window.trekkie; 1353 1354 var originalDocumentWrite = document.write; 1355 document.write = customDocumentWrite; 1356 try { window.ShopifyAnalytics.merchantGoogleAnalytics.call(this); } catch(error) {}; 1357 document.write = originalDocumentWrite; 1358 1359 var match = window.location.pathname.match(/checkouts\/(.+)\/(thank_you|post_purchase)/) 1360 var token = match? match[1]: undefined; 1361 if (!hasLoggedConversion(token)) { 1362 setCookieIfConversion(token); 1363 1364 } 1365 }); 1366 1367 window.ShopifyAnalytics.lib.page(null,{"pageType":"cart","requestId":"75a7c00c-de80-4178-96de-a80299f317cf-1791103105","shopifyEmitted":true}); 1368 1369 var eventsListenerScript = document.createElement('script'); 1370 eventsListenerScript.async = true; 1371 eventsListenerScript.src = "//printroom.co/cdn/shopifycloud/storefront/assets/shop_events_listener-4e26a9ce.js"; 1372 document.getElementsByTagName('head')[0].appendChild(eventsListenerScript); 1373})();</script>
1373 1374
1374<script> 1375 if (!window.ga || (window.ga && typeof window.ga !== 'function')) { 1376 window.ga = function ga() { 1377 (window.ga.q = window.ga.q || []).push(arguments); 1378 if (window.Shopify && window.Shopify.analytics && typeof window.Shopify.analytics.publish === 'function') { 1379 window.Shopify.analytics.publish("ga_stub_called", {}, {sendTo: "google_osp_migration"}); 1380 } 1381 console.error("Shopify's Google Analytics stub called with:", Array.from(arguments), "\nSee https://help.shopify.com/manual/promoting-marketing/pixels/pixel-migration#google for more information."); 1382 }; 1383 if (window.Shopify && window.Shopify.analytics && typeof window.Shopify.analytics.publish === 'function') { 1384 window.Shopify.analytics.publish("ga_stub_initialized", {}, {sendTo: "google_osp_migration"}); 1385 } 1386 } 1387</script>
vendor: 1 bytes, line 1387
1387
1388<script 1389 defer 1390 src="https://printroom.co/cdn/shopifycloud/perf-kit/shopify-perf-kit-3.9.4.min.js" 1391 data-application="storefront-renderer" 1392 data-shop-id="7054289" 1393 data-render-region="gcp-us-central1" 1394 data-page-type="cart" 1395 data-theme-instance-id="151830298694" 1396 data-theme-name="Baseline" 1397 data-theme-version="3.3.1" 1398 data-monorail-region="shop_domain" 1399 data-resource-timing-sampling-rate="10" 1400 data-shs="true" 1401 data-shs-beacon="true" 1402 data-shs-export-with-fetch="true" 1403 data-shs-logs-sample-rate="1" 1404 data-shs-beacon-endpoint="https://printroom.co/api/collect" 1405></script>
1405 1406<meta name="shopify-y" content="ebfa40dd-f56d-47b8-b5ec-d07565e6bfe5" data-expiration="1822660705000"><meta name="shopify-s" content="da674f67-bf6a-409d-9c80-f5d363ce780b" data-expiration="1791104905000"><meta name="new-cookie-storage-activated" content="t"> 1407</head> 1408 1409 <body> 1410<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-W9DFFGB" 1411 height="0" width="0" style="display:none;visibility:hidden" title="gtm"></iframe></noscript> 1412 1413 <a class="skip-link" href="#MainContent">Skip to content</a> 1414 1415 <!-- BEGIN sections: header-group --> 1416<div id="shopify-section-sections--21296457187398__geo_market_banner" class="shopify-section shopify-section-group-header-group contents"> 1417 <style data-shopify> 1418 #shopify-section-sections--21296457187398__geo_market_banner [data-geo-market-banner] { 1419 position: sticky; 1420 top: 0; 1421 left: 0; 1422 right: 0; 1423 z-index: 40; 1424 display: block; 1425 width: 100%; 1426 padding: 0; 1427 border-bottom: 1px solid rgba(248, 250, 244, 0.18); 1428 background: #2b3990; 1429 color: #f8faf4; 1430 box-shadow: 0 14px 30px rgba(19, 27, 68, 0.18); 1431 pointer-events: auto; 1432 } 1433 1434 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__inner { 1435 display: grid; 1436 grid-template-columns: minmax(0, 1fr) auto; 1437 align-items: center; 1438 gap: 1rem 1.5rem; 1439 padding: 0.95rem var(--section-horizontal-spacing); 1440 } 1441 1442 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__message { 1443 margin: 0; 1444 max-width: 48rem; 1445 color: inherit; 1446 font-family: var(--font-body); 1447 font-size: var(--font-size-base); 1448 font-style: var(--font-body-style); 1449 font-weight: 500; 1450 letter-spacing: -0.01em; 1451 line-height: 1.45; 1452 } 1453 1454 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__actions { 1455 display: flex; 1456 flex-wrap: wrap; 1457 align-items: center; 1458 justify-content: flex-end; 1459 gap: 0.75rem; 1460 justify-self: end; 1461 } 1462 1463 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__button, 1464 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss { 1465 display: inline-flex; 1466 min-height: 2.875rem; 1467 align-items: center; 1468 justify-content: center; 1469 gap: 0.45rem; 1470 border-style: solid; 1471 border-width: var(--text-border-width); 1472 border-radius: var(--button-border-radius); 1473 font-family: var(--font-body); 1474 font-size: var(--font-size-base); 1475 font-style: var(--font-body-style); 1476 font-weight: 600; 1477 line-height: 1; 1478 text-decoration: none; 1479 text-transform: var(--button-text-transform); 1480 white-space: nowrap; 1481 transition: 1482 transform 0.18s ease, 1483 box-shadow 0.18s ease, 1484 background-color 0.18s ease, 1485 border-color 0.18s ease, 1486 color 0.18s ease, 1487 opacity 0.18s ease; 1488 } 1489 1490 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__button { 1491 padding: 0.8rem 1.35rem; 1492 border: 1px solid rgba(255, 255, 255, 0.12); 1493 background: #fbfbf6; 1494 box-shadow: 0 12px 24px rgba(14, 21, 52, 0.14); 1495 color: #2b3990; 1496 } 1497 1498 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss { 1499 padding: 0.8rem 1rem; 1500 border-color: rgba(248, 250, 244, 0.32); 1501 background: rgba(248, 250, 244, 0.08); 1502 box-shadow: none; 1503 color: inherit; 1504 opacity: 0.96; 1505 } 1506 1507 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss-icon { 1508 font-size: 0.95rem; 1509 line-height: 1; 1510 } 1511 1512 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__button:focus-visible, 1513 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss:focus-visible { 1514 outline: 2px solid #f8faf4; 1515 outline-offset: 2px; 1516 } 1517 1518 @media (hover: hover) and (pointer: fine) { 1519 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__button:hover, 1520 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss:hover { 1521 transform: translateY(-1px); 1522 } 1523 1524 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__button:hover { 1525 background: #ffffff; 1526 box-shadow: 0 16px 30px rgba(14, 21, 52, 0.18); 1527 } 1528 1529 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss:hover { 1530 border-color: rgba(248, 250, 244, 0.56); 1531 background: rgba(248, 250, 244, 0.16); 1532 opacity: 1; 1533 } 1534 } 1535 1536 @media (max-width: 767px) { 1537 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__inner { 1538 grid-template-columns: 1fr; 1539 align-items: stretch; 1540 gap: 0.9rem; 1541 } 1542 1543 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__message { 1544 max-width: none; 1545 } 1546 1547 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__actions { 1548 width: 100%; 1549 display: grid; 1550 grid-template-columns: 1fr; 1551 justify-content: stretch; 1552 justify-self: stretch; 1553 } 1554 1555 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__button { 1556 width: 100%; 1557 } 1558 1559 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss { 1560 justify-self: start; 1561 } 1562 } 1563 </style> 1564 1565 <data-island 1566 data-color-scheme="scheme3" 1567 x-data="GeoMarketBanner({ 1568 enabled: true, 1569 nzTargetUrl: "https:\/\/theprintroom.nz", 1570 intlTargetUrl: "https:\/\/printroom.co", 1571 auTargetUrl: "https:\/\/www.printroom.co\/en-au", 1572 messages: { 1573 fromInternational: "You're on our international site.", 1574 fromNz: "You're on our New Zealand site.", 1575 fromAu: "You're on our Australia site.", 1576 switchToNz: "Switch to New Zealand", 1577 switchToAu: "Switch to Australia", 1578 switchToInternational: "Switch to international",
1579 dismiss: "Dismiss" 1580 } 1581 })" 1582 role="region" 1583 aria-label="Regional site selector" 1584 x-show="shown" 1585 x-transition:enter="transition duration-300 motion-reduce:duration-0 outline-0" 1586 x-transition:enter-start="-translate-y-full" 1587 x-transition:enter-end="translate-y-0" 1588 x-transition:leave="transition duration-200 motion-reduce:duration-0 outline-0" 1589 x-transition:leave-start="translate-y-0" 1590 x-transition:leave-end="-translate-y-full" 1591 @keydown.escape.window="dismiss" 1592 id="sections--21296457187398__geo_market_banner" 1593 data-geo-market-banner 1594 style="display: none;" 1595 on="idle" 1596 src="//printroom.co/cdn/shop/t/59/assets/island-geo-market-banner.bundle.js?v=76971093760605141431787098434" 1597 > 1598 <div class="geo-market-banner__inner"> 1599 <p class="geo-market-banner__message"> 1600 <span x-text="message"></span> 1601 </p> 1602 <div class="geo-market-banner__actions"> 1603 <a 1604 class="geo-market-banner__button" 1605 :href="targetUrl" 1606 x-text="ctaLabel" 1607 @click="acceptSwitch($event)" 1608 ></a> 1609 <button 1610 class="geo-market-banner__dismiss" 1611 type="button" 1612 @click="dismiss" 1613 :aria-label="dismissLabel" 1614 > 1615 <span x-text="dismissLabel"></span> 1616 <span class="geo-market-banner__dismiss-icon" aria-hidden="true">Ã</span> 1617 </button> 1618 </div> 1619 </div> 1620 </data-island> 1621 1622 1623 1624</div><div id="shopify-section-sections--21296457187398__header" class="shopify-section shopify-section-group-header-group section-header relative z-20"> 1625 1626 1627<style data-shopify> 1628 1629 #shopify-section-sections--21296457187398__header { 1630 position: sticky; 1631 top: 0; 1632 z-index: 30; 1633 } 1634 1635 :root { 1636 --sticky-header-height: 66px; 1637 } 1638 1639 1640 #shopify-section-sections--21296457187398__header { 1641 --logo-max-width: 80px; 1642 } 1643 @media (min-width: 1024px) { 1644 #shopify-section-sections--21296457187398__header { 1645 --logo-max-width: 90px; 1646 } 1647 } 1648</style> 1649 1650<data-island 1651 x-data="Header" 1652 class="block" 1653 :class="{ 'is-stuck' : isStuck }" 1654 1655 data-sticky="true" 1656 1657 1658 data-color-scheme="scheme1" 1659 data-overlay-header-with-sticky="false" 1660 data-overlay-text-color-scheme="scheme1" 1661 id="sections--21296457187398__header" 1662 role="banner" 1663 data-theme-header 1664> 1665 1666 <sticky-header-height-helper hidden></sticky-header-height-helper> 1667 1668 <header 1669 x-ref="header" 1670 class="relative z-10 text-scheme-text header-glass" 1671 data-color-scheme="scheme1" 1672 > 1673 <nav 1674 class="relative hidden lg:block" 1675 aria-label="Primary" 1676 > 1677 <div class="flex items-stretch px-section-horizontal-spacing justify-between flex-wrap "> 1678 <div class="flex items-stretch"> 1679 1680 <div class="flex"> 1681 <a 1682 href="/" 1683 class="break-word my-auto inline-block py-4" 1684 > 1685 1686 1687 <div class="max-w-[var(--logo-max-width)]"> 1688 1689<img 1690 src="//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=90" 1691 srcset="//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=80 80w,//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=160 160w,//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=240 240w,//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=90 90w,//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=180 180w,//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=270 270w 1692 " 1693 width="543" 1694 height="397" 1695 loading="eager" 1696 1697 sizes="(min-width: 1024px) 90px, 80px" 1698 1699 alt="The Print Room" 1700 1701 > 1702 1703 1704 1705 </div> 1706 1707 1708 </a> 1709 </div> 1710 1711 1712 </div> 1713 1714 1715 1716 1717 1718 <a 1719 1720 class="flex py-4 relative self-stretch inline-flex flex-col" 1721 href="/collections/product-library" 1722 >
1723 <span class="m-auto inline-block">Products</span></a> 1724 1725 1726<data-island 1727 x-data="{ 1728 expanded: false, 1729 hoverTimeout: null, 1730 openDropdown() { 1731 clearTimeout(this.hoverTimeout); 1732 this.expanded = true; 1733 this.$nextTick(() => { 1734 const header = this.$el.closest('header'); 1735 const dd = this.$el.querySelector('.dropdown-glass'); 1736 if (header && dd) { 1737 header.style.setProperty('--dropdown-h', dd.offsetHeight + 'px'); 1738 } 1739 }); 1740 }, 1741 closeDropdown() { 1742 this.hoverTimeout = setTimeout(() => { 1743 this.expanded = false; 1744 }, 150); 1745 } 1746 }" 1747 @mouseenter="openDropdown()" 1748 @mouseleave="closeDropdown()" 1749 @focusin="openDropdown()" 1750 @focusout="if ($event.relatedTarget && !$el.contains($event.relatedTarget)) closeDropdown()" 1751 class="no-js-focus-wrapper flex self-stretch header-dropdown" 1752 1753 > 1754 <button 1755 class="inline-flex py-4 items-center header-menu-item" 1756 @click="expanded = !expanded" 1757 :aria-expanded="expanded ? true : 'false'" 1758 aria-controls="menu0" 1759 > 1760 <span class="inline-block pr-1">Services</span><span 1761 class="mr-1 inline-block h-3 w-3 origin-center align-middle" 1762 x-show="!expanded" 1763 ><svg 1764 class="theme-icon" 1765 xmlns="http://www.w3.org/2000/svg" 1766 fill="none" 1767 viewBox="0 0 24 24" 1768> 1769 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 1770</svg> 1771</span> 1772 <span 1773 class="mr-1 inline-block h-3 w-3 origin-center align-middle" 1774 x-show="expanded" 1775 style="display: none;" 1776 ><svg 1777 class="theme-icon" 1778 xmlns="http://www.w3.org/2000/svg" 1779 fill="none" 1780 viewBox="0 0 24 24" 1781> 1782 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 1783</svg> 1784</span></button> 1785 <div 1786 id="menu0" 1787 class="no-js-focus-container absolute top-full z-20 dropdown-glass text-scheme-text bottom-auto left-0 w-full" 1788 x-cloak 1789 x-show="expanded" 1790 x-transition:enter="transition ease-out duration-300 motion-reduce:duration-0" 1791 x-transition:enter-start="opacity-0 -translate-y-2 scale-[0.98]" 1792 x-transition:enter-end="opacity-100 translate-y-0 scale-100" 1793 x-transition:leave="transition ease-in duration-200 motion-reduce:duration-0" 1794 x-transition:leave-start="opacity-100 translate-y-0 scale-100" 1795 x-transition:leave-end="opacity-0 -translate-y-1 scale-[0.99]" 1796 style="transform-origin: top center;" 1797 data-color-scheme="" 1798 ><div class=" text-left"><div class="grid gap-gutter bg-gridline-color grid-cols-4"> 1799 1800 <div class="bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text"> 1801 <a 1802 1803 class="font-heading inline-block py-1" 1804 href="/pages/services" 1805 > 1806 Services 1807 </a> 1808 </div> 1809 1810 1811 1812 1813<div class="bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text"> 1814 <h2 class="font-heading mb-2"> 1815 1816 <a 1817 1818 class="inline-block py-1" 1819 href="/pages/product-capabilities" 1820 1821 > 1822 Production capabilities 1823 </a> 1824 1825 </h2> 1826 <ul><li class=""> 1827 <a 1828 1829 class="inline-block py-1" 1830 href="/pages/custom-manufactured" 1831 >Custom-manufactured</a> 1832 </li><li class=""> 1833 <a 1834 1835 class="inline-block py-1" 1836 href="/pages/screen-printing" 1837 >Screen printing</a> 1838 </li><li class=""> 1839 <a 1840 1841 class="inline-block py-1" 1842 href="/pages/embroidery" 1843 >Embroidery</a> 1844 </li><li class=""> 1845 <a 1846 1847 class="inline-block py-1" 1848 href="/pages/heat-transfers" 1849 >Heat transfers</a> 1850 </li><li class=""> 1851 <a 1852 1853 class="inline-block py-1" 1854 href="/pages/finishing" 1855 >Finishing</a> 1856 </li></ul> 1857 </div><div class="bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text"> 1858 <h2 class="font-heading mb-2"> 1859 1860 <a 1861 1862 class="inline-block py-1" 1863 href="/pages/partner-services" 1864 1865 > 1866 Partner services 1867 </a> 1868 1869 </h2> 1870 <ul><li class=""> 1871 <a 1872 1873 class="inline-block py-1" 1874 href="/pages/client-portal" 1875 >Client portal</a> 1876 </li><li class=""> 1877 <a 1878 1879 class="inline-block py-1" 1880 href="/pages/fundraising-pre-orders" 1881 >Fundraise & pre-order</a> 1882 </li><li class=""> 1883 <a 1884 1885 class="inline-block py-1" 1886 href="/pages/repurpose-initiative" 1887 >Repurpose initiative</a> 1888 </li></ul> 1889 </div><div class="bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text"> 1890 <h2 class="font-heading mb-2"> 1891 1892 <a 1893 1894 class="inline-block py-1" 1895 href="/pages/popular-services" 1896 1897 > 1898 Popular services 1899 </a> 1900 1901 </h2> 1902 <ul><li class=""> 1903 <a 1904 1905 class="inline-block py-1" 1906 href="/pages/school-leavers-gear" 1907 >School leavers gear</a> 1908 </li><li class=""> 1909 <a 1910 1911 class="inline-block py-1" 1912 href="/pages/tshirt-printing" 1913 >Custom t-shirt printing</a> 1914 </li></ul> 1915 </div> 1916</div></div></div> 1917 </data-island> 1918 1919 1920 1921 1922 <a 1923 1924 class="flex py-4 relative self-stretch inline-flex flex-col" 1925 href="/pages/responsibility" 1926 >
1927 <span class="m-auto inline-block">Responsibility</span></a> 1928 1929 1930<data-island 1931 x-data="{ 1932 expanded: false, 1933 hoverTimeout: null, 1934 openDropdown() { 1935 clearTimeout(this.hoverTimeout); 1936 this.expanded = true; 1937 this.$nextTick(() => { 1938 const header = this.$el.closest('header'); 1939 const dd = this.$el.querySelector('.dropdown-glass'); 1940 if (header && dd) { 1941 header.style.setProperty('--dropdown-h', dd.offsetHeight + 'px'); 1942 } 1943 }); 1944 }, 1945 closeDropdown() { 1946 this.hoverTimeout = setTimeout(() => { 1947 this.expanded = false; 1948 }, 150); 1949 } 1950 }" 1951 @mouseenter="openDropdown()" 1952 @mouseleave="closeDropdown()" 1953 @focusin="openDropdown()" 1954 @focusout="if ($event.relatedTarget && !$el.contains($event.relatedTarget)) closeDropdown()" 1955 class="no-js-focus-wrapper flex self-stretch header-dropdown" 1956 style="position: relative;" 1957 > 1958 <button 1959 class="inline-flex py-4 items-center header-menu-item" 1960 @click="expanded = !expanded" 1961 :aria-expanded="expanded ? true : 'false'" 1962 aria-controls="menu1" 1963 > 1964 <span class="inline-block pr-1">Our story</span><span 1965 class="mr-1 inline-block h-3 w-3 origin-center align-middle" 1966 x-show="!expanded" 1967 ><svg 1968 class="theme-icon" 1969 xmlns="http://www.w3.org/2000/svg" 1970 fill="none" 1971 viewBox="0 0 24 24" 1972> 1973 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 1974</svg> 1975</span> 1976 <span 1977 class="mr-1 inline-block h-3 w-3 origin-center align-middle" 1978 x-show="expanded" 1979 style="display: none;" 1980 ><svg 1981 class="theme-icon" 1982 xmlns="http://www.w3.org/2000/svg" 1983 fill="none" 1984 viewBox="0 0 24 24" 1985> 1986 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 1987</svg> 1988</span></button> 1989 <div 1990 id="menu1" 1991 class="no-js-focus-container absolute top-full z-20 dropdown-glass text-scheme-text gs-dropdown-content nav-dropdown-content" 1992 x-cloak 1993 x-show="expanded" 1994 x-transition:enter="transition ease-out duration-300 motion-reduce:duration-0" 1995 x-transition:enter-start="opacity-0 -translate-y-2 scale-[0.98]" 1996 x-transition:enter-end="opacity-100 translate-y-0 scale-100" 1997 x-transition:leave="transition ease-in duration-200 motion-reduce:duration-0" 1998 x-transition:leave-start="opacity-100 translate-y-0 scale-100" 1999 x-transition:leave-end="opacity-0 -translate-y-1 scale-[0.99]" 2000 style="transform-origin: top left;" 2001 data-color-scheme="" 2002 ><a 2003 href="/pages/in-good-company-with" 2004 2005 >In good company withâ¦</a><a 2006 href="/pages/about-print-room" 2007 2008 >Our origins</a></div> 2009 </data-island> 2010 2011<data-island 2012 x-data="{ 2013 expanded: false, 2014 hoverTimeout: null, 2015 openDropdown() { 2016 clearTimeout(this.hoverTimeout); 2017 this.expanded = true; 2018 this.$nextTick(() => { 2019 const header = this.$el.closest('header'); 2020 const dd = this.$el.querySelector('.dropdown-glass'); 2021 if (header && dd) { 2022 header.style.setProperty('--dropdown-h', dd.offsetHeight + 'px'); 2023 } 2024 }); 2025 }, 2026 closeDropdown() { 2027 this.hoverTimeout = setTimeout(() => { 2028 this.expanded = false; 2029 }, 150); 2030 } 2031 }" 2032 @mouseenter="openDropdown()" 2033 @mouseleave="closeDropdown()" 2034 @focusin="openDropdown()" 2035 @focusout="if ($event.relatedTarget && !$el.contains($event.relatedTarget)) closeDropdown()" 2036 class="no-js-focus-wrapper flex items-center self-stretch header-dropdown" 2037 style="position: relative;" 2038 > 2039 <button 2040 class="gs-pill" 2041 :class="{ 'is-active': expanded }" 2042 @click="expanded = !expanded" 2043 :aria-expanded="expanded ? 'true' : 'false'" 2044 >
2045 <span>Get started +</span> 2046 </button> 2047 <div 2048 class="no-js-focus-container absolute top-full z-20 dropdown-glass text-scheme-text gs-dropdown-content" 2049 x-cloak 2050 x-show="expanded" 2051 x-transition:enter="transition ease-out duration-300 motion-reduce:duration-0" 2052 x-transition:enter-start="opacity-0 -translate-y-2" 2053 x-transition:enter-end="opacity-100 translate-y-0" 2054 x-transition:leave="transition ease-in duration-200 motion-reduce:duration-0" 2055 x-transition:leave-start="opacity-100 translate-y-0" 2056 x-transition:leave-end="opacity-0 -translate-y-1" 2057 style="transform-origin: top left;" 2058 data-color-scheme="" 2059 ><a href="/collections/product-library">Start a project</a><a href="/pages/book-a-call">Book a call</a></div> 2060 </data-island> 2061 2062 2063<div class="flex items-stretch justify-end gap-x-4 text-right "><div class="ml-4 my-auto shrink-0"><form method="post" action="/localization" id="header-localization-form" accept-charset="UTF-8" class="shopify-localization-form" enctype="multipart/form-data"><input type="hidden" name="form_type" value="localization" /><input type="hidden" name="utf8" value="â" /><input type="hidden" name="_method" value="put" /><input type="hidden" name="return_to" value="/cart" /><div class="flex gap-4 justify-end max-lg:hidden"><div class="inline-block shrink-0 select-none"> 2064 <h2 class="sr-only" id="country-heading-header"> 2065 Country/region 2066 </h2> 2067 <data-island 2068 class="relative" 2069 x-data="{ expanded: false }" 2070 @keydown.escape.prevent.stop="expanded = false" 2071 @click.outside="expanded = false" 2072 > 2073 <button 2074 type="button" 2075 class="text-base py-4" 2076 :aria-expanded="expanded" 2077 aria-controls="country-list-header" 2078 aria-describedby="country-heading-header" 2079 @click.prevent="expanded = ! expanded" 2080 > 2081 United States (USD 2082 $) 2083 <span 2084 class="rotate ml-1 inline-block w-3 origin-center transform fill-current transition" 2085 :class="{ 'rotate-180': expanded }" 2086 > 2087 <svg 2088 class="theme-icon" 2089 xmlns="http://www.w3.org/2000/svg" 2090 fill="none" 2091 viewBox="0 0 24 24" 2092> 2093 <path stroke="currentColor" d="M1.5 7 12 17.5 22.5 7" vector-effect="non-scaling-stroke"/> 2094</svg> 2095 2096 </span> 2097 </button> 2098 <div 2099 class="absolute top-full left-0 right-auto" 2100 x-show="expanded" 2101 style="display: none;" 2102 > 2103 <ul 2104 id="country-list-header" 2105 class="relative z-10 flex max-h-[30vh] w-max max-w-[theme(spacing.64)] snap-y snap-mandatory flex-col gap-[--text-border-width] overflow-y-auto border-text border-gridline-color bg-gridline-color text-base" 2106 x-transition:enter="transition ease duration-300" 2107 x-transition:enter-start="opacity-0" 2108 x-transition:enter-end="opacity-100" 2109 x-transition:leave="transition ease duration-300" 2110 x-transition:leave-start="opacity-100" 2111 x-transition:leave-end="opacity-0" 2112 :aria-hidden="! expanded" 2113 > 2114 2115 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2116 <button 2117 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2118 type="button" 2119 2120 @click.prevent="$refs.input.value = 'AU'; $root.closest('form').submit();" 2121 > 2122 <span class="border-transparent border-b-text">Australia (AUD 2123 $)</span 2124 > 2125 </button> 2126 </li> 2127 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2128 <button 2129 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2130 type="button" 2131 2132 @click.prevent="$refs.input.value = 'CN'; $root.closest('form').submit();" 2133 >
2134 <span class="border-transparent border-b-text">China (CNY 2135 Â¥)</span 2136 > 2137 </button> 2138 </li> 2139 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2140 <button 2141 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2142 type="button" 2143 2144 @click.prevent="$refs.input.value = 'FR'; $root.closest('form').submit();" 2145 > 2146 <span class="border-transparent border-b-text">France (EUR 2147 â¬)</span 2148 > 2149 </button> 2150 </li> 2151 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2152 <button 2153 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2154 type="button" 2155 2156 @click.prevent="$refs.input.value = 'NZ'; $root.closest('form').submit();" 2157 > 2158 <span class="border-transparent border-b-text">New Zealand (NZD 2159 $)</span 2160 > 2161 </button> 2162 </li> 2163 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2164 <button 2165 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2166 type="button" 2167 2168 @click.prevent="$refs.input.value = 'GB'; $root.closest('form').submit();" 2169 > 2170 <span class="border-transparent border-b-text">United Kingdom (GBP 2171 £)</span 2172 > 2173 </button> 2174 </li> 2175 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2176 <button 2177 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2178 type="button" 2179 2180 aria-current="true" 2181 2182 @click.prevent="$refs.input.value = 'US'; $root.closest('form').submit();" 2183 > 2184 <span class="border-scheme-text border-b-text">United States (USD 2185 $)</span 2186 > 2187 </button> 2188 </li></ul> 2189 </div> 2190 2191 <input 2192 x-ref="input" 2193 type="hidden" 2194 name="country_code" 2195 id="CountrySelector" 2196 value="US" 2197 > 2198 </data-island> 2199 </div></div></form></div> 2200 <div class="flex items-stretch whitespace-nowrap"> 2201 <data-island 2202 x-data="{ searchOpen: false }" 2203 class="contents" 2204> 2205 <a 2206 x-ref="searchToggle" 2207 @click.prevent="searchOpen = true" 2208 @keydown.space.prevent="searchOpen = true" 2209 class="inline-flex py-4 h-full" 2210 href="/search" 2211 :role="`button`" 2212 ><span class="sr-only">Search</span> 2213 <span class="my-auto inline-block h-6 w-6 align-middle"><svg 2214 class="theme-icon" 2215 xmlns="http://www.w3.org/2000/svg" 2216 fill="none" 2217 viewBox="0 0 24 24" 2218> 2219 <path stroke="currentColor" d="M2 11a9 9 0 1 0 18 0 9 9 0 0 0-18 0Zm15.364 6.364L22 22" vector-effect="non-scaling-stroke"/> 2220</svg> 2221</span></a> 2222 2223 <data-island 2224 class="absolute z-20 border-y-gridline border-gridline-color bg-scheme-background px-section-horizontal-spacing py-2 text-scheme-text w-full top-full bottom-auto left-0" 2225 x-cloak 2226 x-show="searchOpen" 2227 x-transition:enter="ease duration-200" 2228 x-transition:enter-start="opacity-0" 2229 x-transition:enter-end="opacity-100" 2230 x-transition:leave="ease duration-200" 2231 x-transition:leave-start="opacity-100" 2232 x-transition:leave-end="opacity-0" 2233 2234 x-data="PredictiveSearch('product,collection,article,page,query')" 2235 x-trap.inert.noscroll="resultsOpen" 2236 @keyup="onKeyup" 2237 @keydown="onKeydown" 2238 @click.outside.prevent="close()" 2239 @keyup.escape.prevent.stop="close(true, $refs.searchToggle)" 2240 @focusin.window="( searchOpen && ! $root.contains($event.target) ) && close()" 2241 style="--results-height: calc(100vh - var(--header-group-height) - var(--search-bar-height) + var(--gridline-width));" 2242 src="//printroom.co/cdn/shop/t/59/assets/island-predictive-search.bundle.js?v=181601895277339900721787098435" 2243 2244 x-ref="searchComponent" 2245 data-color-scheme="scheme1" 2246 on="idle" 2247 > 2248 <div 2249 class="w-full whitespace-normal" 2250 > 2251 <form 2252 action="/search" 2253 method="get" 2254 class="predictive-search-form input-group search" 2255 role="search" 2256 > 2257 <input type="hidden" name="options[prefix]" value="last"><label 2258 for="search-logo_left_menu_spread-desktop" 2259 class="hidden" 2260 >Submit</label> 2261 2262 <div 2263 class="flex items-center justify-between" 2264 > 2265 <button 2266 class="mr-4 py-2" 2267 aria-label="Submit" 2268 type="submit" 2269 >
2270 <span class="inline-block h-6 w-6 align-middle"><svg 2271 class="theme-icon" 2272 xmlns="http://www.w3.org/2000/svg" 2273 fill="none" 2274 viewBox="0 0 24 24" 2275> 2276 <path stroke="currentColor" d="M2 11a9 9 0 1 0 18 0 9 9 0 0 0-18 0Zm15.364 6.364L22 22" vector-effect="non-scaling-stroke"/> 2277</svg> 2278</span> 2279 <span class="sr-only">Submit</span> 2280 </button> 2281 <input 2282 id="search-logo_left_menu_spread-desktop" 2283 type="search" 2284 name="q" 2285 value="" 2286 placeholder="Search" 2287 class="font-body block w-full bg-transparent placeholder-current" 2288 aria-label="Search" 2289 data-search-input 2290 2291 :aria-expanded="resultsOpen" 2292 :aria-activedescendant="resultsOpen ? 'predictive-search-results' : false" 2293 aria-owns="predictive-search-results" 2294 aria-controls="predictive-search-results" 2295 aria-autocomplete="list" 2296 autocorrect="off" 2297 autocomplete="off" 2298 autocapitalize="off" 2299 spellcheck="false" 2300 x-ref="input" 2301 x-model.debounce.300="rawQuery" 2302 @focus="onFocus" 2303 2304 > 2305 <button 2306 class="ml-4 py-2" 2307 2308 @click="close()" 2309 2310 type="button" 2311 > 2312 <span class="sr-only">Close</span> 2313 <span class="inline-block h-6 w-6 align-middle"><svg 2314 class="theme-icon" 2315 xmlns="http://www.w3.org/2000/svg" 2316 fill="none" 2317 viewBox="0 0 24 24" 2318> 2319 <path stroke="currentColor" d="m1.5 1.5 21 21m0-21-21 21" vector-effect="non-scaling-stroke"/> 2320</svg> 2321</span> 2322 </button> 2323 </div><div 2324 tabindex="-1" 2325 x-cloak 2326 class="predictive-search-results absolute left-0 right-0 top-[calc(100%_+_var(--gridline-width))] z-50 h-screen text-scheme-text transition-colors duration-300 ease-out" 2327 > 2328 <template x-if="loading"> 2329 <div class="border-b-gridline border-gridline-color bg-scheme-background"> 2330 <div 2331 class="mx-auto py-6 text-center" 2332 > 2333 <div>Loading…</div> 2334 </div> 2335 </div> 2336 </template> 2337 <template x-if="resultsOpen"> 2338 <div 2339 x-show="!loading && resultsHTML && resultsOpen" 2340 class="px-section max-h-[--results-height] scroll-py-5 overflow-hidden overflow-y-auto border-b-gridline border-gridline-color bg-scheme-background" 2341 x-html-if-set="resultsHTML" 2342 ></div> 2343 </template> 2344 </div> 2345 <span 2346 class="predictive-search-status sr-only" 2347 role="status" 2348 aria-hidden="true" 2349 ></span></form> 2350 </div> 2351 </data-island> 2352</data-island> 2353 2354 </div> 2355 2356 2357 <div class="flex items-stretch whitespace-nowrap gap-4"><style> 2358 @keyframes quote-badge-pulse { 2359 0% { transform: scale(1); } 2360 50% { transform: scale(1.22); } 2361 100% { transform: scale(1); } 2362 } 2363 2364 @keyframes quote-icon-pulse { 2365 0% { transform: scale(1); } 2366 50% { transform: scale(1.12); } 2367 100% { transform: scale(1); } 2368 } 2369 2370 .quote-badge-animate { 2371 animation: quote-badge-pulse 0.4s ease-in-out; 2372 } 2373 .quote-icon-animate { 2374 animation: quote-icon-pulse 0.4s ease-in-out; 2375 } 2376 .quote-badge { 2377 min-width: 1.3rem; 2378 padding-inline: 0.22rem; 2379 box-shadow: 0 10px 24px rgba(43, 57, 144, 0.22); 2380 } 2381 .quote-tooltip { 2382 position: absolute; 2383 top: calc(100% + 8px); 2384 right: -10px; 2385 width: 152px; 2386 padding: 15px 16px; 2387 border-radius: 20px; 2388 font-size: 14px; 2389 font-style: italic; 2390 line-height: 17px; 2391 color: #000; 2392 background: #FBFBF6; 2393 border: 1px solid #000; 2394 box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.15); 2395 z-index: 1000; 2396 cursor: pointer; 2397 white-space: normal; 2398 text-align: left; 2399 } 2400 .quote-tooltip::before { 2401 content: ''; 2402 position: absolute; 2403 top: -7px; 2404 right: 24px; 2405 width: 14px; 2406 height: 14px; 2407 background: #FBFBF6; 2408 border-top: 1px solid #000; 2409 border-left: 1px solid #000; 2410 transform: rotate(45deg); 2411 } 2412 @media (max-width: 640px) { 2413 .quote-tooltip { 2414 right: -10px; 2415 } 2416 } 2417</style> 2418 2419<div 2420 class="relative" 2421 x-data="{ 2422 showTooltip: false,
2423 tooltipDismissed: false, 2424 animating: false, 2425 tooltipTimer: null, 2426 dismissTooltip() { 2427 this.showTooltip = false; 2428 this.tooltipDismissed = true; 2429 if (this.tooltipTimer) clearTimeout(this.tooltipTimer); 2430 if (this.tooltipDelayTimer) clearTimeout(this.tooltipDelayTimer); 2431 }, 2432 tooltipDelayTimer: null, 2433 triggerTooltip() { 2434 try { 2435 if (this.tooltipDismissed || sessionStorage.getItem('psstShown')) return; 2436 } catch (error) { 2437 if (this.tooltipDismissed) return; 2438 } 2439 if (this.tooltipDelayTimer) clearTimeout(this.tooltipDelayTimer); 2440 this.tooltipDelayTimer = setTimeout(() => { 2441 if (this.tooltipDismissed) return; 2442 try { sessionStorage.setItem('psstShown', '1'); } catch(e) {} 2443 this.showTooltip = true; 2444 if (this.tooltipTimer) clearTimeout(this.tooltipTimer); 2445 this.tooltipTimer = setTimeout(() => { this.showTooltip = false; }, 15000); 2446 }, 5000); 2447 }, 2448 pulseIcon() { 2449 this.animating = true; 2450 setTimeout(() => { this.animating = false; }, 450); 2451 } 2452 }" 2453 @quote-item-added.document="pulseIcon(); triggerTooltip()" 2454> 2455 <a 2456 href="/pages/general-quote" 2457 class="inline-flex min-h-10 items-center py-4 h-full" 2458 :role="`button`" 2459 :aria-expanded="$store.modals.rightDrawer.contents === 'favorites'" 2460 @click.prevent="$store.modals.open('favorites'); dismissTooltip(); window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: 'quote_drawer_opened', quote_count: $store.favorites.count, page_path: window.location.pathname })" 2461 @keydown.space.prevent="$store.modals.open('favorites'); dismissTooltip()" 2462 aria-label="Open your quote" 2463 ><div class="pointer-events-none relative my-auto align-middle" :class="{ 'quote-icon-animate': animating }"><span class="inline-block h-6 w-6 align-top [&_*]:pointer-events-none"><span class="h-full w-full"> 2464 <svg 2465 aria-hidden="true" 2466 focusable="false" 2467 role="presentation" 2468 class="icon icon-quote-list-outline" 2469 viewBox="0 0 24 24" 2470 fill="none" 2471 ><rect x="3" y="1" width="18" height="22" rx="2.5" ry="2.5" stroke="currentColor" stroke-width="1.5"></rect><circle cx="7.5" cy="7.5" r="1" fill="currentColor"></circle> 2472 <line x1="10" y1="7.5" x2="17.5" y2="7.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 2473 <circle cx="7.5" cy="11" r="1" fill="currentColor"></circle> 2474 <line x1="10" y1="11" x2="17.5" y2="11" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 2475 <circle cx="7.5" cy="14.5" r="1" fill="currentColor"></circle> 2476 <line x1="10" y1="14.5" x2="17.5" y2="14.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 2477 <circle cx="7.5" cy="18" r="1" fill="currentColor"></circle> 2478 <line x1="10" y1="18" x2="17.5" y2="18" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 2479 </svg> 2480</span> 2481</span><span 2482 x-show="$store.favorites.count > 0" 2483 x-cloak 2484 class="quote-badge absolute flex items-center justify-center rounded-full text-[10px] font-bold" 2485 style="background-color: #4B4D72; color: #fff; width: 18px; height: 18px; top: -7px; right: -8px;" 2486 :class="{ 'quote-badge-animate': animating }" 2487 x-text="$store.favorites.count" 2488 ></span> 2489 <span class="sr-only" x-text="'Your Quote: ' + $store.favorites.countWithText()"> 2490 Your Quote: 0 items 2491 </span> 2492 </div></a><div 2493 x-show="showTooltip" 2494 x-transition:enter="transition ease-out duration-200" 2495 x-transition:enter-start="opacity-0 translate-y-1" 2496 x-transition:enter-end="opacity-100 translate-y-0" 2497 x-transition:leave="transition ease-in duration-150" 2498 x-transition:leave-start="opacity-100" 2499 x-transition:leave-end="opacity-0" 2500 x-cloak 2501 class="quote-tooltip" 2502 @click="dismissTooltip()" 2503 > 2504 Hi, your favourite products are here. 2505 </div> 2506</div> 2507 2508 <a 2509 href="/cart" 2510 class="inline-flex py-4 h-full" 2511 2512 ><div class="pointer-events-none relative my-auto align-middle"> 2513 <span 2514 x-show="$store.cartCount.count > 0" 2515 class="absolute right-0 top-1 h-2 w-2 rounded-full" 2516 style="background-color: #f1ffa5;" 2517 ></span>
2518 <span class="inline-block h-6 w-6 fill-current align-top [&_*]:pointer-events-none"><svg 2519 class="theme-icon" 2520 xmlns="http://www.w3.org/2000/svg" 2521 fill="none" 2522 viewBox="0 0 24 24" 2523> 2524 <path stroke="currentColor" d="M2 7h20v15H2V7Zm15 0v-.2A4.8 4.8 0 0 0 12.2 2h-.4A4.8 4.8 0 0 0 7 6.8V7" vector-effect="non-scaling-stroke"/> 2525</svg> 2526</span> 2527 <span class="sr-only" x-text="$store.cartCount.countWithText()"> 2528 25290 items 2530 </span> 2531 </div></a> 2532 </div> 2533 </div> 2534 </div> 2535 2536 2537 </nav> 2538 2539 2540 <nav 2541 aria-label="Header" 2542 class="lg:hidden" 2543 > 2544 <div class="flex items-center justify-between px-section-horizontal-spacing lg:relative"> 2545 <div class="flex gap-2 items-center"> 2546 2547 <div> 2548 <a 2549 href="/" 2550 class="break-word my-auto inline-block py-4" 2551 > 2552 2553 2554 <div class="max-w-[var(--logo-max-width)]"> 2555 2556<img 2557 src="//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=90" 2558 srcset="//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=80 80w,//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=160 160w,//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=240 240w,//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=90 90w,//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=180 180w,//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=270 270w 2559 " 2560 width="543" 2561 height="397" 2562 loading="eager" 2563 2564 sizes="(min-width: 1024px) 90px, 80px" 2565 2566 alt="The Print Room" 2567 2568 > 2569 2570 2571 2572 </div> 2573 2574 2575 </a> 2576 </div> 2577 2578 2579 </div> 2580 2581 2582 2583 <div class="flex justify-end gap-2 text-right"> 2584 2585 <button 2586 class="inline-block no-js:hidden py-4" 2587 :aria-expanded="$store.modals.leftDrawer.contents === 'sidebar'" 2588 @click="$store.modals.open('sidebar')" 2589 ><span class="sr-only pointer-events-none">Menu</span> 2590 <span class="pointer-events-none inline-block h-6 w-6 align-middle"><svg 2591 class="theme-icon" 2592 xmlns="http://www.w3.org/2000/svg" 2593 fill="none" 2594 viewBox="0 0 24 24" 2595> 2596 <path stroke="currentColor" d="M1 7.364h22M1 15.636h22" vector-effect="non-scaling-stroke"/> 2597</svg> 2598</span></button> 2599 2600 2601 2602 2603 2604 <div class="whitespace-nowrap lg:ml-4"> 2605 <data-island 2606 x-data="{ searchOpen: false }" 2607 class="contents" 2608> 2609 <a 2610 x-ref="searchToggle" 2611 @click.prevent="searchOpen = true" 2612 @keydown.space.prevent="searchOpen = true" 2613 class="inline-flex py-4 h-full" 2614 href="/search" 2615 :role="`button`" 2616 ><span class="sr-only">Search</span> 2617 <span class="my-auto inline-block h-6 w-6 align-middle"><svg 2618 class="theme-icon" 2619 xmlns="http://www.w3.org/2000/svg" 2620 fill="none" 2621 viewBox="0 0 24 24" 2622> 2623 <path stroke="currentColor" d="M2 11a9 9 0 1 0 18 0 9 9 0 0 0-18 0Zm15.364 6.364L22 22" vector-effect="non-scaling-stroke"/> 2624</svg> 2625</span></a> 2626 2627 <data-island 2628 class="absolute z-20 border-y-gridline border-gridline-color bg-scheme-background px-section-horizontal-spacing py-2 text-scheme-text w-full top-full bottom-auto left-0" 2629 x-cloak 2630 x-show="searchOpen" 2631 x-transition:enter="ease duration-200" 2632 x-transition:enter-start="opacity-0" 2633 x-transition:enter-end="opacity-100" 2634 x-transition:leave="ease duration-200" 2635 x-transition:leave-start="opacity-100" 2636 x-transition:leave-end="opacity-0" 2637 2638 x-data="PredictiveSearch('product,collection,article,page,query')" 2639 x-trap.inert.noscroll="resultsOpen" 2640 @keyup="onKeyup" 2641 @keydown="onKeydown" 2642 @click.outside.prevent="close()" 2643 @keyup.escape.prevent.stop="close(true, $refs.searchToggle)" 2644 @focusin.window="( searchOpen && ! $root.contains($event.target) ) && close()" 2645 style="--results-height: calc(100vh - var(--header-group-height) - var(--search-bar-height) + var(--gridline-width));" 2646 src="//printroom.co/cdn/shop/t/59/assets/island-predictive-search.bundle.js?v=181601895277339900721787098435" 2647 2648 x-ref="searchComponent" 2649 data-color-scheme="scheme1" 2650 on="idle" 2651 > 2652 <div 2653 class="w-full whitespace-normal" 2654 > 2655 <form 2656 action="/search" 2657 method="get" 2658 class="predictive-search-form input-group search" 2659 role="search" 2660 > 2661 <input type="hidden" name="options[prefix]" value="last"><label 2662 for="search-logo_left_menu_spread-mobile" 2663 class="hidden" 2664 >Submit</label> 2665 2666 <div 2667 class="flex items-center justify-between" 2668 > 2669 <button 2670 class="mr-4 py-2" 2671 aria-label="Submit" 2672 type="submit" 2673 >
2674 <span class="inline-block h-6 w-6 align-middle"><svg 2675 class="theme-icon" 2676 xmlns="http://www.w3.org/2000/svg" 2677 fill="none" 2678 viewBox="0 0 24 24" 2679> 2680 <path stroke="currentColor" d="M2 11a9 9 0 1 0 18 0 9 9 0 0 0-18 0Zm15.364 6.364L22 22" vector-effect="non-scaling-stroke"/> 2681</svg> 2682</span> 2683 <span class="sr-only">Submit</span> 2684 </button> 2685 <input 2686 id="search-logo_left_menu_spread-mobile" 2687 type="search" 2688 name="q" 2689 value="" 2690 placeholder="Search" 2691 class="font-body block w-full bg-transparent placeholder-current" 2692 aria-label="Search" 2693 data-search-input 2694 2695 :aria-expanded="resultsOpen" 2696 :aria-activedescendant="resultsOpen ? 'predictive-search-results' : false" 2697 aria-owns="predictive-search-results" 2698 aria-controls="predictive-search-results" 2699 aria-autocomplete="list" 2700 autocorrect="off" 2701 autocomplete="off" 2702 autocapitalize="off" 2703 spellcheck="false" 2704 x-ref="input" 2705 x-model.debounce.300="rawQuery" 2706 @focus="onFocus" 2707 2708 > 2709 <button 2710 class="ml-4 py-2" 2711 2712 @click="close()" 2713 2714 type="button" 2715 > 2716 <span class="sr-only">Close</span> 2717 <span class="inline-block h-6 w-6 align-middle"><svg 2718 class="theme-icon" 2719 xmlns="http://www.w3.org/2000/svg" 2720 fill="none" 2721 viewBox="0 0 24 24" 2722> 2723 <path stroke="currentColor" d="m1.5 1.5 21 21m0-21-21 21" vector-effect="non-scaling-stroke"/> 2724</svg> 2725</span> 2726 </button> 2727 </div><div 2728 tabindex="-1" 2729 x-cloak 2730 class="predictive-search-results absolute left-0 right-0 top-[calc(100%_+_var(--gridline-width))] z-50 h-screen text-scheme-text transition-colors duration-300 ease-out" 2731 > 2732 <template x-if="loading"> 2733 <div class="border-b-gridline border-gridline-color bg-scheme-background"> 2734 <div 2735 class="mx-auto py-6 text-center" 2736 > 2737 <div>Loading…</div> 2738 </div> 2739 </div> 2740 </template> 2741 <template x-if="resultsOpen"> 2742 <div 2743 x-show="!loading && resultsHTML && resultsOpen" 2744 class="px-section max-h-[--results-height] scroll-py-5 overflow-hidden overflow-y-auto border-b-gridline border-gridline-color bg-scheme-background" 2745 x-html-if-set="resultsHTML" 2746 ></div> 2747 </template> 2748 </div> 2749 <span 2750 class="predictive-search-status sr-only" 2751 role="status" 2752 aria-hidden="true" 2753 ></span></form> 2754 </div> 2755 </data-island> 2756</data-island> 2757 2758 </div> 2759 2760<div class="inline-block shrink-0 select-none whitespace-nowrap lg:ml-4"> 2761 <data-island 2762 class="relative" 2763 x-data="{ expanded: false }" 2764 @keydown.escape.prevent.stop="expanded = false" 2765 @click.outside="expanded = false" 2766 > 2767 <button 2768 type="button" 2769 class="inline-flex py-4 h-full" 2770 :aria-expanded="expanded" 2771 aria-controls="currency-list-header" 2772 @click.prevent="expanded = ! expanded" 2773 aria-label="Currency selector" 2774 > 2775 <span class="my-auto inline-flex items-center gap-1"> 2776 <span class="inline-block h-6 w-6 align-middle"> 2777 <svg class="theme-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> 2778 <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="1.5" vector-effect="non-scaling-stroke" fill="none"/> 2779 <path stroke="currentColor" stroke-width="1.5" d="M12 6v12M8 10h8M8 14h8" vector-effect="non-scaling-stroke"/> 2780</svg> 2781 </span> 2782 <span class="text-xs font-medium">USD</span> 2783 </span>
2784 <span 2785 class="rotate ml-1 inline-block w-3 origin-center transform fill-current transition my-auto" 2786 :class="{ 'rotate-180': expanded }" 2787 > 2788 <svg 2789 class="theme-icon" 2790 xmlns="http://www.w3.org/2000/svg" 2791 fill="none" 2792 viewBox="0 0 24 24" 2793> 2794 <path stroke="currentColor" d="M1.5 7 12 17.5 22.5 7" vector-effect="non-scaling-stroke"/> 2795</svg> 2796 2797 </span> 2798 </button> 2799 <div 2800 class="absolute top-full right-0" 2801 x-show="expanded" 2802 style="display: none;" 2803 > 2804 <form method="post" action="/localization" accept-charset="UTF-8" enctype="multipart/form-data"> 2805 <input type="hidden" name="form_type" value="localization"> 2806 <input type="hidden" name="utf8" value="â"> 2807 <input type="hidden" name="_method" value="put"> 2808 <input type="hidden" name="return_to" value="/cart"> 2809 <ul 2810 id="currency-list-header" 2811 class="relative z-50 flex max-h-[30vh] w-max max-w-[theme(spacing.64)] snap-y snap-mandatory flex-col gap-[--text-border-width] overflow-y-auto border-text border-gridline-color bg-gridline-color text-base" 2812 x-transition:enter="transition ease duration-300" 2813 x-transition:enter-start="opacity-0" 2814 x-transition:enter-end="opacity-100" 2815 x-transition:leave="transition ease duration-300" 2816 x-transition:leave-start="opacity-100" 2817 x-transition:leave-end="opacity-0" 2818 :aria-hidden="! expanded" 2819 > 2820 2821 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2822 <button 2823 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2824 type="submit" 2825 name="country_code" 2826 value="AU" 2827 2828 > 2829 <span class="border-transparent border-b-text">AUD $<span class="ml-2 text-xs opacity-70">Australia</span></span 2830 > 2831 </button> 2832 </li> 2833 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2834 <button 2835 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2836 type="submit" 2837 name="country_code" 2838 value="CN" 2839 2840 > 2841 <span class="border-transparent border-b-text">CNY Â¥<span class="ml-2 text-xs opacity-70">China</span></span 2842 > 2843 </button> 2844 </li> 2845 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2846 <button 2847 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2848 type="submit" 2849 name="country_code" 2850 value="FR" 2851 2852 > 2853 <span class="border-transparent border-b-text">EUR â¬<span class="ml-2 text-xs opacity-70">France</span></span 2854 > 2855 </button> 2856 </li> 2857 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2858 <button 2859 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2860 type="submit" 2861 name="country_code" 2862 value="NZ" 2863 2864 >
2865 <span class="border-transparent border-b-text">NZD $<span class="ml-2 text-xs opacity-70">New Zealand</span></span 2866 > 2867 </button> 2868 </li> 2869 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2870 <button 2871 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2872 type="submit" 2873 name="country_code" 2874 value="GB" 2875 2876 > 2877 <span class="border-transparent border-b-text">GBP £<span class="ml-2 text-xs opacity-70">United Kingdom</span></span 2878 > 2879 </button> 2880 </li> 2881 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2882 <button 2883 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2884 type="submit" 2885 name="country_code" 2886 value="US" 2887 2888 aria-current="true" 2889 2890 > 2891 <span class="border-scheme-text border-b-text">USD $<span class="ml-2 text-xs opacity-70">United States</span></span 2892 > 2893 </button> 2894 </li></ul> 2895 </form> 2896 </div> 2897 </data-island> 2898 </div><div class="flex items-center whitespace-nowrap gap-2 lg:ml-4"><style> 2899 @keyframes quote-badge-pulse { 2900 0% { transform: scale(1); } 2901 50% { transform: scale(1.22); } 2902 100% { transform: scale(1); } 2903 } 2904 2905 @keyframes quote-icon-pulse { 2906 0% { transform: scale(1); } 2907 50% { transform: scale(1.12); } 2908 100% { transform: scale(1); } 2909 } 2910 2911 .quote-badge-animate { 2912 animation: quote-badge-pulse 0.4s ease-in-out; 2913 } 2914 .quote-icon-animate { 2915 animation: quote-icon-pulse 0.4s ease-in-out; 2916 } 2917 .quote-badge { 2918 min-width: 1.3rem; 2919 padding-inline: 0.22rem; 2920 box-shadow: 0 10px 24px rgba(43, 57, 144, 0.22); 2921 } 2922 .quote-tooltip { 2923 position: absolute; 2924 top: calc(100% + 8px); 2925 right: -10px; 2926 width: 152px; 2927 padding: 15px 16px; 2928 border-radius: 20px; 2929 font-size: 14px; 2930 font-style: italic; 2931 line-height: 17px; 2932 color: #000; 2933 background: #FBFBF6; 2934 border: 1px solid #000; 2935 box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.15); 2936 z-index: 1000; 2937 cursor: pointer; 2938 white-space: normal; 2939 text-align: left; 2940 } 2941 .quote-tooltip::before { 2942 content: ''; 2943 position: absolute; 2944 top: -7px; 2945 right: 24px; 2946 width: 14px; 2947 height: 14px; 2948 background: #FBFBF6; 2949 border-top: 1px solid #000; 2950 border-left: 1px solid #000; 2951 transform: rotate(45deg); 2952 } 2953 @media (max-width: 640px) { 2954 .quote-tooltip { 2955 right: -10px; 2956 } 2957 } 2958</style> 2959 2960<div 2961 class="relative" 2962 x-data="{ 2963 showTooltip: false, 2964 tooltipDismissed: false, 2965 animating: false, 2966 tooltipTimer: null, 2967 dismissTooltip() { 2968 this.showTooltip = false; 2969 this.tooltipDismissed = true; 2970 if (this.tooltipTimer) clearTimeout(this.tooltipTimer); 2971 if (this.tooltipDelayTimer) clearTimeout(this.tooltipDelayTimer); 2972 }, 2973 tooltipDelayTimer: null, 2974 triggerTooltip() { 2975 try { 2976 if (this.tooltipDismissed || sessionStorage.getItem('psstShown')) return; 2977 } catch (error) { 2978 if (this.tooltipDismissed) return; 2979 } 2980 if (this.tooltipDelayTimer) clearTimeout(this.tooltipDelayTimer); 2981 this.tooltipDelayTimer = setTimeout(() => { 2982 if (this.tooltipDismissed) return; 2983 try { sessionStorage.setItem('psstShown', '1'); } catch(e) {} 2984 this.showTooltip = true; 2985 if (this.tooltipTimer) clearTimeout(this.tooltipTimer); 2986 this.tooltipTimer = setTimeout(() => { this.showTooltip = false; }, 15000); 2987 }, 5000); 2988 }, 2989 pulseIcon() { 2990 this.animating = true; 2991 setTimeout(() => { this.animating = false; }, 450); 2992 } 2993 }" 2994 @quote-item-added.document="pulseIcon(); triggerTooltip()" 2995> 2996 <a 2997 href="/pages/general-quote" 2998 class="inline-flex min-h-10 items-center py-4 h-full" 2999 :role="`button`" 3000 :aria-expanded="$store.modals.rightDrawer.contents === 'favorites'" 3001 @click.prevent="$store.modals.open('favorites'); dismissTooltip(); window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: 'quote_drawer_opened', quote_count: $store.favorites.count, page_path: window.location.pathname })" 3002 @keydown.space.prevent="$store.modals.open('favorites'); dismissTooltip()" 3003 aria-label="Open your quote" 3004 ><div class="pointer-events-none relative my-auto align-middle" :class="{ 'quote-icon-animate': animating }"><span class="inline-block h-6 w-6 align-top [&_*]:pointer-events-none"><span class="h-full w-full"> 3005 <svg 3006 aria-hidden="true" 3007 focusable="false" 3008 role="presentation" 3009 class="icon icon-quote-list-outline"
3010 viewBox="0 0 24 24" 3011 fill="none" 3012 ><rect x="3" y="1" width="18" height="22" rx="2.5" ry="2.5" stroke="currentColor" stroke-width="1.5"></rect><circle cx="7.5" cy="7.5" r="1" fill="currentColor"></circle> 3013 <line x1="10" y1="7.5" x2="17.5" y2="7.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 3014 <circle cx="7.5" cy="11" r="1" fill="currentColor"></circle> 3015 <line x1="10" y1="11" x2="17.5" y2="11" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 3016 <circle cx="7.5" cy="14.5" r="1" fill="currentColor"></circle> 3017 <line x1="10" y1="14.5" x2="17.5" y2="14.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 3018 <circle cx="7.5" cy="18" r="1" fill="currentColor"></circle> 3019 <line x1="10" y1="18" x2="17.5" y2="18" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 3020 </svg> 3021</span> 3022</span><span 3023 x-show="$store.favorites.count > 0" 3024 x-cloak 3025 class="quote-badge absolute flex items-center justify-center rounded-full text-[10px] font-bold" 3026 style="background-color: #4B4D72; color: #fff; width: 18px; height: 18px; top: -7px; right: -8px;" 3027 :class="{ 'quote-badge-animate': animating }" 3028 x-text="$store.favorites.count" 3029 ></span> 3030 <span class="sr-only" x-text="'Your Quote: ' + $store.favorites.countWithText()"> 3031 Your Quote: 0 items 3032 </span> 3033 </div></a><div 3034 x-show="showTooltip" 3035 x-transition:enter="transition ease-out duration-200" 3036 x-transition:enter-start="opacity-0 translate-y-1" 3037 x-transition:enter-end="opacity-100 translate-y-0" 3038 x-transition:leave="transition ease-in duration-150" 3039 x-transition:leave-start="opacity-100" 3040 x-transition:leave-end="opacity-0" 3041 x-cloak 3042 class="quote-tooltip" 3043 @click="dismissTooltip()" 3044 > 3045 Hi, your favourite products are here. 3046 </div> 3047</div> 3048 3049 <a 3050 href="/cart" 3051 class="inline-flex py-4 h-full" 3052 3053 ><div class="pointer-events-none relative my-auto align-middle"> 3054 <span 3055 x-show="$store.cartCount.count > 0" 3056 class="absolute right-0 top-1 h-2 w-2 rounded-full" 3057 style="background-color: #f1ffa5;" 3058 ></span> 3059 <span class="inline-block h-6 w-6 fill-current align-top [&_*]:pointer-events-none"><svg 3060 class="theme-icon" 3061 xmlns="http://www.w3.org/2000/svg" 3062 fill="none" 3063 viewBox="0 0 24 24" 3064> 3065 <path stroke="currentColor" d="M2 7h20v15H2V7Zm15 0v-.2A4.8 4.8 0 0 0 12.2 2h-.4A4.8 4.8 0 0 0 7 6.8V7" vector-effect="non-scaling-stroke"/> 3066</svg> 3067</span> 3068 <span class="sr-only" x-text="$store.cartCount.countWithText()"> 3069 30700 items 3071 </span> 3072 </div></a> 3073 </div> 3074 </div> 3075 </div> 3076 </nav> 3077 </header> 3078</data-island><noscript> 3079 <style data-shopify> 3080 .no-js-focus-wrapper:focus-within .no-js-focus-container { 3081 display: block !important; 3082 } 3083 3084 </style> 3085</noscript> 3086 3087<style> 3088 /* ââ Get Started pill + dropdown ââ */ 3089 .gs-pill { 3090 display: inline-flex; 3091 align-items: center; 3092 padding: 0 20px; 3093 height: 39px; 3094 border: 1px solid #2a3a8e; 3095 border-radius: 40px; 3096 background: transparent; 3097 color: #2a3a8e; 3098 font-size: 17.3px; 3099 font-family: 'DM Sans', sans-serif; 3100 font-weight: 400; 3101 line-height: 24px; 3102 cursor: pointer; 3103 white-space: nowrap; 3104 transition: background-color 0.25s ease, color 0.25s ease; 3105 } 3106 3107 .gs-pill:hover, 3108 .gs-pill.is-active { 3109 background-color: #2b3990; 3110 color: #f9fafb; 3111 } 3112 3113 .gs-dropdown-content { 3114 display: flex; 3115 flex-direction: column; 3116 gap: 6px; 3117 padding: 10px 20px 14px; 3118 left: 0; 3119 } 3120 3121 .gs-dropdown-content a { 3122 color: #2a3a8e; 3123 font-size: 17.3px; 3124 font-family: 'DM Sans', sans-serif; 3125 font-weight: 400; 3126 text-decoration: none; 3127 white-space: nowrap; 3128 line-height: 32px; 3129 } 3130 3131 .gs-dropdown-content a:hover { 3132 opacity: 0.7; 3133 } 3134 3135 /* Nav dropdowns (e.g. "Our story") nudged left to sit under the menu label */ 3136 .nav-dropdown-content { 3137 left: -12px; 3138 } 3139 3140 .quote-pill-button { 3141 display: inline-block; 3142 padding: 1rem 2rem; 3143 border-radius: 9999px; 3144 cursor: pointer; 3145 border: 0; 3146 background-color: #f1ffa5; 3147 transition: all 0.5s ease; 3148 color: #1F2937; 3149 text-decoration: none; 3150 font-weight: 600; 3151 font-size: 1.1em; 3152 } 3153 3154 .quote-pill-button:hover { 3155 transform: scale(1.2); 3156 } 3157 3158 .quote-pill-button:active { 3159 transform: scale(1.07); 3160 transition: 100ms; 3161 } 3162
3163 .start-design-button { 3164 display: inline-block; 3165 padding: 1rem 2rem; 3166 border-radius: 9999px; 3167 cursor: pointer; 3168 border: 0; 3169 background-color: #2b3990; 3170 transition: all 0.5s ease; 3171 color: #ffffff; 3172 text-decoration: none; 3173 font-weight: 600; 3174 font-size: 1.1em; 3175 } 3176 3177 .start-design-button:hover { 3178 transform: scale(1.2); 3179 } 3180 3181 .start-design-button:active { 3182 transform: scale(1.07); 3183 transition: 100ms; 3184 } 3185 3186 @keyframes float { 3187 0%, 100% { 3188 transform: translateY(0px); 3189 } 3190 50% { 3191 transform: translateY(-6px); 3192 } 3193 } 3194 3195 .beta-badge { 3196 position: absolute; 3197 top: -8px; 3198 right: -8px; 3199 background-color: #f1ffa5; 3200 color: #1e2326; 3201 font-size: 0.65em; 3202 font-weight: 700; 3203 padding: 0.25rem 0.5rem; 3204 border-radius: 9999px; 3205 text-transform: uppercase; 3206 letter-spacing: 0.5px; 3207 box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); 3208 z-index: 10; 3209 animation: float 2s ease-in-out infinite; 3210 } 3211</style> 3212 3213 3214 3215
3215<script> 3216 if (!customElements.get('sticky-header-height-helper')) { 3217 class StickyHeaderHeightHelper extends HTMLElement { 3218 constructor() { 3219 super(); 3220 } 3221 3222 connectedCallback() { 3223 const headerEl = this.closest('[data-theme-header]'); 3224 3225 if (headerEl && headerEl.getAttribute('data-sticky')) { 3226 document.documentElement.style.setProperty( 3227 '--sticky-header-height', 3228 `${headerEl.getBoundingClientRect().height}px` 3229 ); 3230 } else { 3231 3232 document.documentElement.style.setProperty( 3233 '--sticky-header-height', 3234 '0px' 3235 ); 3236 } 3237 } 3238 } 3239 3240 customElements.define( 3241 'sticky-header-height-helper', 3242 StickyHeaderHeightHelper 3243 ); 3244 } 3245 </script>
3245 3246 3247 3248<style> #shopify-section-sections--21296457187398__header .bg-scheme-background {border-bottom: 1px solid #2b3990;} </style></div> 3249<!-- END sections: header-group --> 3250<div id="shopify-section-menu-drawer" class="shopify-section"> 3251 3252<data-island 3253 3254 x-data 3255 3256 x-init="initTeleport($root); $store.modals.register('sidebar', 'leftDrawer');" 3257 on="idle" 3258> 3259 <template data-should-teleport="#left-drawer-slot"> 3260 <template 3261 id="sidebar" 3262 x-if="$store.modals.leftDrawer.contents === 'sidebar'" 3263 > 3264 3265 <div 3266 3267 data-modal-label="Menu" 3268 > 3269 <div class="sticky top-0 z-1 flex items-center justify-between border-b-gridline border-gridline-color px-section-horizontal-spacing py-4"> 3270 <div aria-hidden="true"> </div> 3271 <button 3272 @click.prevent="$store.modals.close('sidebar')" 3273 class="absolute right-0 top-0 block h-full" 3274 type="button" 3275 > 3276 <span class="sr-only">Close</span> 3277 <div class="my-auto mr-section-horizontal-spacing h-6 w-6"><svg 3278 class="theme-icon" 3279 xmlns="http://www.w3.org/2000/svg" 3280 fill="none" 3281 viewBox="0 0 24 24" 3282> 3283 <path stroke="currentColor" d="m1.5 1.5 21 21m0-21-21 21" vector-effect="non-scaling-stroke"/> 3284</svg> 3285</div> 3286 </button> 3287 </div> 3288 <nav 3289 3290 aria-label="Primary" 3291 > 3292 <ul><li 3293 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 3294 ><a class="inline-block py-4 w-full text-heading-standard" href="/collections/product-library"> 3295 Products 3296 </a></li><li 3297 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 3298 ><data-island class="contents" x-data="{ expanded: false }"><button 3299 class="relative block w-full text-left inline-block py-4 w-full text-heading-standard ease pr-10 transition font-body" 3300 x-bind:aria-expanded="expanded ? true : 'false'" 3301 @click="expanded = ! expanded" 3302 aria-controls="accordion0" 3303 > 3304 Services 3305 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3306 class="inline-block w-full origin-center" 3307 x-show="!expanded" 3308 ><svg 3309 class="theme-icon" 3310 xmlns="http://www.w3.org/2000/svg" 3311 fill="none" 3312 viewBox="0 0 24 24" 3313> 3314 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3315</svg> 3316</span> 3317 <span 3318 class="inline-block w-full origin-center" 3319 x-show="expanded" 3320 style="display: none;" 3321 ><svg 3322 class="theme-icon" 3323 xmlns="http://www.w3.org/2000/svg" 3324 fill="none" 3325 viewBox="0 0 24 24" 3326> 3327 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3328</svg> 3329</span></span> 3330 </button> 3331 <ul 3332 id="accordion0" 3333 class="no-js-focus-container pb-2 pl-4" 3334 x-show="expanded" 3335 x-cloak 3336 ><li class="no-js-focus-wrapper"><data-island class="contents" x-data="{ expanded: false }" > 3337 <button 3338 class="relative w-full text-left inline-block py-1 pr-10" 3339 x-bind:aria-expanded="expanded ? true : 'false'" 3340 @click="expanded = ! expanded" 3341 aria-controls="accordion1" 3342 > 3343 Production capabilities 3344 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3345 class="inline-block w-full origin-center" 3346 x-show="!expanded" 3347 ><svg 3348 class="theme-icon" 3349 xmlns="http://www.w3.org/2000/svg" 3350 fill="none" 3351 viewBox="0 0 24 24" 3352> 3353 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3354</svg> 3355</span>
3356 <span 3357 class="inline-block w-full origin-center" 3358 x-show="expanded" 3359 style="display: none;" 3360 ><svg 3361 class="theme-icon" 3362 xmlns="http://www.w3.org/2000/svg" 3363 fill="none" 3364 viewBox="0 0 24 24" 3365> 3366 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3367</svg> 3368</span></span> 3369 </button> 3370 <ul 3371 id="accordion1" 3372 class="no-js-focus-container px-2 pb-2 pt-1" 3373 x-show="expanded" 3374 x-cloak 3375 ><li> 3376 <a 3377 class="inline-block py-1 " 3378 href="/pages/custom-manufactured" 3379 > 3380 Custom-manufactured 3381 </a> 3382 </li><li> 3383 <a 3384 class="inline-block py-1 " 3385 href="/pages/screen-printing" 3386 > 3387 Screen printing 3388 </a> 3389 </li><li> 3390 <a 3391 class="inline-block py-1 " 3392 href="/pages/embroidery" 3393 > 3394 Embroidery 3395 </a> 3396 </li><li> 3397 <a 3398 class="inline-block py-1 " 3399 href="/pages/heat-transfers" 3400 > 3401 Heat transfers 3402 </a> 3403 </li><li> 3404 <a 3405 class="inline-block py-1 " 3406 href="/pages/finishing" 3407 > 3408 Finishing 3409 </a> 3410 </li></ul> 3411 </data-island></li><li class="no-js-focus-wrapper"><data-island class="contents" x-data="{ expanded: false }" > 3412 <button 3413 class="relative w-full text-left inline-block py-1 pr-10" 3414 x-bind:aria-expanded="expanded ? true : 'false'" 3415 @click="expanded = ! expanded" 3416 aria-controls="accordion2" 3417 > 3418 Partner services 3419 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3420 class="inline-block w-full origin-center" 3421 x-show="!expanded" 3422 ><svg 3423 class="theme-icon" 3424 xmlns="http://www.w3.org/2000/svg" 3425 fill="none" 3426 viewBox="0 0 24 24" 3427> 3428 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3429</svg> 3430</span> 3431 <span 3432 class="inline-block w-full origin-center" 3433 x-show="expanded" 3434 style="display: none;" 3435 ><svg 3436 class="theme-icon" 3437 xmlns="http://www.w3.org/2000/svg" 3438 fill="none" 3439 viewBox="0 0 24 24" 3440> 3441 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3442</svg> 3443</span></span> 3444 </button> 3445 <ul 3446 id="accordion2" 3447 class="no-js-focus-container px-2 pb-2 pt-1" 3448 x-show="expanded" 3449 x-cloak 3450 ><li> 3451 <a 3452 class="inline-block py-1 " 3453 href="/pages/client-portal" 3454 > 3455 Client portal 3456 </a> 3457 </li><li> 3458 <a 3459 class="inline-block py-1 " 3460 href="/pages/fundraising-pre-orders" 3461 > 3462 Fundraise & pre-order 3463 </a> 3464 </li><li> 3465 <a 3466 class="inline-block py-1 " 3467 href="/pages/repurpose-initiative" 3468 > 3469 Repurpose initiative 3470 </a> 3471 </li></ul> 3472 </data-island></li><li class="no-js-focus-wrapper"><data-island class="contents" x-data="{ expanded: false }" > 3473 <button 3474 class="relative w-full text-left inline-block py-1 pr-10" 3475 x-bind:aria-expanded="expanded ? true : 'false'" 3476 @click="expanded = ! expanded" 3477 aria-controls="accordion3" 3478 > 3479 Popular services
3480 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3481 class="inline-block w-full origin-center" 3482 x-show="!expanded" 3483 ><svg 3484 class="theme-icon" 3485 xmlns="http://www.w3.org/2000/svg" 3486 fill="none" 3487 viewBox="0 0 24 24" 3488> 3489 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3490</svg> 3491</span> 3492 <span 3493 class="inline-block w-full origin-center" 3494 x-show="expanded" 3495 style="display: none;" 3496 ><svg 3497 class="theme-icon" 3498 xmlns="http://www.w3.org/2000/svg" 3499 fill="none" 3500 viewBox="0 0 24 24" 3501> 3502 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3503</svg> 3504</span></span> 3505 </button> 3506 <ul 3507 id="accordion3" 3508 class="no-js-focus-container px-2 pb-2 pt-1" 3509 x-show="expanded" 3510 x-cloak 3511 ><li> 3512 <a 3513 class="inline-block py-1 " 3514 href="/pages/school-leavers-gear" 3515 > 3516 School leavers gear 3517 </a> 3518 </li><li> 3519 <a 3520 class="inline-block py-1 " 3521 href="/pages/tshirt-printing" 3522 > 3523 Custom t-shirt printing 3524 </a> 3525 </li></ul> 3526 </data-island></li></ul> 3527 </data-island></li><li 3528 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 3529 ><a class="inline-block py-4 w-full text-heading-standard" href="/pages/responsibility"> 3530 Responsibility 3531 </a></li><li 3532 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 3533 ><data-island class="contents" x-data="{ expanded: false }"><button 3534 class="relative block w-full text-left inline-block py-4 w-full text-heading-standard ease pr-10 transition font-body" 3535 x-bind:aria-expanded="expanded ? true : 'false'" 3536 @click="expanded = ! expanded" 3537 aria-controls="accordion4" 3538 > 3539 Our story 3540 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3541 class="inline-block w-full origin-center" 3542 x-show="!expanded" 3543 ><svg 3544 class="theme-icon" 3545 xmlns="http://www.w3.org/2000/svg" 3546 fill="none" 3547 viewBox="0 0 24 24" 3548> 3549 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3550</svg> 3551</span> 3552 <span 3553 class="inline-block w-full origin-center" 3554 x-show="expanded" 3555 style="display: none;" 3556 ><svg 3557 class="theme-icon" 3558 xmlns="http://www.w3.org/2000/svg" 3559 fill="none" 3560 viewBox="0 0 24 24" 3561> 3562 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3563</svg> 3564</span></span> 3565 </button> 3566 <ul 3567 id="accordion4" 3568 class="no-js-focus-container pb-2 pl-4" 3569 x-show="expanded" 3570 x-cloak 3571 ><li class="no-js-focus-wrapper"><a 3572 class="inline-block py-1 " 3573 href="/pages/in-good-company-with" 3574 > 3575 In good company with⦠3576 </a></li><li class="no-js-focus-wrapper"><a 3577 class="inline-block py-1 " 3578 href="/pages/about-print-room" 3579 > 3580 Our origins 3581 </a></li></ul> 3582 </data-island></li><li 3583 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gr
3583idline-color first-of-type:border-t-0" 3584 ><data-island class="contents" x-data="{ expanded: false }"><button 3585 class="relative block w-full text-left inline-block py-4 w-full text-heading-standard ease pr-10 transition font-body" 3586 x-bind:aria-expanded="expanded ? true : 'false'" 3587 @click="expanded = ! expanded" 3588 aria-controls="accordion5" 3589 > 3590 Get started 3591 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3592 class="inline-block w-full origin-center" 3593 x-show="!expanded" 3594 ><svg 3595 class="theme-icon" 3596 xmlns="http://www.w3.org/2000/svg" 3597 fill="none" 3598 viewBox="0 0 24 24" 3599> 3600 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3601</svg> 3602</span> 3603 <span 3604 class="inline-block w-full origin-center" 3605 x-show="expanded" 3606 style="display: none;" 3607 ><svg 3608 class="theme-icon" 3609 xmlns="http://www.w3.org/2000/svg" 3610 fill="none" 3611 viewBox="0 0 24 24" 3612> 3613 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3614</svg> 3615</span></span> 3616 </button> 3617 <ul 3618 id="accordion5" 3619 class="no-js-focus-container pb-2 pl-4" 3620 x-show="expanded" 3621 x-cloak 3622 ><li class="no-js-focus-wrapper"><a 3623 class="inline-block py-1 " 3624 href="/collections/product-library" 3625 > 3626 Start a project 3627 </a></li><li class="no-js-focus-wrapper"><a 3628 class="inline-block py-1 " 3629 href="/pages/book-a-call" 3630 > 3631 Book a call 3632 </a></li></ul> 3633 </data-island></li></ul> 3634 </nav> 3635 <div class="border-t-gridline border-gridline-color"> 3636 <nav class="my-6" aria-label="Secondary"> 3637 <ul></ul> 3638 </nav> 3639 3640 3641 <div class="my-6 px-section-horizontal-spacing"> 3642 <form method="post" action="/localization" id="sidebar-localization-form" accept-charset="UTF-8" class="shopify-localization-form" enctype="multipart/form-data"><input type="hidden" name="form_type" value="localization" /><input type="hidden" name="utf8" value="â" /><input type="hidden" name="_method" value="put" /><input type="hidden" name="return_to" value="/cart" /><div class="flex gap-4 flex-col gap-y-0"><div class="inline-block shrink-0 select-none"> 3643 <h2 class="sr-only" id="country-heading-sidebar"> 3644 Country/region 3645 </h2> 3646 <data-island 3647 class="relative" 3648 x-data="{ expanded: false }" 3649 @keydown.escape.prevent.stop="expanded = false" 3650 @click.outside="expanded = false" 3651 > 3652 <button 3653 type="button" 3654 class="text-base py-2" 3655 :aria-expanded="expanded" 3656 aria-controls="country-list-sidebar" 3657 aria-describedby="country-heading-sidebar" 3658 @click.prevent="expanded = ! expanded" 3659 > 3660 United States (USD 3661 $) 3662 <span 3663 class="rotate ml-1 inline-block w-3 origin-center transform fill-current transition" 3664 :class="{ 'rotate-180': expanded }" 3665 > 3666 <svg 3667 class="theme-icon" 3668 xmlns="http://www.w3.org/2000/svg" 3669 fill="none" 3670 viewBox="0 0 24 24" 3671> 3672 <path stroke="currentColor" d="M1.5 7 12 17.5 22.5 7" vector-effect="non-scaling-stroke"/> 3673</svg> 3674 3675 </span> 3676 </button> 3677 <div 3678 class="absolute bottom-[calc(100%_+_0.5rem)] right-auto left-0" 3679 x-show="expanded" 3680 style="display: none;" 3681 > 3682 <ul 3683 id="country-list-sidebar" 3684 class="relative z-10 flex max-h-[30vh] w-max max-w-[theme(spacing.52)] snap-y snap-mandatory flex-col gap-[--text-border-width] overflow-y-auto border-text border-gr
3684idline-color bg-gridline-color text-base" 3685 x-transition:enter="transition ease duration-300" 3686 x-transition:enter-start="opacity-0" 3687 x-transition:enter-end="opacity-100" 3688 x-transition:leave="transition ease duration-300" 3689 x-transition:leave-start="opacity-100" 3690 x-transition:leave-end="opacity-0" 3691 :aria-hidden="! expanded" 3692 > 3693 3694 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 3695 <button 3696 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 3697 type="button" 3698 3699 @click.prevent="$refs.input.value = 'AU'; $root.closest('form').submit();" 3700 > 3701 <span class="border-transparent border-b-text">Australia (AUD 3702 $)</span 3703 > 3704 </button> 3705 </li> 3706 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 3707 <button 3708 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 3709 type="button" 3710 3711 @click.prevent="$refs.input.value = 'CN'; $root.closest('form').submit();" 3712 > 3713 <span class="border-transparent border-b-text">China (CNY 3714 Â¥)</span 3715 > 3716 </button> 3717 </li> 3718 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 3719 <button 3720 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 3721 type="button" 3722 3723 @click.prevent="$refs.input.value = 'FR'; $root.closest('form').submit();" 3724 > 3725 <span class="border-transparent border-b-text">France (EUR 3726 â¬)</span 3727 > 3728 </button> 3729 </li> 3730 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 3731 <button 3732 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 3733 type="button" 3734 3735 @click.prevent="$refs.input.value = 'NZ'; $root.closest('form').submit();" 3736 > 3737 <span class="border-transparent border-b-text">New Zealand (NZD 3738 $)</span 3739 > 3740 </button> 3741 </li> 3742 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 3743 <button 3744 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 3745 type="button" 3746 3747 @click.prevent="$refs.input.value = 'GB'; $root.closest('form').submit();" 3748 > 3749 <span class="border-transparent border-b-text">United Kingdom (GBP 3750 £)</span 3751 > 3752 </button> 3753 </li> 3754 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 3755 <button 3756 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 3757 type="button" 3758 3759 aria-current="true" 3760 3761 @click.prevent="$refs.input.value = 'US'; $root.closest('form').submit();" 3762 > 3763 <span class="border-scheme-text border-b-text">United States (USD 3764 $)</span 3765 > 3766 </button> 3767 </li></ul> 3768 </div> 3769 3770 <input 3771 x-ref="input" 3772 type="hidden" 3773 name="country_code" 3774 id="CountrySelector" 3775 value="US" 3776 > 3777 </data-island> 3778 </div></div></form> 3779 </div> 3780 3781 3782 3783<form 3784 class="my-6 px-section-horizontal-spacing" 3785 action="/search" 3786 method="get" 3787 role="search" 3788 > 3789 <div class="flex w-full max-w-xs items-end"> 3790 <label for="menu-drawer-search" class="sr-only">Search</label> 3791 <input 3792 class="min-w-0 flex-auto border-b-text border-current bg-transparent py-1.5 placeholder-current" 3793 id="menu-drawer-search" 3794 type="text" 3795 name="q" 3796 placeholder="Search" 3797 > 3798 <button 3799 class="px-1" 3800 type="submit" 3801 >
3802 <span class="inline-block h-6 w-6"><svg 3803 class="theme-icon" 3804 xmlns="http://www.w3.org/2000/svg" 3805 fill="none" 3806 viewBox="0 0 24 24" 3807> 3808 <path stroke="currentColor" d="M2 11a9 9 0 1 0 18 0 9 9 0 0 0-18 0Zm15.364 6.364L22 22" vector-effect="non-scaling-stroke"/> 3809</svg> 3810</span> 3811 <span class="sr-only">Submit</span> 3812 </button> 3813 </div> 3814 </form> 3815 </div> 3816 </div> 3817 3818 </template> 3819 </template> 3820</data-island> 3821 3822<noscript> 3823 <section class="section-sidebar"> 3824 <div class="px-section-horizontal-spacing py-2 text-right"> 3825 <button 3826 class="inline-flex items-center justify-center py-2 " 3827 data-menu-drawer-toggle 3828 > 3829 <span class="mr-2 inline-block h-6 w-6 align-middle"><svg 3830 class="theme-icon" 3831 xmlns="http://www.w3.org/2000/svg" 3832 fill="none" 3833 viewBox="0 0 24 24" 3834> 3835 <path stroke="currentColor" d="M1 4.545h22M1 12h22M1 19.455h22" vector-effect="non-scaling-stroke"/> 3836</svg> 3837</span> 3838 <span>Menu</span> 3839 </button> 3840 </div> 3841 <div class="sidebar-container z-80 border-r-grid border-grid-color fixed bottom-0 left-0 top-0 w-11/12 max-w-xl transform overflow-y-auto bg-scheme-background text-scheme-text transition-transform"> 3842 3843 <div 3844 3845 data-modal-label="Menu" 3846 > 3847 <div class="sticky top-0 z-1 flex items-center justify-between border-b-gridline border-gridline-color px-section-horizontal-spacing py-4"> 3848 <div aria-hidden="true"> </div> 3849 <button 3850 @click.prevent="$store.modals.close('sidebar')" 3851 class="absolute right-0 top-0 block h-full" 3852 type="button" 3853 > 3854 <span class="sr-only">Close</span> 3855 <div class="my-auto mr-section-horizontal-spacing h-6 w-6"><svg 3856 class="theme-icon" 3857 xmlns="http://www.w3.org/2000/svg" 3858 fill="none" 3859 viewBox="0 0 24 24" 3860> 3861 <path stroke="currentColor" d="m1.5 1.5 21 21m0-21-21 21" vector-effect="non-scaling-stroke"/> 3862</svg> 3863</div> 3864 </button> 3865 </div> 3866 <nav 3867 3868 aria-label="Primary" 3869 > 3870 <ul><li 3871 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 3872 ><a class="inline-block py-4 w-full text-heading-standard" href="/collections/product-library"> 3873 Products 3874 </a></li><li 3875 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 3876 ><data-island class="contents" x-data="{ expanded: false }"><button 3877 class="relative block w-full text-left inline-block py-4 w-full text-heading-standard ease pr-10 transition font-body" 3878 x-bind:aria-expanded="expanded ? true : 'false'" 3879 @click="expanded = ! expanded" 3880 aria-controls="accordion0" 3881 > 3882 Services 3883 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3884 class="inline-block w-full origin-center" 3885 x-show="!expanded" 3886 ><svg 3887 class="theme-icon" 3888 xmlns="http://www.w3.org/2000/svg" 3889 fill="none" 3890 viewBox="0 0 24 24" 3891> 3892 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3893</svg> 3894</span> 3895 <span 3896 class="inline-block w-full origin-center" 3897 x-show="expanded" 3898 style="display: none;" 3899 ><svg 3900 class="theme-icon" 3901 xmlns="http://www.w3.org/2000/svg" 3902 fill="none" 3903 viewBox="0 0 24 24" 3904> 3905 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3906</svg> 3907</span></span> 3908 </button> 3909 <ul 3910 id="accordion0" 3911 class="no-js-focus-container pb-2 pl-4" 3912 x-show="expanded" 3913 x-cloak 3914 ><li class="no-js-focus-wrapper"><data-island class="contents" x-data="{ expanded: false }" > 3915 <button 3916 class="relative w-full text-left inline-block py-1 pr-10" 3917 x-bind:aria-expanded="expanded ? true : 'false'" 3918 @click="expanded = ! expanded" 3919 aria-controls="accordion1" 3920 > 3921 Production capabilities
3922 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3923 class="inline-block w-full origin-center" 3924 x-show="!expanded" 3925 ><svg 3926 class="theme-icon" 3927 xmlns="http://www.w3.org/2000/svg" 3928 fill="none" 3929 viewBox="0 0 24 24" 3930> 3931 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3932</svg> 3933</span> 3934 <span 3935 class="inline-block w-full origin-center" 3936 x-show="expanded" 3937 style="display: none;" 3938 ><svg 3939 class="theme-icon" 3940 xmlns="http://www.w3.org/2000/svg" 3941 fill="none" 3942 viewBox="0 0 24 24" 3943> 3944 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3945</svg> 3946</span></span> 3947 </button> 3948 <ul 3949 id="accordion1" 3950 class="no-js-focus-container px-2 pb-2 pt-1" 3951 x-show="expanded" 3952 x-cloak 3953 ><li> 3954 <a 3955 class="inline-block py-1 " 3956 href="/pages/custom-manufactured" 3957 > 3958 Custom-manufactured 3959 </a> 3960 </li><li> 3961 <a 3962 class="inline-block py-1 " 3963 href="/pages/screen-printing" 3964 > 3965 Screen printing 3966 </a> 3967 </li><li> 3968 <a 3969 class="inline-block py-1 " 3970 href="/pages/embroidery" 3971 > 3972 Embroidery 3973 </a> 3974 </li><li> 3975 <a 3976 class="inline-block py-1 " 3977 href="/pages/heat-transfers" 3978 > 3979 Heat transfers 3980 </a> 3981 </li><li> 3982 <a 3983 class="inline-block py-1 " 3984 href="/pages/finishing" 3985 > 3986 Finishing 3987 </a> 3988 </li></ul> 3989 </data-island></li><li class="no-js-focus-wrapper"><data-island class="contents" x-data="{ expanded: false }" > 3990 <button 3991 class="relative w-full text-left inline-block py-1 pr-10" 3992 x-bind:aria-expanded="expanded ? true : 'false'" 3993 @click="expanded = ! expanded" 3994 aria-controls="accordion2" 3995 > 3996 Partner services 3997 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3998 class="inline-block w-full origin-center" 3999 x-show="!expanded" 4000 ><svg 4001 class="theme-icon" 4002 xmlns="http://www.w3.org/2000/svg" 4003 fill="none" 4004 viewBox="0 0 24 24" 4005> 4006 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 4007</svg> 4008</span> 4009 <span 4010 class="inline-block w-full origin-center" 4011 x-show="expanded" 4012 style="display: none;" 4013 ><svg 4014 class="theme-icon" 4015 xmlns="http://www.w3.org/2000/svg" 4016 fill="none" 4017 viewBox="0 0 24 24" 4018> 4019 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 4020</svg> 4021</span></span> 4022 </button> 4023 <ul 4024 id="accordion2" 4025 class="no-js-focus-container px-2 pb-2 pt-1" 4026 x-show="expanded" 4027 x-cloak 4028 ><li> 4029 <a 4030 class="inline-block py-1 " 4031 href="/pages/client-portal" 4032 > 4033 Client portal 4034 </a> 4035 </li><li> 4036 <a 4037 class="inline-block py-1 " 4038 href="/pages/fundraising-pre-orders" 4039 > 4040 Fundraise & pre-order 4041 </a> 4042 </li><li> 4043 <a 4044 class="inline-block py-1 " 4045 href="/pages/repurpose-initiative" 4046 > 4047 Repurpose initiative 4048 </a> 4049 </li></ul> 4050 </data-island></li><li class="no-js-focus-wrapper"><data-island class="contents" x-data="{ expanded: false }" > 4051 <button 4052 class="relative w-full text-left inline-block py-1 pr-10" 4053 x-bind:aria-expanded="expanded ? true : 'false'" 4054 @click="expanded = ! expanded" 4055 aria-controls="accordion3" 4056 > 4057 Popular services
4058 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 4059 class="inline-block w-full origin-center" 4060 x-show="!expanded" 4061 ><svg 4062 class="theme-icon" 4063 xmlns="http://www.w3.org/2000/svg" 4064 fill="none" 4065 viewBox="0 0 24 24" 4066> 4067 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 4068</svg> 4069</span> 4070 <span 4071 class="inline-block w-full origin-center" 4072 x-show="expanded" 4073 style="display: none;" 4074 ><svg 4075 class="theme-icon" 4076 xmlns="http://www.w3.org/2000/svg" 4077 fill="none" 4078 viewBox="0 0 24 24" 4079> 4080 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 4081</svg> 4082</span></span> 4083 </button> 4084 <ul 4085 id="accordion3" 4086 class="no-js-focus-container px-2 pb-2 pt-1" 4087 x-show="expanded" 4088 x-cloak 4089 ><li> 4090 <a 4091 class="inline-block py-1 " 4092 href="/pages/school-leavers-gear" 4093 > 4094 School leavers gear 4095 </a> 4096 </li><li> 4097 <a 4098 class="inline-block py-1 " 4099 href="/pages/tshirt-printing" 4100 > 4101 Custom t-shirt printing 4102 </a> 4103 </li></ul> 4104 </data-island></li></ul> 4105 </data-island></li><li 4106 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 4107 ><a class="inline-block py-4 w-full text-heading-standard" href="/pages/responsibility"> 4108 Responsibility 4109 </a></li><li 4110 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 4111 ><data-island class="contents" x-data="{ expanded: false }"><button 4112 class="relative block w-full text-left inline-block py-4 w-full text-heading-standard ease pr-10 transition font-body" 4113 x-bind:aria-expanded="expanded ? true : 'false'" 4114 @click="expanded = ! expanded" 4115 aria-controls="accordion4" 4116 > 4117 Our story 4118 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 4119 class="inline-block w-full origin-center" 4120 x-show="!expanded" 4121 ><svg 4122 class="theme-icon" 4123 xmlns="http://www.w3.org/2000/svg" 4124 fill="none" 4125 viewBox="0 0 24 24" 4126> 4127 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 4128</svg> 4129</span> 4130 <span 4131 class="inline-block w-full origin-center" 4132 x-show="expanded" 4133 style="display: none;" 4134 ><svg 4135 class="theme-icon" 4136 xmlns="http://www.w3.org/2000/svg" 4137 fill="none" 4138 viewBox="0 0 24 24" 4139> 4140 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 4141</svg> 4142</span></span> 4143 </button> 4144 <ul 4145 id="accordion4" 4146 class="no-js-focus-container pb-2 pl-4" 4147 x-show="expanded" 4148 x-cloak 4149 ><li class="no-js-focus-wrapper"><a 4150 class="inline-block py-1 " 4151 href="/pages/in-good-company-with" 4152 > 4153 In good company with⦠4154 </a></li><li class="no-js-focus-wrapper"><a 4155 class="inline-block py-1 " 4156 href="/pages/about-print-room" 4157 > 4158 Our origins 4159 </a></li></ul> 4160 </data-island></li><li 4161 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gr
4161idline-color first-of-type:border-t-0" 4162 ><data-island class="contents" x-data="{ expanded: false }"><button 4163 class="relative block w-full text-left inline-block py-4 w-full text-heading-standard ease pr-10 transition font-body" 4164 x-bind:aria-expanded="expanded ? true : 'false'" 4165 @click="expanded = ! expanded" 4166 aria-controls="accordion5" 4167 > 4168 Get started 4169 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 4170 class="inline-block w-full origin-center" 4171 x-show="!expanded" 4172 ><svg 4173 class="theme-icon" 4174 xmlns="http://www.w3.org/2000/svg" 4175 fill="none" 4176 viewBox="0 0 24 24" 4177> 4178 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 4179</svg> 4180</span> 4181 <span 4182 class="inline-block w-full origin-center" 4183 x-show="expanded" 4184 style="display: none;" 4185 ><svg 4186 class="theme-icon" 4187 xmlns="http://www.w3.org/2000/svg" 4188 fill="none" 4189 viewBox="0 0 24 24" 4190> 4191 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 4192</svg> 4193</span></span> 4194 </button> 4195 <ul 4196 id="accordion5" 4197 class="no-js-focus-container pb-2 pl-4" 4198 x-show="expanded" 4199 x-cloak 4200 ><li class="no-js-focus-wrapper"><a 4201 class="inline-block py-1 " 4202 href="/collections/product-library" 4203 > 4204 Start a project 4205 </a></li><li class="no-js-focus-wrapper"><a 4206 class="inline-block py-1 " 4207 href="/pages/book-a-call" 4208 > 4209 Book a call 4210 </a></li></ul> 4211 </data-island></li></ul> 4212 </nav> 4213 <div class="border-t-gridline border-gridline-color"> 4214 <nav class="my-6" aria-label="Secondary"> 4215 <ul></ul> 4216 </nav> 4217 4218 4219 <div class="my-6 px-section-horizontal-spacing"> 4220 <form method="post" action="/localization" id="sidebar-localization-form" accept-charset="UTF-8" class="shopify-localization-form" enctype="multipart/form-data"><input type="hidden" name="form_type" value="localization" /><input type="hidden" name="utf8" value="â" /><input type="hidden" name="_method" value="put" /><input type="hidden" name="return_to" value="/cart" /><div class="flex gap-4 flex-col gap-y-0"><div class="inline-block shrink-0 select-none"> 4221 <h2 class="sr-only" id="country-heading-sidebar"> 4222 Country/region 4223 </h2> 4224 <data-island 4225 class="relative" 4226 x-data="{ expanded: false }" 4227 @keydown.escape.prevent.stop="expanded = false" 4228 @click.outside="expanded = false" 4229 > 4230 <button 4231 type="button" 4232 class="text-base py-2" 4233 :aria-expanded="expanded" 4234 aria-controls="country-list-sidebar" 4235 aria-describedby="country-heading-sidebar" 4236 @click.prevent="expanded = ! expanded" 4237 > 4238 United States (USD 4239 $) 4240 <span 4241 class="rotate ml-1 inline-block w-3 origin-center transform fill-current transition" 4242 :class="{ 'rotate-180': expanded }" 4243 > 4244 <svg 4245 class="theme-icon" 4246 xmlns="http://www.w3.org/2000/svg" 4247 fill="none" 4248 viewBox="0 0 24 24" 4249> 4250 <path stroke="currentColor" d="M1.5 7 12 17.5 22.5 7" vector-effect="non-scaling-stroke"/> 4251</svg> 4252 4253 </span> 4254 </button> 4255 <div 4256 class="absolute bottom-[calc(100%_+_0.5rem)] right-auto left-0" 4257 x-show="expanded" 4258 style="display: none;" 4259 > 4260 <ul 4261 id="country-list-sidebar" 4262 class="relative z-10 flex max-h-[30vh] w-max max-w-[theme(spacing.52)] snap-y snap-mandatory flex-col gap-[--text-border-width] overflow-y-auto border-text border-gr
4262idline-color bg-gridline-color text-base" 4263 x-transition:enter="transition ease duration-300" 4264 x-transition:enter-start="opacity-0" 4265 x-transition:enter-end="opacity-100" 4266 x-transition:leave="transition ease duration-300" 4267 x-transition:leave-start="opacity-100" 4268 x-transition:leave-end="opacity-0" 4269 :aria-hidden="! expanded" 4270 > 4271 4272 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 4273 <button 4274 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 4275 type="button" 4276 4277 @click.prevent="$refs.input.value = 'AU'; $root.closest('form').submit();" 4278 > 4279 <span class="border-transparent border-b-text">Australia (AUD 4280 $)</span 4281 > 4282 </button> 4283 </li> 4284 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 4285 <button 4286 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 4287 type="button" 4288 4289 @click.prevent="$refs.input.value = 'CN'; $root.closest('form').submit();" 4290 > 4291 <span class="border-transparent border-b-text">China (CNY 4292 Â¥)</span 4293 > 4294 </button> 4295 </li> 4296 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 4297 <button 4298 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 4299 type="button" 4300 4301 @click.prevent="$refs.input.value = 'FR'; $root.closest('form').submit();" 4302 > 4303 <span class="border-transparent border-b-text">France (EUR 4304 â¬)</span 4305 > 4306 </button> 4307 </li> 4308 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 4309 <button 4310 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 4311 type="button" 4312 4313 @click.prevent="$refs.input.value = 'NZ'; $root.closest('form').submit();" 4314 > 4315 <span class="border-transparent border-b-text">New Zealand (NZD 4316 $)</span 4317 > 4318 </button> 4319 </li> 4320 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 4321 <button 4322 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 4323 type="button" 4324 4325 @click.prevent="$refs.input.value = 'GB'; $root.closest('form').submit();" 4326 > 4327 <span class="border-transparent border-b-text">United Kingdom (GBP 4328 £)</span 4329 > 4330 </button> 4331 </li> 4332 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 4333 <button 4334 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 4335 type="button" 4336 4337 aria-current="true" 4338 4339 @click.prevent="$refs.input.value = 'US'; $root.closest('form').submit();" 4340 > 4341 <span class="border-scheme-text border-b-text">United States (USD 4342 $)</span 4343 > 4344 </button> 4345 </li></ul> 4346 </div> 4347 4348 <input 4349 x-ref="input" 4350 type="hidden" 4351 name="country_code" 4352 id="CountrySelector" 4353 value="US" 4354 > 4355 </data-island> 4356 </div></div></form> 4357 </div> 4358 4359 4360 4361<form 4362 class="my-6 px-section-horizontal-spacing" 4363 action="/search" 4364 method="get" 4365 role="search" 4366 > 4367 <div class="flex w-full max-w-xs items-end"> 4368 <label for="menu-drawer-search" class="sr-only">Search</label> 4369 <input 4370 class="min-w-0 flex-auto border-b-text border-current bg-transparent py-1.5 placeholder-current" 4371 id="menu-drawer-search" 4372 type="text" 4373 name="q" 4374 placeholder="Search" 4375 > 4376 <button 4377 class="px-1" 4378 type="submit" 4379 >
4380 <span class="inline-block h-6 w-6"><svg 4381 class="theme-icon" 4382 xmlns="http://www.w3.org/2000/svg" 4383 fill="none" 4384 viewBox="0 0 24 24" 4385> 4386 <path stroke="currentColor" d="M2 11a9 9 0 1 0 18 0 9 9 0 0 0-18 0Zm15.364 6.364L22 22" vector-effect="non-scaling-stroke"/> 4387</svg> 4388</span> 4389 <span class="sr-only">Submit</span> 4390 </button> 4391 </div> 4392 </form> 4393 </div> 4394 </div> 4395 4396 </div> 4397 </section> 4398 4399 <style> 4400 .section-sidebar { 4401 display: block !important; 4402 } 4403 4404 @media (min-width: 1024px) { 4405 .section-sidebar { 4406 display: none !important; 4407 } 4408 } 4409 4410 .sidebar-container { 4411 position: static; 4412 width: 100%; 4413 max-width: 100%; 4414 border-right: 0; 4415 display: none; 4416 } 4417 4418 .section-sidebar:focus-within .sidebar-container { 4419 display: block !important; 4420 } 4421 </style> 4422</noscript> 4423 4424 4425</div>
4425<script> 4426 const calculateHeaderHeights = () => { 4427 const headerGroupHeights = []; 4428 4429 document 4430 .querySelectorAll('.shopify-section-group-header-group') 4431 .forEach((headerGroupSectionEl) => { 4432 headerGroupHeights.push( 4433 headerGroupSectionEl.getBoundingClientRect().height 4434 ); 4435 }); 4436 4437 document.documentElement.style.setProperty( 4438 '--header-group-height', 4439 `${headerGroupHeights.reduce((subtotal, a) => subtotal + a, 0)}px` 4440 ); 4441 }; 4442 4443 calculateHeaderHeights(); 4444 4445 if (document.readyState === 'loading') { 4446 document.addEventListener('DOMContentLoaded', calculateHeaderHeights); 4447 } 4448 window.addEventListener('load', calculateHeaderHeights); 4449 4450 const debouncedCalculateHeaderHeights = debounce(calculateHeaderHeights, 300); 4451 4452 window.addEventListener('resize', debouncedCalculateHeaderHeights); 4453</script>
4453 4454 4455 4456 4457<style> 4458 #MainContent 4459 > .shopify-section.banner-section:first-child 4460 [data-media-container].h-screen { 4461 height: calc(100vh - var(--header-group-height)); 4462 } 4463 4464 @media (min-width: 990px) { 4465 #MainContent 4466 > .shopify-section.banner-section:first-child 4467 [data-media-container].lg\:h-auto { 4468 height: auto; 4469 } 4470 4471 #MainContent 4472 > .shopify-section.banner-section:first-child 4473 [data-media-container].lg\:h-screen { 4474 height: calc(100vh - var(--header-group-height)); 4475 } 4476 } 4477</style> 4478 4479 4480 4481 <main id="MainContent"> 4482 <div id="shopify-section-template--21296461119558__cart-items" class="shopify-section"><section 4483 id="main-cart-items" 4484 class="border-b-gridline border-gridline-color bg-scheme-background text-scheme-text" 4485 data-color-scheme="" 4486> 4487 4488<data-island 4489 x-data="CartItems" 4490 data-cart-items 4491 on="idle" 4492> 4493 4494 4495 <div class="py-section-vertical-spacing px-section-horizontal-spacing"> 4496 <h1 class="font-heading text-heading-standard"> 4497 Your cart 4498 </h1> 4499 4500 <div class="mt-8"> 4501 <p class="mb-8">Your cart is currently empty.</p> 4502 <a 4503 class="theme-link inline-block text-scheme-text hover:text-scheme-accent" 4504 href="/" 4505 >Continue shopping</a> 4506 </div> 4507 </div> 4508 4509 <p 4510 class="sr-only" 4511 id="cart-live-region-text" 4512 aria-live="polite" 4513 role="status" 4514 ></p> 4515 <p 4516 class="sr-only" 4517 id="shopping-cart-line-item-status" 4518 aria-live="polite" 4519 aria-hidden="true" 4520 role="status" 4521 > 4522 Loading... 4523 </p> 4524</data-island> 4525 4526</section> 4527 4528 4529</div><div id="shopify-section-template--21296461119558__custom_liquid_jM7V3F" class="shopify-section"><section 4530 class="gap-gutter overflow-hidden border-b-gridline border-gridline-color bg-gridline-color text-scheme-text" 4531 data-color-scheme="scheme1" 4532> 4533 <div class="bg-scheme-background"> 4534 <div class="px-section-horizontal-spacing py-section-vertical-spacing"><h2 class="font-heading mb-4 text-2xl"></h2><!DOCTYPE html> 4535<html lang="en"> 4536<head> 4537 <meta charset="UTF-8"> 4538 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 4539 <title>Go Back Example</title> 4540 <style> 4541 /* Add any custom styles here */ 4542 .goback-link { 4543 text-decoration: underline; 4544 cursor: pointer; /* Ensures pointer cursor on hover */ 4545 color: #; /* Replace with your Shopify theme's primary color variable */ 4546 } 4547 </style> 4548</head> 4549<body> 4550 <!-- Your Shopify page content here --> 4551 4552 <span class="goback-link" onclick="goBack()">Go Back</span> 4553 4554 <!-- Your Shopify page content continues here --> 4555 4556
4556<script> 4557 function goBack() { 4558 window.history.back(); 4559 } 4560 </script>
4560 4561<div id="shopify-block-AWDJwL3lGQkF3Zitrd__39280165312039977" class="shopify-block shopify-app-block"> 4562 4563�
4563<script> 4564 console.log('[FulfillmentFee] Namespace: app--313853968385--fulfillment_fee'); 4565 console.log('[FulfillmentFee] Key: config'); 4566 console.log('[FulfillmentFee] Config value:', {"vendorFees":{"WÄtÄ FX Crew":5.75},"feeProductVariantId":"gid:\/\/shopify\/ProductVariant\/44486403227718","isEnabled":true}); 4567</script>
4567<script> 4568 (function() { 4569 // The metafield .value is already a parsed JSON object 4570 var configData = {"vendorFees":{"WÄtÄ FX Crew":5.75},"feeProductVariantId":"gid:\/\/shopify\/ProductVariant\/44486403227718","isEnabled":true}; 4571 if (configData && typeof configData === 'object') { 4572 window.__FULFILLMENT_FEE_CONFIG__ = configData; 4573 console.log('[FulfillmentFee] Config loaded:', window.__FULFILLMENT_FEE_CONFIG__); 4574 } else { 4575 console.error('[FulfillmentFee] Invalid config data:', configData); 4576 window.__FULFILLMENT_FEE_CONFIG__ = null; 4577 } 4578 })(); 4579</script>
vendor: 2 bytes, line 4579
4579
4580<script src="https://cdn.shopify.com/extensions/019d45d2-6a70-7eed-8da1-d1e8fd0fae86/fulfillment-fee-app-100/assets/fulfillment-fee-manager.js" defer></script>
4580 4581</div><div id="shopify-block-AWitpMC8rZDJCSlg4R__15573056287721514228" class="shopify-block shopify-app-block json-ld-for-seo"><!-- generated: 2026-10-04 21:38:25 +1300 --> 4582<!-- BEGIN app snippet: json_ld_for_seo_web_page -->
4582<script type="application/ld+json"> 4583 { 4584 "@context": "https://schema.org", 4585 "@type": "WebPage", 4586 "@id": "https:\/\/printroom.co\/cart#json-ld-for-seo-webpage", 4587 "url": "https:\/\/printroom.co\/cart", 4588 "image": null, 4589 "primaryImageOfPage": null, 4590 "dateCreated": null, 4591 "datePublished": null 4592 } 4593</script>
4593 4594<!-- END app snippet --> 4595<!-- wp 1 --><!-- BEGIN app snippet: json_ld_for_seo_organization -->
4596<script type="application/ld+json"> 4597{ 4598 "@context": "https://schema.org", 4599 "@type": "Organization","@id": "https:\/\/printroom.co\/#org", 4600 "name": "The Print Room", 4601 "url": "https:\/\/printroom.co", 4602 "description": "NZâs experts in custom t-shirt printing, tote bags, uniforms, and branded merchandise. Print Room offers high-quality screen printing and embroidery using eco-friendly inks. Fast turnaround, sustainable production, and trusted by leading New Zealand brands.", 4603 "telephone": "+6434259694", 4604 "logo": "https:\/\/cdn.shopify.com\/s\/images\/admin\/no-image-large.gif", 4605 "image": "https:\/\/cdn.shopify.com\/s\/images\/admin\/no-image-large.gif", 4606 "sameAs": ["","https:\/\/www.instagram.com\/printroomnz\/"], 4607 "address": { 4608 "@type": "PostalAddress", 4609 "streetAddress": "21 Grosvenor Street, 21", 4610 "addressLocality": "Dunedin", 4611 "addressRegion": "Otago", 4612 "postalCode": "9011", 4613 "addressCountry": "NZ" 4614 }, 4615 "contactPoint": [ 4616 { 4617 "@type": "ContactPoint", 4618 "telephone": "+6434259694", 4619 "email": "" 4620 } 4621 ]} 4622</script>
4622 4623<!-- END app snippet --> <!-- o 6 --><!-- BEGIN app snippet: json_ld_for_seo_product_group --><!-- END app snippet --> 4624<!-- p 1 --><!-- A 10 --> 4625 4626 4627</div></body> 4628</html> 4629 </div> 4630 </div> 4631</section> 4632 4633 4634</div><div id="shopify-section-template--21296461119558__cart-footer" class="shopify-section"><section 4635 id="main-cart-footer" 4636 class="text-scheme-text bg-scheme-background border-b-gridline border-gridline-color" 4637 data-color-scheme="scheme1" 4638> 4639 4640 4641<data-island 4642 x-data="CartFooter" 4643 data-cart-footer 4644 on="idle" 4645> 4646 <div class="hidden md:grid md:grid-cols-12 px-section-horizontal-spacing pb-theme"> 4647 4648 <div class="mt-4 md:col-span-5"> 4649 <label class="block" for="CartSpecialInstructions">Add a note to your order</label> 4650 <textarea 4651 class="mt-1 block w-full border-text border-current bg-transparent p-2 text-sm" 4652 name="note" 4653 id="CartSpecialInstructions" 4654 form="cart" 4655 :class="{ 'opacity-50 cursor-progress' : updating }" 4656 :readonly="updating" 4657 x-data="CartNote" 4658 x-model.debounce.750ms="note" 4659 ></textarea> 4660 </div> 4661 4662 <div class="mt-4 text-center md:col-span-5 md:col-start-8 lg:col-span-4 lg:col-start-9"> 4663 <dl class="grid grid-cols-2 text-right"><dt>Subtotal</dt> 4664 <dd>$0.00 USD</dd> 4665 </dl><p class="has-theme-links mt-4 text-right"> 4666 Tax included. <a href="/policies/shipping-policy">Shipping</a> calculated at checkout. 4667 4668 </p> 4669 4670 <div class="no-js:lg:grid no-js:lg:grid-cols-2 no-js:lg:gap-2 mt-4 w-full items-center justify-between"> 4671 <button 4672 class="theme-button--secondary hidden no-js:block" 4673 type="submit" 4674 name="update" 4675 form="cart" 4676 >Update</button><button 4677 class="mt-2 block w-full cursor-pointer rounded-button p-2 [text-transform:var(--button-text-transform)] after:content-[var(--button-after-content)] lg:mt-0 border-text border-button bg-button text-button hover:border-button-hover hover:bg-button-hover hover:text-button-hover" 4678 type="submit" 4679 name="checkout" 4680 form="cart" 4681 >Check out</button> 4682 </div> 4683 4684 4685 4686 <div 4687 class="mt-4 lg:text-right text-scheme-accent" 4688 id="cart-errors" 4689 ></div> 4690 </div> 4691 </div> 4692 4693 4694</data-island> 4695 4696 4697</section> 4698 4699 4700</div>
4700<script data-locksmith> 4701 var load = function () { 4702 4703 if (document.querySelectorAll('.locksmith-manual-trigger').length > 0) { 4704 Locksmith.ping(); 4705 } 4706 4707 4708 Locksmith.util.on('submit', 'locksmith-resource-form', function (event) { 4709 event.preventDefault(); 4710 var data = Locksmith.util.serializeForm(event.target); 4711 var options = { spinner: false, container: 'locksmith-content' }; 4712 // a form rendered inline (section replacement) must keep that context 4713 // on resubmit: same enclosing container (there may be several on the 4714 // page), and no layout classes or cancel affordance in the re-render 4715 var inlineContainer = event.target.closest && event.target.closest('[id^="locksmith-content"]'); 4716 if (inlineContainer) { 4717 options.container = inlineContainer; 4718 } 4719 if (event.target.getAttribute('data-locksmith-inline') === 'true') { 4720 options.include_layout_classes = false; 4721 } 4722 Locksmith.postResource(data, options); 4723 }); 4724 4725 Locksmith.util.on('click', 'locksmith-manual-trigger', function (event) { 4726 event.preventDefault(); 4727 Locksmith.postResource({}, { spinner: true, container: document }); 4728 }); 4729 4730 Locksmith.submitPasscode = function (passcode) { 4731 Locksmith.postResource( 4732 { passcode: passcode }, 4733 { spinner: false, container: 'locksmith-content' } 4734 ); 4735 }; 4736 }; 4737 4738 if (typeof Locksmith !== 'undefined') { 4739 load(); 4740 } else { 4741 window.addEventListener('load', load); 4742 } 4743 </script>
4743 4744 </main> 4745 4746 <!-- BEGIN sections: footer-group --> 4747<div id="shopify-section-sections--21296457154630__176903720293717250" class="shopify-section shopify-section-group-footer-group"> 4748 4749 4750 4751</div><div id="shopify-section-sections--21296457154630__footer" class="shopify-section shopify-section-group-footer-group"><footer 4752 class="bg-scheme-background text-scheme-text" 4753 data-color-scheme="scheme2" 4754 data-theme-footer 4755> 4756 4757 <section 4758 class="border-b-gridline border-gridline-color bg-scheme-background py-section-vertical-spacing text-scheme-text" 4759 data-color-scheme="scheme2" 4760> 4761 <div class="justify-center px-section-horizontal-spacing lg:flex lg:items-center lg:justify-between"> 4762 <div class="text-base"> 4763 4764 4765 4766 <div class="[&_a[href]]:underline [&_a[href]]:hover:text-scheme-accent"> 4767 <h2>We occasionally send out <strong>newsletters</strong>. You should sign up â</h2> 4768 </div> 4769 4770 </div> 4771 4772 <div class="mt-theme-half lg:mt-0"> 4773 <form method="post" action="/contact#Contact-sections--21296457154630__footer" id="Contact-sections--21296457154630__footer" accept-charset="UTF-8" class="contact-form"><input type="hidden" name="form_type" value="customer" /><input type="hidden" name="utf8" value="â" /> 4774 4775 4776 4777 <input type="hidden" name="contact[tags]" value="newsletter"> 4778 <div class="items-end lg:ml-4 lg:flex"> 4779 <label class="sr-only" for="Email-sections--21296457154630__footer">Email address</label> 4780 <input 4781 type="email" 4782 class="font-body block w-full border-b-text border-current bg-transparent pb-1 leading-[inherit] placeholder-current" 4783 name="contact[email]" 4784 id="Email-sections--21296457154630__footer" 4785 value="" 4786 placeholder="Email address" 4787 autocorrect="off" 4788 autocapitalize="off" 4789 > 4790 <button 4791 class="theme-link mt-2 shrink-0 py-1 leading-[inherit] hover:text-scheme-accent lg:ml-2 lg:mt-0" 4792 type="submit" 4793 name="commit" 4794 id="Subscribe" 4795 >Subscribe</button> 4796 </div> 4797 4798 </form> 4799 </div> 4800 </div> 4801</section> 4802 4803 4804 4805 <div class="border-b-gridline border-gridline-color"> 4806 <div 4807 class="grid lg:grid-cols-var bg-gridline-color" 4808 style="--grid-cols: 12;" 4809 ><div 4810 class="break-word bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text lg:col-span-var" 4811 style="--col-span: 3;" 4812 4813 ><div class="inline-block text-left"> 4814 4815 4816 <h2 class="font-heading mb-4 text-base"> 4817 Explore 4818 </h2> 4819 4820 <ul class="list-none space-y-1"> 4821 4822<li> 4823 <a 4824 href="/pages/all-products" 4825 class="hover:text-scheme-accent" 4826 > 4827 Products 4828 </a> 4829 </li> 4830 4831<li> 4832 <a 4833 href="/pages/services" 4834 class="hover:text-scheme-accent" 4835 > 4836 Services 4837 </a> 4838 </li> 4839 4840<li> 4841 <a 4842 href="https://www.theprintroom.nz/apps/order-tracker" 4843 class="hover:text-scheme-accent" 4844 > 4845 Track your order 4846 </a> 4847 </li> 4848 4849<li> 4850 <a 4851 href="/pages/responsibility" 4852 class="hover:text-scheme-accent" 4853 > 4854 Responsibility 4855 </a> 4856 </li> 4857 4858<li> 4859 <a 4860 href="/pages/about-print-room" 4861 class="hover:text-scheme-accent" 4862 > 4863 About us 4864 </a> 4865 </li> 4866 4867 </ul> 4868 </div></div><div 4869 class="break-word bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text lg:col-span-var" 4870 style="--col-span: 3;" 4871 4872 ><div class="inline-block text-left"> 4873 4874 4875 <h2 class="font-heading mb-4 text-base"> 4876 Helpful stuff 4877 </h2> 4878 4879 <ul class="list-none space-y-1"> 4880 4881<li> 4882 <a 4883 href="/pages/screen-printing-faqs-the-print-room-quality-screen-printing-garment-design-blank-clothing" 4884 class="hover:text-scheme-accent" 4885 > 4886 FAQs 4887 </a> 4888 </li> 4889 4890<li> 4891 <a 4892 href="https://help.theprintroom.nz/" 4893 class="hover:text-scheme-accent" 4894 > 4895 Resource hub 4896 </a> 4897 </li> 4898 4899<li> 4900 <a 4901 href="/pages/catalogue" 4902 class="hover:text-scheme-accent" 4903 > 4904 Catalogues 4905 </a> 4906 </li> 4907 4908<li> 4909 <a 4910 href="/blogs/the-print-room-nz" 4911 class="hover:text-scheme-accent" 4912 > 4913 Blogs 4914 </a> 4915 </li> 4916 4917<li> 4918 <a 4919 href="/pages/policies" 4920 class="hover:text-scheme-accent" 4921 >
4922 Policies & T&Cs 4923 </a> 4924 </li> 4925 4926 </ul> 4927 </div></div><div 4928 class="break-word bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text lg:col-span-var" 4929 style="--col-span: 3;" 4930 4931 > 4932 <h2 class="font-heading break-word mb-4 text-base"> 4933 Get in touch - NZ 4934 </h2> 4935 4936<div class="rte"> 4937 <p>21 Grosvenor St, Kensington, Dunedin,<br/>9012<br/>[email protected]<br/>NZ: 03 425 9694</p> 4938 </div></div><div 4939 class="break-word bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text lg:col-span-var" 4940 style="--col-span: 3;" 4941 4942 > 4943 <h2 class="font-heading break-word mb-4 text-base"> 4944 Get in touch - AUS 4945 </h2> 4946 4947<div class="rte"> 4948 <p>The Commons, 10â20 Gwynne St, Cremorne VIC 3121<br/>[email protected]<br/>+61 (0) 451 701 385</p> 4949 </div></div></div> 4950 </div> 4951 4952 4953 <div> 4954 <div class="px-section-horizontal-spacing py-section-vertical-spacing lg:flex lg:flex-wrap lg:items-center lg:justify-between"> 4955 <div class="mb-4 space-y-2 text-sm lg:mb-0 lg:flex-1"> 4956 <p> 4957 © 2026, 4958 <a href="/" title="">The Print Room</a>. 4959 </p> 4960 <ul class="flex flex-wrap gap-1 text-sm [&>li:last-child]:after:content-none [&>li]:after:content-['\00B7']"> 4961 <li> 4962 4963 </li></ul> 4964 </div> 4965 4966</div> 4967 </div> 4968</footer> 4969 4970 4971 <style> 4972 .footer-logo-image { 4973 display: block; 4974 max-width: px; 4975 } 4976 </style> 4977 4978 4979 4980<style> #shopify-section-sections--21296457154630__footer .text-base {font-size: 20px;} #shopify-section-sections--21296457154630__footer .font-heading {text-decoration: underline;} #shopify-section-sections--21296457154630__footer .inline-block {line-height: 1.7;} #shopify-section-sections--21296457154630__footer /*.bg-scheme-background {border-top: 1px solid black;}*/.text-scheme-text {border-bottom: 1px solid black;} </style></div> 4981<!-- END sections: footer-group --><!-- BEGIN sections: overlay-group --> 4982<div id="shopify-section-sections--21296457220166__promo-popup" class="shopify-section shopify-section-group-overlay-group contents"> 4983 4984 4985</div><div id="shopify-section-sections--21296457220166__age-check" class="shopify-section shopify-section-group-overlay-group contents"> 4986</div><div id="shopify-section-sections--21296457220166__privacy-banner" class="shopify-section shopify-section-group-overlay-group contents"> 4987 4988 4989</div> 4990<!-- END sections: overlay-group --> 4991 4992 <div 4993 id="screenreader-announce" 4994 class="sr-only" 4995 aria-live="polite" 4996 role="status" 4997 ></div> 4998 4999 <ul hidden> 5000 <li id="a11y-refresh-page-message"> 5001 Choosing a selection results in a full page refresh. 5002 </li> 5003 <li id="a11y-selection-message"> 5004 Press the space key then arrow keys to make a selection. 5005 </li> 5006 </ul> 5007 5008 5009 <data-island 5010 role="complementary" 5011 aria-labelledby="left-drawer-slot" 5012 x-data 5013 on="load" 5014> 5015 <template x-teleport="body"> 5016 <div 5017 x-show="$store.modals.leftDrawer.open" 5018 @keydown.escape.prevent.stop="$store.modals.close('leftDrawer')" 5019 @click="$store.modals.close('leftDrawer')" 5020 class="fixed inset-0 z-110" 5021 data-color-scheme="scheme1" 5022 id="modals-leftDrawer" 5023 > 5024 <div 5025 @click.stop 5026 x-show="$store.modals.leftDrawer.open" 5027 x-transition:enter="duration-300 motion-reduce:duration-0 outline-0" 5028 x-transition:enter-start="opacity-0 -translate-x-full" 5029 x-transition:leave="duration-300 motion-reduce:duration-0 outline-0" 5030 x-transition:leave-end="-translate-x-full" 5031 x-trap.noscroll.inert="$store.modals.leftDrawer.open" 5032 class="mr-auto h-full w-11/12 max-w-md transform overflow-y-auto border-r-gridline border-gr
5032idline-color bg-scheme-background text-scheme-text transition-transform" 5033 id="left-drawer-slot" 5034 role="dialog" 5035 @left-drawer-is-open.window="setTimeout(() => { $el.setAttribute('aria-modal', 'true') }, 120)" 5036 @left-drawer-is-closed.window="setTimeout(() => { $el.removeAttribute('aria-modal') }, 120)" 5037 :aria-label="getModalLabel('leftDrawer', $el)" 5038 tabindex="-1" 5039 > 5040 <!-- Modal content is teleported here --> 5041 </div> 5042 </div> 5043 </template> 5044</data-island> 5045<data-island 5046 role="complementary" 5047 aria-labelledby="right-drawer-slot" 5048 x-data 5049 on="load" 5050> 5051 <template x-teleport="body"> 5052 <div 5053 x-show="$store.modals.rightDrawer.open" 5054 @keydown.escape.prevent.stop="$store.modals.close('rightDrawer')" 5055 @click="$store.modals.close('rightDrawer')" 5056 class="fixed inset-0 z-110" 5057 style="background: rgba(208,208,208,0.2); backdrop-filter: blur(1.5px); -webkit-backdrop-filter: blur(1.5px);" 5058 data-color-scheme="scheme1" 5059 id="modals-rightDrawer" 5060 > 5061 <div 5062 @click.stop 5063 x-show="$store.modals.rightDrawer.open" 5064 x-transition:enter="duration-300 motion-reduce:duration-0 outline-0" 5065 x-transition:enter-start="translate-x-full" 5066 x-transition:leave="duration-300 motion-reduce:duration-0 outline-0" 5067 x-transition:leave-end="translate-x-full" 5068 x-trap.noscroll.inert="$store.modals.rightDrawer.open" 5069 class="ml-auto h-full w-11/12 max-w-lg transform overflow-y-auto bg-scheme-background text-scheme-text" 5070 style="border-left: 2px solid black;" 5071 id="right-drawer-slot" 5072 role="dialog" 5073 @right-drawer-is-open.window="setTimeout(() => { $el.setAttribute('aria-modal', 'true') }, 120)" 5074 @right-drawer-is-closed.window="setTimeout(() => { $el.removeAttribute('aria-modal') }, 120)" 5075 :aria-label="getModalLabel('rightDrawer', $el)" 5076 tabindex="-1" 5077 > 5078 <!-- Modal content is teleported here --> 5079 </div> 5080 </div> 5081 </template> 5082</data-island> 5083<data-island 5084 role="complementary" 5085 aria-labelledby="quick-buy-drawer-slot-container" 5086 x-data 5087 on="load" 5088> 5089 <template x-teleport="body"> 5090 <div 5091 x-show="$store.modals.quickBuyDrawer.open" 5092 @keydown.escape.prevent.stop="$store.modals.close('quickBuyDrawer')" 5093 @click="$store.modals.close('quickBuyDrawer')" 5094 class="fixed inset-0 z-110 flex lg:block" 5095 data-color-scheme="scheme1" 5096 id="modals-quickBuyDrawer" 5097 > 5098 <div 5099 @click.stop 5100 id="quick-buy-drawer-slot-container" 5101 x-show="$store.modals.quickBuyDrawer.open" 5102 x-transition:enter="duration-300 motion-reduce:duration-0 outline-0" 5103 x-transition:enter-start="max-lg:translate-y-full lg:translate-x-full" 5104 x-transition:leave="duration-300 motion-reduce:duration-0 outline-0" 5105 x-transition:leave-end="max-lg:translate-y-full lg:translate-x-full" 5106 x-trap.noscroll.inert="$store.modals.quickBuyDrawer.open" 5107 class="mt-auto h-auto w-full transform border-gridline-color bg-scheme-background text-scheme-text lg:ml-auto lg:h-full lg:w-11/12 lg:max-w-md lg:overflow-y-auto lg:border-l-gridline" 5108 role="dialog" 5109 @quick-buy-drawer-is-open.window="setTimeout(() => { $el.setAttribute('aria-modal', 'true') }, 120)" 5110 @quick-buy-drawer-is-closed.window="setTimeout(() => { $el.removeAttribute('aria-modal') }, 120)" 5111 :aria-label="getModalLabel('quickBuyDrawer', document.getElementById('quick-buy-drawer-slot'))" 5112 tabindex="-1" 5113 > 5114 <div class="sticky top-0 z-1 flex items-center justify-between border-y-gridline border-gridline-color bg-scheme-background px-section-horizontal-spacing py-4 lg:border-t-0"> 5115 <div> 5116 Choose options 5117 </div> 5118 <button 5119 @click.prevent="$store.modals.close('quickBuyDrawer')" 5120 class="absolute right-0 top-0 block h-full" 5121 type="button" 5122 > 5123 <span class="sr-only">Close</span> 5124 <div class="my-auto mr-section-horizontal-spacing h-6 w-6"> 5125 <svg 5126 class="theme-icon" 5127 xmlns="http://www.w3.org/2000/svg" 5128 fill="none" 5129 viewBox="0 0 24 24" 5130> 5131 <path stroke="currentColor" d="m1.5 1.5 21 21m0-21-21 21" vector-effect="non-scaling-stroke"/> 5132</svg> 5133 5134 </div> 5135 </button> 5136 </div> 5137 <div 5138 id="quick-buy-drawer-slot" 5139 class="max-lg:h-fit max-lg:max-h-[65vh] max-lg:overflow-y-auto" 5140 ></div> 5141 </div> 5142 </div> 5143 </template> 5144</data-island> 5145<data-island 5146 x-data 5147 on="load" 5148> 5149 <template x-teleport="body"> 5150 <div 5151 x-show="$store.modals.promo.open" 5152 class="pointer-events-none fixed inset-0 z-110" 5153 id="modals-promo" 5154 > 5155 <div 5156 x-show="$store.modals.promo.open" 5157 class="flex h-full w-full" 5158 > 5159 <div 5160 x-show="$store.modals.promo.open" 5161 x-transition:enter="transition duration-300 motion-reduce:duration-0 delay-75 outline-0" 5162 x-transition:enter-start="translate-y-full" 5163 x-transition:enter-end="translate-y-0" 5164 x-transition:leave="transition duration-300 motion-reduce:duration-0 outline-0" 5165 x-transition:leave-start="translate-y-0" 5166 x-transition:leave-end="translate-y-full" 5167 class="pointer-events-auto relative bottom-0 left-0 right-0 top-auto mt-auto w-full overflow-y-auto" 5168 id="promo-slot" 5169 role="dialog" 5170 @promo-is-open.window="setTimeout(() => { $el.setAttribute('aria-modal', 'true') }, 120)" 5171 @promo-is-closed.window="setTimeout(() => { $el.removeAttribute('aria-modal') }, 120)" 5172 :aria-label="getModalLabel('promo', $el)" 5173 tabindex="-1" 5174 > 5175 <!-- Modal content is teleported here --> 5176 </div> 5177 </div> 5178 </div> 5179 </template> 5180</data-island> 5181<data-island x-data on="load"> 5182 <template x-teleport="body"> 5183 <div 5184 x-show="$store.modals.popup.open" 5185 @keydown.escape.prevent.stop="$store.modals.close('popup')" 5186 @click="$store.modals.close('popup')" 5187 class="fixed inset-0 z-110 p-8 lg:p-24" 5188 data-color-scheme="scheme1" 5189 id="modals-popup" 5190 > 5191 <div 5192 x-show="$store.modals.popup.open" 5193 class="fixed inset-0 bg-transparent" 5194 > 5195 <!-- Overlay --> 5196 </div> 5197 <div 5198 x-show="$store.modals.popup.open" 5199 class="flex h-full w-full" 5200 > 5201 <div 5202 @click.stop 5203 x-show="$store.modals.popup.open" 5204 x-trap.noscroll.inert="$store.modals.popup.open" 5205 class="relative m-auto max-h-full w-full max-w-2xl overflow-y-auto border-gr
5205idline border-gridline-color bg-scheme-background text-scheme-text" 5206 id="popup-slot" 5207 role="dialog" 5208 @popup-is-open.window="setTimeout(() => { $el.setAttribute('aria-modal', 'true') }, 120)" 5209 @popup-is-closed.window="setTimeout(() => { $el.removeAttribute('aria-modal') }, 120)" 5210 :aria-label="getModalLabel('popup', $el)" 5211 tabindex="-1" 5212 > 5213 <!-- Modal content is teleported here --> 5214 </div> 5215 </div> 5216 </div> 5217 </template> 5218</data-island> 5219<data-island x-data on="load"> 5220 <template x-teleport="body"> 5221 <div 5222 x-show="$store.modals.modal.open" 5223 x-transition:enter="transition ease-out duration-300" 5224 x-transition:enter-start="opacity-0" 5225 x-transition:enter-end="opacity-100" 5226 x-transition:leave="transition ease-in duration-200" 5227 x-transition:leave-start="opacity-100" 5228 x-transition:leave-end="opacity-0" 5229 @keydown.escape.prevent.stop="$store.modals.close('modal')" 5230 @click="$store.modals.close('modal')" 5231 class="fixed inset-0 z-110 bg-black/40 backdrop-blur-md" 5232 style="backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);" 5233 data-color-scheme="scheme1" 5234 id="modals-modal" 5235 > 5236 <div 5237 x-show="$store.modals.modal.open" 5238 class="flex h-full w-full justify-center p-2 sm:p-4 md:p-6 lg:p-8" 5239 :class="$store.modals.modal.contents === 'quoteRequest' ? 'items-stretch sm:items-center sm:p-6 lg:p-10' : 'items-center'" 5240 > 5241 <div 5242 @click.stop 5243 x-show="$store.modals.modal.open" 5244 x-transition:enter="transition ease-out duration-300" 5245 x-transition:enter-start="opacity-0 scale-95 translate-y-4" 5246 x-transition:enter-end="opacity-100 scale-100 translate-y-0" 5247 x-transition:leave="transition ease-in duration-200" 5248 x-transition:leave-start="opacity-100 scale-100 translate-y-0" 5249 x-transition:leave-end="opacity-0 scale-95 translate-y-4" 5250 x-trap.inert="$store.modals.modal.open" 5251 class="relative flex w-full flex-col overflow-hidden text-scheme-text" 5252 :class="$store.modals.modal.contents === 'quoteRequest' 5253 ? 'max-w-2xl max-h-[100dvh] sm:max-h-[calc(100dvh-48px)] rounded-none sm:rounded-[24px]' 5254 : 'max-w-lg sm:max-w-xl md:max-w-2xl lg:max-w-3xl max-h-[calc(100vh-24px)] sm:max-h-[calc(100vh-48px)] md:max-h-[calc(100vh-64px)] lg:max-h-[calc(100vh-96px)] rounded-[20px]'" 5255 style="background: #FBFBF6; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);" 5256 id="modal-slot" 5257 role="dialog" 5258 @modal-is-open.window="setTimeout(() => { $el.setAttribute('aria-modal', 'true') }, 120)" 5259 @modal-is-closed.window="setTimeout(() => { $el.removeAttribute('aria-modal') }, 120)" 5260 :aria-label="getModalLabel('modal', $el)" 5261 tabindex="-1" 5262 > 5263 <!-- Modal content is teleported here --> 5264 </div> 5265 </div> 5266 </div> 5267 </template> 5268</data-island> 5269 5270 5271 5272 5273 5274 5275 <style> 5276 /* Push chatbot left when quote drawer is open */ 5277 body:has([data-favorites-drawer]:not([style*="display: none"])) #tidio-chat, 5278 body:has([data-favorites-drawer]:not([style*="display: none"])) .tidio-chat, 5279 body:has([data-favorites-drawer]:not([style*="display: none"])) iframe[title*="chat" i], 5280 body:has([data-favorites-drawer]:not([style*="display: none"])) iframe[title*="tidio" i], 5281 body:has([data-favorites-drawer]:not([style*="display: none"])) [class*="chat-widget"], 5282 body:has([data-favorites-drawer]:not([style*="display: none"])) [id*="chat-widget"] { 5283 transform: translateX(-464px) !important; 5284 transition: transform 0.3s ease !important; 5285 } 5286 5287 /* Push AI chatbot trigger left when drawer is open - desktop only */ 5288 @media (min-width: 768px) { 5289 body:has([data-favorites-drawer]:not([style*="display: none"])) .ai-chatbot__trigger { 5290 right: calc(32rem + 24px) !important; 5291 transition: right 0.3s ease, transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease !important; 5292 } 5293 } 5294 5295 /* Override theme color scheme â force black text throughout drawer */ 5296 [data-favorites-drawer] { 5297 --color-scheme-text: 0 0 0 !important; 5298 } 5299 [data-favorites-drawer] h2 { 5300 letter-spacing: 0px !important; 5301 } 5302 @media (max-width: 639px) { 5303 [data-favorites-drawer] h2 { 5304 text-align: left !important; 5305 } 5306 } 5307 [data-favorites-drawer] *, 5308 [data-favorites-drawer] h2, 5309 [data-favorites-drawer] p, 5310 [data-favorites-drawer] a, 5311 [data-favorites-drawer] span, 5312 [data-favorites-drawer] div, 5313 [data-favorites-drawer] li { 5314 color: black !important; 5315 } 5316 5317 /* Close button stays muted */ 5318 [data-favorites-drawer] button[aria-label*="Close"], 5319 [data-favorites-drawer] button[aria-label*="Close"] svg { 5320 color: rgba(0,0,0,0.4) !important; 5321 } 5322 5323 /* Remove button stays muted, red on hover */ 5324 [data-favorites-drawer] button[aria-label*="Remove"],
5325 [data-favorites-drawer] button[aria-label*="Remove"] svg { 5326 color: rgba(0,0,0,0.3) !important; 5327 } 5328 [data-favorites-drawer] button[aria-label*="Remove"]:hover, 5329 [data-favorites-drawer] button[aria-label*="Remove"]:hover svg { 5330 color: #ef4444 !important; 5331 } 5332 5333 /* Product dividers â solid black */ 5334 [data-favorites-drawer] li { 5335 border-bottom: 1px solid black !important; 5336 } 5337 [data-favorites-drawer] li:last-child { 5338 border-bottom: none !important; 5339 } 5340 5341 /* Footer dividers â solid black */ 5342 [data-favorites-drawer] .drawer-divider { 5343 border-top: 1px solid black !important; 5344 } 5345 5346 /* Start quote button â visible border */ 5347 [data-favorites-drawer] .drawer-cta-btn { 5348 border: 2px solid #4B4D72 !important; 5349 color: #4B4D72 !important; 5350 } 5351 [data-favorites-drawer] .drawer-cta-btn:hover { 5352 background-color: #4B4D72 !important; 5353 color: #fff !important; 5354 } 5355</style> 5356 5357<data-island 5358 x-data="FavoritesDrawer" 5359 on="idle" 5360 x-cloak 5361> 5362 <div> 5363 <template x-teleport="#right-drawer-slot"> 5364 <div 5365 class="flex h-full flex-col overflow-hidden" style="background: #FBFBF6;" 5366 :data-modal-label="`Your current project - ${$store.favorites.countWithText()}`" 5367 x-show="$store.modals.rightDrawer.contents === 'favorites'" 5368 data-favorites-drawer 5369 ><div class="relative shrink-0" style="padding: 80px 40px 24px;"> 5370 <button 5371 @click.prevent="$store.modals.close('favorites')" 5372 class="absolute rounded-full p-2 transition-colors" 5373 style="top: 19px; right: 19px; color: rgba(0,0,0,0.4);" 5374 type="button" 5375 > 5376 <span class="sr-only">Close project drawer</span> 5377 <svg width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-width="2" d="m6 6 12 12m0-12-12 12"/></svg> 5378 </button> 5379 <h2 id="FavoritesTitle" tabindex="-1" class="font-bold" style="font-size: 41px; letter-spacing: 0px; line-height: 1; color: black; text-align: center;"> 5380 Your current project 5381 </h2> 5382 </div><div class="flex-1 overflow-y-auto" style="padding: 20px 40px; min-height: 0;"><template x-if="$store.favorites.count === 0"> 5383 <div class="flex flex-col items-center justify-center py-12 text-center"> 5384 <p class="mb-2 text-base font-medium text-scheme-text">No products yet</p> 5385 <p class="mx-auto mb-8 max-w-xs text-sm text-scheme-text/60">Browse our products and add items to your project.</p> 5386 <a 5387 href="/collections/product-library" 5388 class="inline-flex items-center justify-center font-light transition" 5389 style="border: 2px solid #4B4D72; color: #4B4D72; border-radius: 50px; padding: 18px 48px; font-size: 24px;" 5390 onmouseover="this.style.backgroundColor='#4B4D72'; this.style.color='#fff';" 5391 onmouseout="this.style.backgroundColor='transparent'; this.style.color='#4B4D72';" 5392 @click="$store.modals.close('favorites')" 5393 > 5394 Browse Products 5395 </a> 5396 </div> 5397 </template><template x-if="$store.favorites.count > 0"> 5398 <ul> 5399 <template x-for="item in $store.favorites.items" :key="item.key"> 5400 <li class="flex items-center" style="padding: 20px 0; gap: 16px;"> 5401 <button 5402 @click="$store.favorites.remove(item.key)" 5403 class="shrink-0 rounded-full p-1 transition-colors hover:text-red-500" 5404 style="color: rgba(0,0,0,0.3);" 5405 :aria-label="'Remove ' + item.title" 5406 > 5407 <svg width="19" height="19" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-width="2" d="m6 6 12 12m0-12-12 12"/></svg> 5408 </button> 5409 <a :href="item.url" class="block shrink-0 overflow-hidden bg-gray-100" style="width: 90px; height: 90px;"> 5410 <img :src="item.image" :alt="item.title" class="h-full w-full object-cover" loading="lazy" width="90" height="90"> 5411 </a> 5412 <div class="min-w-0 flex-1"> 5413 <p style="font-size: 16px; font-weight: 300; line-height: 18px; color: black;" x-text="item.vendor || ''"></p> 5414 <a :href="item.url" class="line-clamp-1" style="font-size: 16px; font-weight: 600; line-height: 18px; color: black;" x-text="item.title"></a> 5415 <p class="text-xs text-gray-600" x-text="item.colour || (item.hasColours ? 'Colour TBC' : '')"></p> 5416 </div> 5417 </li> 5418 </template> 5419 </ul> 5420 </template> 5421 </div><div class="shrink-0" style="padding: 0 40px 48px;"> 5422 <template x-if="$store.favorites.count > 0"> 5423 <div>
5424 <div class="drawer-divider" style="padding-top: 28px;"> 5425 <p style="font-size: 23px; font-weight: 300; line-height: 30px;">Get a quote for these products.</p> 5426 </div> 5427 <div class="drawer-divider" style="margin-top: 24px; padding-top: 24px;"> 5428 <p style="font-size: 15px; line-height: 20px;">Once submitted, one of our team will provide a more accurate quote based on the information provided. We aim to have a quote back to you within 5 working days.</p> 5429 </div> 5430 <button 5431 @click="$store.modals.close('favorites'); setTimeout(() => $store.modals.open('quoteRequest'), 300)" 5432 class="drawer-cta-btn inline-flex w-full items-center justify-center text-center transition" 5433 style="margin-top: 24px; min-height: 79px; border-radius: 50px; font-size: 27px; font-weight: 300;" 5434 > 5435 Start quote request 5436 </button> 5437 </div> 5438 </template> 5439 </div> 5440 </div> 5441 </template> 5442 </div> 5443</data-island> 5444 5445 5446 5447 <style> 5448 :root { 5449 --color-quote-accent: #2B3990; 5450 } 5451 5452 /* Modal inputs */ 5453 .qr-input, 5454 .qr-select { 5455 width: 100%; 5456 min-height: 2.15rem; 5457 border: 0.666px solid black; 5458 border-radius: 9999px; 5459 padding: 0.5rem 1rem; 5460 background: transparent; 5461 color: #111827; 5462 font-size: 0.875rem; 5463 transition: border-color 0.2s ease, box-shadow 0.2s ease; 5464 } 5465 5466 .qr-textarea { 5467 width: 100%; 5468 border: 0.75px solid black; 5469 border-radius: 10px; 5470 padding: 0.75rem 1rem; 5471 background: transparent; 5472 color: #111827; 5473 font-size: 0.875rem; 5474 resize: vertical; 5475 transition: border-color 0.2s ease, box-shadow 0.2s ease; 5476 } 5477 5478 .qr-input:focus, 5479 .qr-select:focus, 5480 .qr-textarea:focus { 5481 outline: none; 5482 border-color: var(--color-quote-accent, #2B3990); 5483 box-shadow: 0 0 0 3px rgba(43, 57, 144, 0.1); 5484 } 5485 5486 /* Ensure date & select inputs stay pill-shaped */ 5487 input[type="date"].qr-input, 5488 select.qr-select { 5489 border-radius: 9999px !important; 5490 padding-left: 1rem; 5491 padding-right: 2.5rem; 5492 } 5493 5494 input[type="date"].qr-input::-webkit-calendar-picker-indicator { 5495 opacity: 0.4; 5496 cursor: pointer; 5497 } 5498 5499 /* Budget slider */ 5500 .qr-slider { 5501 -webkit-appearance: none; 5502 appearance: none; 5503 width: 100%; 5504 height: 28px; 5505 background: transparent; 5506 outline: none; 5507 cursor: pointer; 5508 position: relative; 5509 z-index: 2; 5510 touch-action: none; 5511 margin: 0; 5512 padding: 0; 5513 } 5514 5515 .qr-slider::-webkit-slider-runnable-track { 5516 height: 6px; 5517 border-radius: 9999px; 5518 background: var(--slider-track, #e5e7eb); 5519 cursor: pointer; 5520 } 5521 5522 .qr-slider::-webkit-slider-thumb { 5523 -webkit-appearance: none; 5524 appearance: none; 5525 width: 24px; 5526 height: 24px; 5527 border-radius: 50%; 5528 background: #658a6a; 5529 cursor: grab; 5530 box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15); 5531 margin-top: -9px; 5532 border: 2px solid #fff; 5533 } 5534 5535 .qr-slider::-webkit-slider-thumb:active { 5536 cursor: grabbing; 5537 transform: scale(1.1); 5538 box-shadow: 0 3px 8px rgba(0, 0, 0, 0.2); 5539 } 5540 5541 .qr-slider::-moz-range-track { 5542 height: 6px; 5543 border-radius: 9999px; 5544 background: var(--slider-track, #e5e7eb); 5545 cursor: pointer; 5546 } 5547 5548 .qr-slider::-moz-range-thumb { 5549 width: 24px; 5550 height: 24px; 5551 border: 2px solid #fff; 5552 border-radius: 50%; 5553 background: #658a6a; 5554 cursor: grab; 5555 box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15); 5556 } 5557 5558 .qr-slider::-moz-range-thumb:active { 5559 cursor: grabbing; 5560 } 5561 5562 .qr-slider::-moz-range-progress { 5563 height: 6px; 5564 border-radius: 9999px; 5565 background: #658a6a; 5566 } 5567 5568 /* Pill buttons for per-product fields */ 5569 .qr-pill { 5570 display: inline-flex; 5571 height: 23px; 5572 align-items: center; 5573 justify-content: center; 5574 gap: 0.25rem; 5575 border: 0.666px solid black; 5576 border-radius: 9999px; 5577 padding: 0 0.75rem; 5578 background: #eee; 5579 color: #111827; 5580 font-size: 10.65px; 5581 font-weight: 400; 5582 cursor: pointer; 5583 transition: border-color 0.15s, background 0.15s; 5584 white-space: nowrap; 5585 position: relative; 5586 } 5587 5588 .qr-pill:hover { 5589 border-color: black; 5590 background: #e2e2e2; 5591 } 5592 5593 .qr-pill--active { 5594 border-color: black; 5595 color: #111827; 5596 background: #e2e2e2; 5597 } 5598 5599 .qr-pill--required { 5600 border-color: #dc2626; 5601 } 5602 5603 /* Pills grid: fixed equal columns across all rows */ 5604 .qr-pills-row { 5605 display: grid; 5606 grid-template-columns: repeat(3, 1fr); 5607 } 5608 5609 /* Popover for pill fields */ 5610 .qr-popover { 5611 position: absolute; 5612 top: calc(100% + 6px); 5613 left: 0; 5614 z-index: 50; 5615 min-width: 14rem; 5616 border: 0.666px solid black; 5617 border-radius: 8px; 5618 background: #fff; 5619 padding: 0.75rem; 5620 box-shadow: 0 3px 7px 0 rgba(0, 0, 0, 0.4); 5621 } 5622 5623 /* Product item rows */ 5624 .qr-product-row { 5625 border-bottom: 1px solid black !important; 5626 padding: 0.75rem 0; 5627 } 5628 5629 .qr-product-row:last-child { 5630 border-bottom: none !important; 5631 } 5632 5633 /* Submit button */ 5634 .qr-submit { 5635 display: flex; 5636 height: 70px; 5637 width: 100%; 5638 max-width: 351px; 5639 margin-left: auto; 5640 margin-right: auto; 5641 align-items: center; 5642 justify-content: center; 5643 border-radius: 50px; 5644 border: 2px solid #4B4D72; 5645 padding: 0.85rem 1.5rem; 5646 background: #4B4D72; 5647 color: #fff; 5648 font-size: 1.5rem; 5649 font-weight: 400; 5650 transition: opacity 0.2s ease, transform 0.2s ease; 5651 } 5652 5653 .qr-submit:hover { 5654 background: #3d3f5e; 5655 border-color: #3d3f5e; 5656 transform: translateY(-1px); 5657 } 5658 5659 .qr-submit:disabled { 5660 opacity: 0.4;
5661 cursor: not-allowed; 5662 transform: none; 5663 } 5664 5665 /* Outlined button */ 5666 .qr-btn-outline { 5667 display: inline-flex; 5668 min-height: 2.75rem; 5669 align-items: center; 5670 justify-content: center; 5671 border: 1.5px solid #4B4D72; 5672 border-radius: 9999px; 5673 padding: 0.65rem 1.5rem; 5674 background: transparent; 5675 color: #4B4D72; 5676 font-size: 0.875rem; 5677 font-weight: 600; 5678 transition: background-color 0.2s ease, color 0.2s ease; 5679 } 5680 5681 .qr-btn-outline:hover { 5682 background: #4B4D72; 5683 color: #fff; 5684 } 5685 5686 @media (max-width: 639px) { 5687 .qr-popover { 5688 position: fixed; 5689 top: auto; 5690 bottom: 0; 5691 left: 0; 5692 right: 0; 5693 min-width: 100%; 5694 border-radius: 8px 8px 0 0; 5695 padding: 1rem; 5696 box-shadow: 0 -3px 7px 0 rgba(0, 0, 0, 0.4); 5697 } 5698 } 5699 5700 /* Fix: Tailwind arbitrary rounded class not compiled */ 5701 @media (min-width: 640px) { 5702 .sm\:rounded-\[24px\] { 5703 border-radius: 27px; 5704 } 5705 } 5706 5707 /* Fix: Tailwind sm:grid-cols-2 not compiled in this theme */ 5708 @media (min-width: 640px) { 5709 [data-quote-request-modal] .sm\:grid-cols-2 { 5710 grid-template-columns: repeat(2, minmax(0, 1fr)); 5711 } 5712 } 5713 5714 /* Make overlay scroll instead of modal body */ 5715 #modals-modal:has([data-quote-request-modal]) { 5716 overflow-y: auto; 5717 } 5718 5719 /* Flex container: min-height instead of fixed height, always center */ 5720 #modals-modal:has([data-quote-request-modal]) > div { 5721 height: auto; 5722 min-height: 100%; 5723 align-items: center; 5724 } 5725 5726 /* Card: remove max-height constraint, allow natural sizing, always rounded */ 5727 #modals-modal:has([data-quote-request-modal]) #modal-slot { 5728 max-height: none !important; 5729 overflow: visible !important; 5730 border-radius: 27px; 5731 border: 1.75px solid black; 5732 box-shadow: 0px 4px 13px 2px rgba(0, 0, 0, 0.1); 5733 } 5734 5735 /* Fix: Tailwind sm:flex-nowrap not compiled */ 5736 @media (min-width: 640px) { 5737 .qr-product-row { 5738 flex-wrap: nowrap; 5739 } 5740 } 5741 5742 /* Content div: match card rounding */ 5743 [data-quote-request-modal] { 5744 border-radius: 27px; 5745 overflow: visible !important; 5746 } 5747 5748 /* All modal text defaults to black per Figma */ 5749 [data-quote-request-modal] label, 5750 [data-quote-request-modal] h3, 5751 [data-quote-request-modal] p, 5752 [data-quote-request-modal] span { 5753 color: black; 5754 } 5755 5756 /* Preserve intentional non-black colors */ 5757 [data-quote-request-modal] .text-gray-400 { 5758 color: #9ca3af !important; 5759 } 5760 [data-quote-request-modal] .text-emerald-600 { 5761 color: #059669 !important; 5762 } 5763 [data-quote-request-modal] .text-red-500 { 5764 color: #ef4444 !important; 5765 } 5766 /* Keep submit button text white */ 5767 [data-quote-request-modal] .qr-submit span { 5768 color: #fff !important; 5769 } 5770 5771 /* Modal title letter spacing */ 5772 [data-quote-request-modal] h2 { 5773 letter-spacing: 0px !important; 5774 } 5775 5776 /* All labels should be black per Figma */ 5777 [data-quote-request-modal] label { 5778 color: black !important; 5779 } 5780 5781 /* Placeholder text should be grey, not blue */ 5782 [data-quote-request-modal] textarea::placeholder, 5783 [data-quote-request-modal] input::placeholder { 5784 color: #9ca3af !important; 5785 } 5786</style> 5787 5788<data-island 5789 x-data="QuoteRequestForm" 5790 on="idle" 5791 x-cloakdata-webhook-url="https://print-room-chatbot-api.vercel.app/api/quote-request" 5792 data-turnstile-site-key="0x4AAAAAAETPnb_3iHel2J69" 5793> 5794 <template x-teleport="#modal-slot"> 5795 <div 5796 x-show="$store.modals.modal.contents === 'quoteRequest'" 5797 class="flex w-full flex-col h-full" 5798 style="background: #FBFBF6;" 5799 data-quote-request-modal 5800 ><div class="shrink-0 px-5 py-4 sm:px-8 sm:py-5"> 5801 <div class="flex items-center justify-between"> 5802 <h2 x-show="!successMessage" class="font-bold" style="font-size: 2.75rem; letter-spacing: 0px; color: black;">Project quote request</h2> 5803 <div x-show="successMessage" class="flex-1"></div> 5804 <button 5805 @click.prevent="$store.modals.close('quoteRequest')" 5806 type="button" 5807 class="rounded-full p-2 text-gray-400 transition hover:text-gray-600" 5808 > 5809 <span class="sr-only">Close</span> 5810 <svg width="20" height="20" fill="none" viewBox="0 0 24 24">
5810<path stroke="currentColor" stroke-width="2" d="m6 6 12 12m0-12-12 12"/></svg> 5811 </button> 5812 </div> 5813 </div><div class="overflow-y-auto flex-1 px-5 py-5 sm:px-8 sm:py-6"> 5814 <div class="mx-auto max-w-2xl"> 5815 <template x-if="!successMessage"> 5816 <form @submit.prevent="submitQuote" class="space-y-8"><section style="padding-bottom: 2rem;"> 5817 <h3 class="text-sm font-normal" style="color: black;" x-text="'Selected products (' + ($store.chatQuote.active ? $store.chatQuote.count : $store.favorites.count) + ')'">Selected products</h3><template x-if="$store.chatQuote.active && $store.chatQuote.count > 0"> 5818 <div class="mt-3"> 5819 <template x-for="item in $store.chatQuote.items" :key="item.id"> 5820 <div class="qr-product-row flex items-start gap-3"> 5821 <div class="shrink-0 overflow-hidden rounded-lg bg-gray-100" style="width: 53px; height: 53px;"> 5822 <template x-if="item.image"> 5823 <img :src="item.image" :alt="item.title" class="h-full w-full object-cover" width="53" height="53"> 5824 </template> 5825 </div> 5826 <div class="min-w-0 flex-1"> 5827 <p class="text-sm font-semibold text-gray-900" x-text="item.title"></p> 5828 <div class="mt-2 flex flex-wrap gap-2"> 5829 <span x-show="item.quantity" class="qr-pill" x-text="'Qty ' + item.quantity"></span> 5830 <span x-show="item.colors && item.colors.length > 0" class="qr-pill" x-text="item.colors.join(', ')"></span> 5831 <span x-show="item.sizes && item.sizes.length > 0" class="qr-pill" x-text="item.sizes.join(', ')"></span> 5832 <span x-show="item.decorationMethod" class="qr-pill" x-text="item.decorationMethod"></span> 5833 </div> 5834 </div> 5835 </div> 5836 </template> 5837 </div> 5838 </template><template x-if="!$store.chatQuote.active && $store.favorites.count > 0"> 5839 <div class="mt-3" x-data="{ openPill: null }" 5840 @click.document="if (openPill && !$event.target.closest('.qr-pill') && !$event.target.closest('.qr-popover')) openPill = null"> 5841 <template x-for="item in $store.favorites.items" :key="item.key"> 5842 <div class="qr-product-row flex items-center gap-3 flex-wrap sm:flex-nowrap" x-init="if(item.handle === 'mystery-product') { $nextTick(() => openPill = item.key + '-notes') }"> 5843 <template x-if="item.handle === 'mystery-product'"> 5844 <div class="shrink-0 flex items-center justify-center" style="width: 53px; height: 53px;"> 5845 <span style="width: 33px; height: 33px; color: black;"><span class="h-full w-full fill-current"> 5846 <svg 5847 aria-hidden="true" 5848 focusable="false" 5849 role="presentation" 5850 class="icon icon-product-question-mark" 5851 viewBox="0 0 24 24" 5852 > 5853 <path d="M12 1c6.075 0 11 4.925 11 11s-4.925 11-11 11S1 18.075 1 12 5.925 1 12 1Zm0 1.375a9.625 9.625 0 1 0 0 19.25 9.625 9.625 0 0 0 0-19.25Zm0 13.75.112.006a1.031 1.031 0 1 1-.224 0l.112-.006Zm3.35-7.646a3.437 3.437 0 0 1-2.204 4.012.688.688 0 0 0-.452.553l-.007.096v.922a.687.687 0 0 1-1.368.094l-.007-.094v-.921c0-.823.488-1.562 1.233-1.89l.143-.056a2.062 2.062 0 1 0-2.745-2.094l-.006.15a.688.688 0 1 1-1.374-.001 3.438 3.438 0 0 1 6.787-.771Z"></path> 5854 </svg> 5855</span> 5856</span> 5857 </div> 5858 </template> 5859 <template x-if="item.handle !== 'mystery-product'"> 5860 <div class="shrink-0 overflow-hidden rounded-lg bg-gray-100" style="width: 53px; height: 53px;"> 5861 <img :src="item.image" :alt="item.title" class="h-full w-full object-cover" width="53" height="53"> 5862 </div> 5863 </template> 5864 <div class="min-w-0" style="width: 5rem; flex: 0 0 5rem;"> 5865 <p style="font-size: 10px; font-weight: 300; line-height: 11px; color: black;" x-text="item.vendor || ''"></p> 5866 <p class="truncate" style="font-size: 10px; font-weight: 600; line-height: 11px; color: black;" x-text="item.title"></p> 5867 </div><div class="qr-pills-row flex-1" style="margin-left: 1rem; gap: 0.75rem; align-items: center;"> 5868 <div class="relative" x-show="item.hasColours"> 5869 <button type="button" class="qr-pill" :class="{ 'qr-pill--active': openPill === item.key + '-colour' }" 5870 @click="openPill = openPill === item.key + '-colour' ? null : item.key + '-colour'; if (openPill) $store.favorites.loadColourChoices(item.key)">
5871 <span x-text="item.colour || 'Colour TBC'"></span> 5872 <svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg> 5873 </button> 5874 <div x-show="openPill === item.key + '-colour'" x-transition class="qr-popover" style="min-width: 10rem; max-height: 15rem; overflow-y: auto;"> 5875 <button 5876 type="button" 5877 data-quote-colour-tbc 5878 class="block w-full text-left text-sm py-1" 5879 :disabled="!$store.favorites.canSelectTbc(item)" 5880 :class="!$store.favorites.canSelectTbc(item) ? 'opacity-40 cursor-not-allowed' : ''" 5881 @click="if ($store.favorites.rekey(item.key, { variantId: null, colour: null })) openPill = null" 5882 >TBC (decide later)</button> 5883 <p class="text-xs text-gray-600" x-show="!($store.favorites.colourChoicesByHandle[item.handle] || []).length">We'll confirm colour with you</p> 5884 <template x-for="choice in ($store.favorites.colourChoicesByHandle[item.handle] || [])" :key="choice.variantId"> 5885 <button type="button" class="block w-full text-left text-sm py-1" x-text="choice.label" 5886 :disabled="$store.favorites.colourChoiceTaken(item, choice)" 5887 :class="$store.favorites.colourChoiceTaken(item, choice) ? 'opacity-40 cursor-not-allowed' : ''" 5888 @click="if ($store.favorites.rekey(item.key, choice)) openPill = null"></button> 5889 </template> 5890 </div> 5891 </div><div class="relative"> 5892 <button type="button" class="qr-pill" :class="{ 'qr-pill--active': openPill === item.key + '-qty' }" @click="openPill = openPill === item.key + '-qty' ? null : item.key + '-qty'"> 5893 <span x-text="'Quantity' + (item.quantity ? ' ' + (item.quantity >= 1000 ? '1000+' : item.quantity) : '')"></span> 5894 <svg class="h-3 w-3 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/></svg> 5895 </button> 5896 <div x-show="openPill === item.key + '-qty'" x-transition class="qr-popover" style="min-width: 8rem; padding: 0.5rem 0.75rem;"> 5897 <div class="flex items-baseline gap-2"> 5898 <span class="text-sm font-normal text-gray-900" x-text="item.quantity || item.moq || 24"></span> 5899 <span class="text-xs font-light text-gray-500">units</span> 5900 </div> 5901 <input x-show="item.sizeSplit === null" 5902 type="range" 5903 min="1" 5904 max="1000" 5905 step="1" 5906 class="qr-slider" 5907 style="height: 18px; margin-top: 2px;" 5908 :value="item.quantity || item.moq || 24" 5909 @input="$store.favorites.updateItemMeta(item.key, 'quantity', parseInt($event.target.value, 10))" 5910 :style="'--slider-track: linear-gradient(to right, #658a6a ' + ((item.quantity - 1) / 999 * 100) + '%, #e5e7eb ' + ((item.quantity - 1) / 999 * 100) + '%)'" 5911 > 5912 <label x-show="item.sizeOptions && item.sizeOptions.length" class="mt-2 flex items-center gap-2 text-xs"> 5913 <input type="checkbox" :checked="item.sizeSplit !== null" @change="$store.favorites.setSizeSplit(item.key, $event.target.checked ? {} : null)"> 5914 Split by size (optional) 5915 </label> 5916 <div x-show="item.sizeSplit !== null && item.sizeOptions && item.sizeOptions.length" class="mt-2 space-y-1"> 5917 <template x-for="size in item.sizeOptions" :key="size"> 5918 <label class="flex items-center gap-2 text-xs">
5919 <span x-text="size" class="w-10"></span> 5920 <input type="number" min="0" max="100000" step="1" class="w-20 border rounded px-1" 5921 :value="(item.sizeSplit || {})[size] || 0" 5922 @input="$store.favorites.setSizeSplit(item.key, { ...(item.sizeSplit || {}), [size]: parseInt($event.target.value, 10) || 0 })"> 5923 </label> 5924 </template> 5925 </div> 5926 </div> 5927 </div><div class="relative"> 5928 <button type="button" class="qr-pill" :class="{ 'qr-pill--active': openPill === item.key + '-artwork' || (item.artworks && item.artworks.length > 0) || item.artworkLink }" @click="openPill = openPill === item.key + '-artwork' ? null : item.key + '-artwork'"> 5929 <template x-if="item.artworks && item.artworks.length > 0"> 5930 <span class="flex items-center gap-1"> 5931 <svg class="h-3 w-3 shrink-0" style="color: #658a6a;" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg> 5932 <span x-text="item.artworks.length === 1 ? '1 file' : item.artworks.length + ' files'"></span> 5933 </span> 5934 </template> 5935 <template x-if="item.artworkLink && !(item.artworks && item.artworks.length > 0)"> 5936 <span class="flex items-center gap-1"> 5937 <svg class="h-3 w-3 shrink-0" style="color: #658a6a;" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/></svg> 5938 <span>Artwork linked</span> 5939 </span> 5940 </template> 5941 <template x-if="!(item.artworks && item.artworks.length > 0) && !item.artworkLink"> 5942 <span x-text="'Upload artwork \u2191'"></span> 5943 </template> 5944 </button> 5945 <div x-show="openPill === item.key + '-artwork'" x-transition class="qr-popover" style="min-width: 14rem;"> 5946 <p class="mb-2 text-xs text-gray-500">Max <strong>5 files</strong>, <strong>10MB</strong> each</p><template x-if="item.artworks && item.artworks.length > 0"> 5947 <div class="mb-2 space-y-3"> 5948 <template x-for="(aw, awIdx) in item.artworks" :key="aw.fileName + awIdx"> 5949 <div class="text-xs"> 5950 <div class="flex items-center gap-1.5"> 5951 <template x-if="aw.status === 'uploading'"> 5952 <svg class="h-3 w-3 shrink-0 animate-spin text-gray-400" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/></svg> 5953 </template> 5954 <template x-if="aw.status === 'done'"> 5955 <svg class="h-3 w-3 shrink-0 text-emerald-500" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/></svg> 5956 </template> 5957 <template x-if="aw.status === 'error'"> 5958 <svg class="h-3 w-3 shrink-0 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5958<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg> 5959 </template> 5960 <span class="flex-1 truncate" :class="aw.status === 'error' ? 'text-red-600' : 'text-gray-700'" x-text="aw.fileName"></span> 5961 <span class="shrink-0 text-gray-400" style="font-size: 10px;" x-text="aw.fileSize ? (aw.fileSize / 1024 < 1024 ? Math.round(aw.fileSize / 1024) + 'KB' : (aw.fileSize / (1024*1024)).toFixed(1) + 'MB') : ''"></span> 5962 <template x-if="aw.status === 'error'"> 5963 <button type="button" class="shrink-0 text-blue-600 underline" @click="retryArtworkUpload(item.key, awIdx)">Retry</button> 5964 </template> 5965 <button type="button" class="shrink-0 text-red-400 hover:text-red-600" @click="removeArtwork(item.key, awIdx)" title="Remove file"> 5966 <svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg> 5967 </button> 5968 </div><template x-if="aw.status === 'done'"> 5969 <div class="relative" style="margin-top: 3px; margin-left: 18px;" x-data="{ placementOpen: false }"> 5970 <button 5971 type="button" 5972 @click="placementOpen = !placementOpen" 5973 class="flex w-full items-center justify-between" 5974 style="height: 20px; padding: 0 8px; font-size: 10px; border: 0.666px solid black; border-radius: 9999px; background: #eee; cursor: pointer;" 5975 > 5976 <span x-text="aw.placement || 'Placementâ¦'" :style="aw.placement ? 'color: black' : 'color: #9ca3af'"></span> 5977 <svg :style="placementOpen ? 'transform: rotate(180deg)' : ''" width="6" height="4" viewBox="0 0 6 4" fill="none" style="margin-left: 4px; flex-shrink: 0; transition: transform 0.15s;"> 5978 <path d="M0.5 0.5L3 3L5.5 0.5" stroke="black" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"/> 5979 </svg> 5980 </button> 5981 <div 5982 x-show="placementOpen" 5983 x-transition 5984 @click.outside="placementOpen = false" 5985 style="position: absolute; top: calc(100% + 3px); left: 0; z-index: 60; background: white; border: 0.666px solid black; border-radius: 10px; padding: 0.35rem 0; min-width: 110px; box-shadow: 0 3px 7px 0 rgba(0,0,0,0.15);" 5986 > 5987 <template x-for="pl in ['Front','Left Chest','Right Chest','Back','Sleeve','Other']" :key="pl"> 5988 <button 5989 type="button" 5990 class="block w-full text-left" 5991 style="padding: 0.2rem 0.65rem; font-size: 10px; line-height: 13px; color: #4b5563; cursor: pointer; background: none; border: none;" 5992 @click="updateArtworkPlacement(item.key, awIdx, pl); placementOpen = false" 5993 @mouseover="$el.style.background = '#f3f4f6'" 5994 @mouseout="$el.style.background = 'none'" 5995 x-text="pl" 5996 ></button> 5997 </template> 5998 </div> 5999 </div> 6000 </template> 6001 </div> 6002 </template> 6003 </div> 6004 </template><template x-if="!item.artworks || item.artworks.length < 5"> 6005 <label class="flex cursor-pointer items-center justify-center gap-2 rounded-xl border border-dashed border-gray-300 px-4 py-2.5 text-sm text-gray-600 transition hover:border-gray-400"> 6006 <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6006<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2M7 10l5-5m0 0l5 5m-5-5v12"/></svg> 6007 <span x-text="item.artworks && item.artworks.length > 0 ? 'Add more files' : 'Select files'"></span> 6008 <input 6009 type="file" 6010 class="hidden" 6011 multiple 6012 accept=".png,.jpg,.jpeg,.svg,.pdf,.ai,.eps" 6013 @change="handlePerProductFileUpload($event, item.key)" 6014 > 6015 </label> 6016 </template><div style="margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid #e5e7eb;"> 6017 <p class="text-xs text-gray-500">For <strong>larger files</strong>: via shared link</p> 6018 <input 6019 type="url" 6020 class="qr-input text-sm" 6021 style="margin-top: 0.5rem; font-size: 0.75rem;" 6022 placeholder="Link address" 6023 :value="item.artworkLink || ''" 6024 @input="$store.favorites.updateItemMeta(item.key, 'artworkLink', $event.target.value)" 6025 > 6026 <p class="mt-1 text-gray-400" style="font-size: 9px;">Eg. Google drive, Dropbox</p> 6027 </div> 6028 </div> 6029 </div><div class="relative"> 6030 <button type="button" class="qr-pill" :class="{ 'qr-pill--active': openPill === item.key + '-notes' || (item.notes && item.notes.length > 0), 'qr-pill--required': item.handle === 'mystery-product' && (!item.notes || !item.notes.trim()) }" @click="openPill = openPill === item.key + '-notes' ? null : item.key + '-notes'"> 6031 <span class="qr-pill-notes-text" x-text="item.notes && item.notes.length > 0 ? 'Notes added' : 'Notes\u2026'"></span> 6032 <template x-if="item.handle === 'mystery-product'"><span style="color: #dc2626; margin-left: 2px;">*</span></template> 6033 </button> 6034 <div x-show="openPill === item.key + '-notes'" x-transition class="qr-popover" style="left: auto; right: 0;"> 6035 <label class="mb-1.5 block text-xs font-medium text-gray-500">Notes</label> 6036 <textarea 6037 rows="3" 6038 class="qr-textarea text-sm" 6039 :placeholder="item.handle === 'mystery-product' ? 'Include the brand, product name or SKU you require' : 'Tell us how and where you would like your artwork printed.'" 6040 :value="item.notes || ''" 6041 @input="$store.favorites.updateItemMeta(item.key, 'notes', $event.target.value)" 6042 ></textarea> 6043 </div> 6044 </div> 6045 </div> 6046 </div> 6047 </template> 6048 <template x-for="shortfall in $store.favorites.moqShortfalls()" :key="shortfall.id"> 6049 <p class="mt-2 text-xs text-red-600" role="alert" x-text="shortfall.title + ' total ' + shortfall.total + ' â minimum ' + shortfall.moq"></p> 6050 </template> 6051 </div> 6052 </template><template x-if="!$store.chatQuote.active && $store.favorites.count === 0"> 6053 <p class="mt-3 text-sm text-gray-400">No products added yet. Browse products and add items to your quote.</p> 6054 </template> 6055 </section><section style="padding-bottom: 2rem;"> 6056 <div style="border: 0.75px solid black; border-radius: 10px; padding: 0.65rem 1.25rem;"> 6057 <p style="font-size: 11px; color: black; margin-bottom: 2px;">Additional notes:</p> 6058 <textarea 6059 id="project-description" 6060 x-model="formData.description" 6061 rows="2" 6062 placeholder="Is there anything else we might need to know about your project?" 6063 style="width: 100%; border: none; padding: 0; background: transparent; font-size: 11.5px; color: #111827; resize: vertical; outline: none;" 6064 ></textarea> 6065 </div> 6066 </section><section style="padding-bottom: 2rem;"> 6067 <label class="text-sm" style="color: black;">Your budget</label> 6068 <div class="flex items-center justify-between" style="margin-top: 0.25rem;">
6069 <span class="text-xs text-gray-400">$500</span> 6070 <span style="font-size: 1.95rem; font-weight: 400; line-height: 1; color: #658a6a;" x-text="'$' + Number(formData.budget).toLocaleString()"></span> 6071 <span class="text-xs text-gray-400">$10,000+</span> 6072 </div> 6073 <div @mousedown.stop @touchstart.stop> 6074 <input 6075 type="range" 6076 x-model.number="formData.budget" 6077 @input="formData.budget = parseInt($event.target.value, 10)" 6078 @click.stop 6079 min="500" 6080 max="10000" 6081 step="500" 6082 class="qr-slider" 6083 :style="'--slider-track: linear-gradient(to right, #658a6a ' + ((formData.budget - 500) / 9500 * 100) + '%, #e5e7eb ' + ((formData.budget - 500) / 9500 * 100) + '%)'" 6084 > 6085 </div> 6086 </section><section class="grid grid-cols-1 gap-4 sm:grid-cols-2"> 6087 <div> 6088 <label for="in-hand-date" class="mb-1.5 block text-sm">The date I need my merch*</label> 6089 <input 6090 type="date" 6091 id="in-hand-date" 6092 x-model="formData.inHandDate" 6093 required 6094 class="qr-input text-sm" 6095 :min="(() => { let d = new Date(), a = 0; while (a < 7) { d.setDate(d.getDate() + 1); if (d.getDay() !== 0 && d.getDay() !== 6) a++; } return d.toISOString().split('T')[0]; })()" 6096 > 6097 </div> 6098 <div x-data="{ locationOpen: false }"> 6099 <label class="mb-1.5 block text-sm" style="color: black;">I need it sent to*</label> 6100 <div class="relative"><select x-model="formData.location" required class="sr-only" tabindex="-1" aria-hidden="true"> 6101 <option value="">Select location</option> 6102 <optgroup label="New Zealand"> 6103 <option value="Northland">Northland</option> 6104 <option value="Auckland">Auckland</option> 6105 <option value="Waikato">Waikato</option> 6106 <option value="Bay of Plenty">Bay of Plenty</option> 6107 <option value="Gisborne">Gisborne</option> 6108 <option value="Hawke's Bay">Hawke's Bay</option> 6109 <option value="Taranaki">Taranaki</option> 6110 <option value="ManawatÅ«-Whanganui">Manawatū-Whanganui</option> 6111 <option value="Wellington">Wellington</option> 6112 <option value="Tasman">Tasman</option> 6113 <option value="Nelson">Nelson</option> 6114 <option value="Marlborough">Marlborough</option> 6115 <option value="West Coast">West Coast</option> 6116 <option value="Canterbury">Canterbury</option> 6117 <option value="Otago">Otago</option> 6118 <option value="Southland">Southland</option> 6119 </optgroup> 6120 <optgroup label="Australia"> 6121 <option value="New South Wales">New South Wales</option> 6122 <option value="Victoria">Victoria</option> 6123 <option value="Queensland">Queensland</option> 6124 <option value="Western Australia">Western Australia</option> 6125 <option value="South Australia">South Australia</option> 6126 <option value="Tasmania">Tasmania</option> 6127 <option value="Australian Capital Territory">Australian Capital Territory</option> 6128 <option value="Northern Territory">Northern Territory</option> 6129 </optgroup> 6130 <option value="International">International</option> 6131 </select><button 6132 type="button" 6133 @click="locationOpen = !locationOpen" 6134 class="qr-select flex w-full items-center justify-between text-sm" 6135 style="cursor: pointer;" 6136 >
6137 <span x-text="formData.location || 'Select location'" :style="formData.location ? 'color: black' : 'color: #9ca3af'"></span> 6138 <svg class="h-4 w-4 shrink-0 transition-transform" :style="locationOpen ? 'transform: rotate(180deg)' : ''" fill="none" stroke="currentColor" viewBox="0 0 24 24" style="color: black;"> 6139 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path> 6140 </svg> 6141 </button><div 6142 x-show="locationOpen" 6143 x-transition 6144 @click.outside="locationOpen = false" 6145 style="position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 50; background: white; border: 0.666px solid black; border-radius: 15.5px; max-height: 232px; overflow-y: auto; padding: 0.75rem 0;" 6146 > 6147 <template x-for="loc in ['Northland','Auckland','Waikato','Bay of Plenty','Gisborne','Hawke\'s Bay','Taranaki','Manawat\u016b-Whanganui','Wellington','Tasman','Nelson','Marlborough','West Coast','Canterbury','Otago','Southland','New South Wales','Victoria','Queensland','Western Australia','South Australia','Tasmania','Australian Capital Territory','Northern Territory','International']" :key="loc"> 6148 <button 6149 type="button" 6150 class="block w-full text-left" 6151 style="padding: 0.25rem 1rem; font-size: 12.65px; line-height: 13.313px; color: #4b5563; cursor: pointer; background: none; border: none;" 6152 @click="formData.location = loc; locationOpen = false" 6153 @mouseover="$el.style.background = '#f3f4f6'" 6154 @mouseout="$el.style.background = 'none'" 6155 x-text="loc" 6156 ></button> 6157 </template> 6158 </div> 6159 </div> 6160 </div> 6161 <div> 6162 <label for="contact-name" class="mb-1.5 block text-sm">Your name*</label> 6163 <input 6164 type="text" 6165 id="contact-name" 6166 x-model="formData.name" 6167 required 6168 placeholder="Your name here" 6169 class="qr-input text-sm" 6170 > 6171 </div> 6172 <div> 6173 <label for="contact-email" class="mb-1.5 block text-sm">Email*</label> 6174 <input 6175 type="email" 6176 id="contact-email" 6177 x-model="formData.email" 6178 required 6179 placeholder="[email protected]" 6180 class="qr-input text-sm" 6181 > 6182 </div> 6183 <div> 6184 <label for="contact-phone" class="mb-1.5 block text-sm">Phone*</label> 6185 <input 6186 type="tel" 6187 id="contact-phone" 6188 x-model="formData.phone" 6189 required 6190 placeholder="Your phone number" 6191 class="qr-input text-sm" 6192 > 6193 </div> 6194 <div> 6195 <label for="contact-company" class="mb-1.5 block text-sm">Company</label> 6196 <input 6197 type="text" 6198 id="contact-company" 6199 x-model="formData.company" 6200 placeholder="Your company's name" 6201 class="qr-input text-sm" 6202 > 6203 </div> 6204 <div x-data="{ heardAboutOpen: false }" class="sm:col-span-2"><label id="heard-about-label" class="mb-1.5 block text-sm" style="color: black;">How did you hear about us?*</label> 6205 <div class="relative"><select x-model="formData.heardAbout" required class="sr-only" tabindex="-1" aria-hidden="true"> 6206 <option value="">Select an option</option><option value="Google search">Google search</option><option value="Social media">Social media</option><option value="Referral or word of mouth">Referral or word of mouth</option><option value="Repeat customer">Repeat customer</option><option value="Saw our work in the wild">Saw our work in the wild</option><option value="Email or newsletter">Email or newsletter</option><option value="Event or trade show">Event or trade show</option><option value="Other">Other</option><option value="Prefer not to say">Prefer not to say</option></select><button 6207 type="button" 6208 @click="heardAboutOpen = !heardAboutOpen" 6209 :aria-expanded="heardAboutOpen" 6210 aria-labelledby="heard-about-label" 6211 class="qr-select flex w-full items-center justify-between text-sm" 6212 style="cursor: pointer;" 6213 >
6214 <span x-text="formData.heardAbout || 'Select an option'" :style="formData.heardAbout ? 'color: black' : 'color: #9ca3af'"></span> 6215 <svg class="h-4 w-4 shrink-0 transition-transform" :style="heardAboutOpen ? 'transform: rotate(180deg)' : ''" fill="none" stroke="currentColor" viewBox="0 0 24 24" style="color: black;"> 6216 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path> 6217 </svg> 6218 </button><div 6219 x-show="heardAboutOpen" 6220 x-transition 6221 @click.outside="heardAboutOpen = false" 6222 style="position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 50; background: white; border: 0.666px solid black; border-radius: 15.5px; max-height: 232px; overflow-y: auto; padding: 0.75rem 0;" 6223 > 6224 <template x-for='opt in ["Google search","Social media","Referral or word of mouth","Repeat customer","Saw our work in the wild","Email or newsletter","Event or trade show","Other","Prefer not to say"]' :key="opt"> 6225 <button 6226 type="button" 6227 class="block w-full text-left" 6228 style="padding: 0.25rem 1rem; font-size: 12.65px; line-height: 13.313px; color: #4b5563; cursor: pointer; background: none; border: none;" 6229 @click="selectHeardAbout(opt); heardAboutOpen = false" 6230 @mouseover="$el.style.background = '#f3f4f6'" 6231 @mouseout="$el.style.background = 'none'" 6232 x-text="opt" 6233 ></button> 6234 </template> 6235 </div> 6236 </div><p x-show="formData.heardAbout === 'Social media'" x-transition class="mt-1.5 text-xs" style="color: #6b7280;"> 6237 Instagram, Facebook, TikTok or LinkedIn 6238 </p><div 6239 x-show="formData.heardAbout === 'Referral or word of mouth' || formData.heardAbout === 'Other'" 6240 x-transition 6241 class="mt-3" 6242 > 6243 <label for="contact-heard-detail" class="mb-1.5 block text-sm" x-text="formData.heardAbout === 'Other' ? 'Tell us more*' : 'Who referred you? (optional)'"></label> 6244 <input 6245 type="text" 6246 id="contact-heard-detail" 6247 x-model="formData.heardAboutDetail" 6248 :required="formData.heardAbout === 'Other'" 6249 :placeholder="formData.heardAbout === 'Other' ? 'How you found us' : 'Their name or company'" 6250 class="qr-input text-sm" 6251 > 6252 </div> 6253 </div> 6254 </section><template x-if="errorMessage"> 6255 <div class="rounded-2xl px-4 py-3 text-center" style="border: 1px solid #e5e7eb; background: #FFFBEB;"> 6256 <p class="text-sm" style="color: #92400e;"> 6257 <span style="font-size: 1.25rem; vertical-align: middle; margin-right: 0.25rem;">🙂</span> 6258 <span x-text="errorMessage"></span> 6259 </p> 6260 </div> 6261 </template><button 6262 type="submit" 6263 class="qr-submit" 6264 style="margin-top: 2.5rem;" 6265 :disabled="submitting || ($store.favorites.count === 0 && !$store.chatQuote.active) || (!$store.chatQuote.active && $store.favorites.moqShortfalls().length > 0)" 6266 > 6267 <span x-show="!submitting">Submit quote request</span> 6268 <span x-show="submitting" class="flex items-center justify-center gap-2"> 6269 <svg class="h-4 w-4 animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> 6270 <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> 6271 <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> 6272 </svg> 6273 Sending... 6274 </span> 6275 </button> 6276 </form> 6277 </template><template x-if="successMessage"> 6278 <div class="flex flex-col items-center justify-center text-center" style="padding: 3rem 1.5rem 4rem;"><img src="//printroom.co/cdn/shop/t/59/assets/success-thumbs-up.svg?v=51729750037822013731787098435" alt="Success" width="141" height="179" style="width: 141px; height: 179px;"> 6279 6280 <h3 style="margin-top: 1.5rem; font-size: clamp(48px, 12vw, 80px); font-weight: 300; line-height: 1; color: black;">Success</h3> 6281 6282 <div style="margin-top: 3rem; max-width: 414px; font-size: clamp(18px, 4vw, 25px); line-height: 1.16; color: black; text-align: center;"> 6283 <p style="margin: 0;">Nice! Your quote request has successfully been submitted. 6284 Our team will try and have a quote back to you within 1 working day.</p> 6285 <p style="margin: 1.5rem 0 0;">In the meantime, a confirmation email has been sent to you.</p> 6286 </div> 6287 6288 <a 6289 href="/collections/product-library" 6290 @click="$store.modals.close('quoteRequest'); successMessage = ''" 6291 class="flex items-center justify-center" 6292 style="margin-top: 2.5rem; width: min(300px, 80vw); max-width: 100%; height: 64px; border: 2.7px solid #4B4D72; border-radius: 40px; font-size: clamp(18px, 5vw, 25px); font-weight: 400; color: #4B4D72; letter-spacing: -1.24px; text-decoration: none; transition: background-color 0.2s ease, color 0.2s ease;" 6293 onmouseover="this.style.backgroundColor='#4B4D72';this.style.color='#fff'" 6294 onmouseout="this.style.backgroundColor='transparent';this.style.color='#4B4D72'" 6295 > 6296 Browse more products 6297 </a> 6298 </div> 6299 </template> 6300 </div> 6301 </div> 6302 </div> 6303 </template> 6304</data-island> 6305 6306 6307 6308 6309 6310 6311 6312 <style> 6313 .cwp-overlay { 6314 position: fixed; 6315 top: var(--header-group-height, 119px); 6316 left: 0; 6317 right: 0; 6318 bottom: 0; 6319 z-index: 999; 6320 display: flex; 6321 align-items: center; 6322 justify-content: center; 6323 backdrop-filter: blur(6px); 6324 -webkit-backdrop-filter: blur(6px); 6325 background: rgba(247, 247, 247, 0.6); 6326 opacity: 0; 6327 transition: opacity 0.3s ease; 6328 } 6329 6330 .cwp-card { 6331 position: relative; 6332 width: 100%; 6333 max-width: 598px; 6334 margin: 1rem; 6335 background: #FBFBF6; 6336 border: 1.565px solid black; 6337 border-radius: 23px; 6338 box-shadow: 0 3.5px 11.5px 1.75px rgba(0, 0, 0, 0.1); 6339 padding: 2.5rem 3rem 2.5rem; 6340 overflow: visible; 6341 } 6342 6343 .cwp-close { 6344 position: absolute; 6345 top: 1.25rem; 6346 right: 1.25rem; 6347 background: none; 6348 border: none; 6349 cursor: pointer; 6350 padding: 0.5rem; 6351 color: black; 6352 } 6353 6354 .cwp-title { 6355 font-size: 70px; 6356 font-weight: 300; 6357 line-height: 1; 6358 color: black; 6359 margin: 0 0 1.5rem; 6360 } 6361 6362 .cwp-body { 6363 font-size: 19px; 6364 line-height: 22px; 6365 color: black; 6366 margin: 0 0 1rem; 6367 } 6368 6369 .cwp-body + .cwp-body { 6370 margin-top: 1rem; 6371 } 6372 6373 .cwp-btn { 6374 display: inline-flex; 6375 align-items: center; 6376 justify-content: center; 6377 margin-top: 1.25rem; 6378 height: 37px; 6379 padding: 0 1.5rem; 6380 background: white; 6381 border: 0.722px solid black; 6382 border-radius: 29px; 6383 font-size: 21.67px; 6384 font-weight: 400; 6385 color: black; 6386 cursor: pointer; 6387 transition: background 0.2s ease; 6388 } 6389 6390 .cwp-btn:hover { 6391 background: #f0f0f0; 6392 } 6393 6394 .cwp-pointer-left { 6395 position: fixed; 6396 left: 240px; 6397 top: 50%; 6398 transform: translateY(-50%) rotate(-15deg); 6399 width: 240px; 6400 opacity: 0; 6401 transition: opacity 0.6s ease; 6402 pointer-events: none; 6403 z-index: 1000; 6404 } 6405 .cwp-pointer-left.visible { 6406 opacity: 1; 6407 animation: cwp-bob-left 1.8s ease-in-out infinite; 6408 } 6409 6410 .cwp-pointer-up { 6411 position: fixed; 6412 top: calc(var(--header-group-height, 119px) - 60px); 6413 right: 60px; 6414 width: 180px; 6415 opacity: 0; 6416 transition: opacity 0.6s ease; 6417 pointer-events: none; 6418 z-index: 1000; 6419 } 6420 .cwp-pointer-up.visible { 6421 opacity: 1; 6422 animation: cwp-bob-up 1.8s ease-in-out infinite; 6423 } 6424 6425 @keyframes cwp-bob-left { 6426 0%, 100% { transform: translateY(-50%) rotate(-15deg) translateX(0); } 6427 50% { transform: translateY(-50%) rotate(-15deg) translateX(-10px); } 6428 } 6429 6430 @keyframes cwp-bob-up { 6431 0%, 100% { transform: translateY(0); } 6432 50% { transform: translateY(-10px); } 6433 } 6434 6435 @media (max-width: 639px) { 6436 .cwp-card { 6437 padding: 2rem 1.5rem; 6438 } 6439 6440 .cwp-title { 6441 font-size: 48px; 6442 } 6443 6444 .cwp-body { 6445 font-size: 16px; 6446 line-height: 20px; 6447 } 6448 6449 .cwp-btn { 6450 font-size: 18px; 6451 } 6452 6453 .cwp-pointer-left, 6454 .cwp-pointer-up { 6455 display: none; 6456 } 6457 } 6458</style> 6459 6460 6461 <style>
6462 /* ââ "Can't find something?" scroll-triggered tab ââ */ 6463 .cft-container { 6464 position: fixed; 6465 right: 0; 6466 bottom: 100px; 6467 z-index: 998; 6468 display: none; 6469 font-family: 'DM Sans', sans-serif; 6470 } 6471 6472 /* ââ Tab state (collapsed) ââ */ 6473 .cft-tab { 6474 position: relative; 6475 width: 77px; 6476 height: 96px; 6477 cursor: pointer; 6478 opacity: 0; 6479 transform: translateX(20px); 6480 transition: opacity 0.4s ease, transform 0.4s ease; 6481 } 6482 6483 .cft-tab-bg { 6484 position: absolute; 6485 inset: 0; 6486 display: flex; 6487 align-items: center; 6488 justify-content: center; 6489 } 6490 6491 .cft-tab-bg-inner { 6492 width: 96px; 6493 height: 77px; 6494 flex-shrink: 0; 6495 transform: rotate(90deg); 6496 background: var(--cant-find-bg, #EFFE9C); 6497 border-bottom: 1.03px solid black; 6498 border-left: 1.03px solid black; 6499 border-right: 1.03px solid black; 6500 border-top: none; 6501 border-radius: 0 0 16px 16px; 6502 box-shadow: -2.94px 3.13px 5.88px 0px rgba(0, 0, 0, 0.2); 6503 } 6504 6505 .cft-tab-icon { 6506 position: absolute; 6507 top: 5%; 6508 left: 10%; 6509 width: 65%; 6510 height: 50%; 6511 background-size: contain; 6512 background-repeat: no-repeat; 6513 background-position: center; 6514 } 6515 6516 .cft-tab-text { 6517 position: absolute; 6518 bottom: 13%; 6519 left: 0; 6520 right: 0; 6521 font-weight: 600; 6522 font-size: 10px; 6523 line-height: 11.3px; 6524 color: black; 6525 text-align: center; 6526 } 6527 6528 .cft-tab:hover { 6529 transform: translateX(0) scale(1.04); 6530 } 6531 6532 /* ââ Card state (expanded) â ~3Ã original size ââ */ 6533 .cft-card { 6534 position: relative; 6535 width: 300px; 6536 height: 200px; 6537 opacity: 0; 6538 transform: translateX(20px); 6539 transition: opacity 0.4s ease, transform 0.4s ease; 6540 cursor: default; 6541 } 6542 6543 .cft-card-bg { 6544 position: absolute; 6545 inset: 0; 6546 } 6547 6548 .cft-card-bg-inner { 6549 width: 100%; 6550 height: 100%; 6551 background: var(--cant-find-bg, #EFFE9C); 6552 border: 0.75px solid black; 6553 border-right: none; 6554 border-radius: 20px 0 0 20px; 6555 box-shadow: -1.17px 2.34px 2.34px 0px rgba(0, 0, 0, 0.14); 6556 } 6557 6558 .cft-card-content { 6559 position: absolute; 6560 inset: 0; 6561 z-index: 1; 6562 padding: 18px 22px; 6563 } 6564 6565 .cft-card-close { 6566 position: absolute; 6567 top: 8px; 6568 right: 8px; 6569 z-index: 2; 6570 background: none; 6571 border: none; 6572 cursor: pointer; 6573 padding: 4px; 6574 color: black; 6575 opacity: 0.5; 6576 transition: opacity 0.2s; 6577 line-height: 1; 6578 } 6579 6580 .cft-card-close:hover { 6581 opacity: 1; 6582 } 6583 6584 .cft-card-title { 6585 font-weight: 500; 6586 font-size: 18px; 6587 line-height: 20px; 6588 color: black; 6589 margin: 0 0 10px; 6590 } 6591 6592 .cft-card-body { 6593 font-weight: 400; 6594 font-size: 13px; 6595 line-height: 16px; 6596 color: black; 6597 margin: 0; 6598 max-width: 180px; 6599 } 6600 6601 .cft-card-link { 6602 font-weight: 400; 6603 font-size: 22px; 6604 line-height: 24px; 6605 color: black; 6606 text-decoration: underline; 6607 cursor: pointer; 6608 background: none; 6609 border: none; 6610 padding: 0; 6611 font-family: inherit; 6612 position: absolute; 6613 bottom: 18px; 6614 left: 22px; 6615 z-index: 1; 6616 } 6617 6618 .cft-card-link:hover { 6619 opacity: 0.7; 6620 } 6621 6622 .cft-card-doodle { 6623 position: absolute; 6624 bottom: -2px; 6625 right: 2px; 6626 width: 110px; 6627 height: 65px; 6628 transform: rotate(-24.8deg); 6629 pointer-events: none; 6630 z-index: 1; 6631 background-size: contain; 6632 background-repeat: no-repeat; 6633 background-position: center; 6634 } 6635 6636 /* ââ Visible states (applied by JS) ââ */ 6637 .cft-tab.visible, 6638 .cft-card.visible { 6639 opacity: 1; 6640 transform: translateX(0); 6641 } 6642 6643 /* ââ Hide when favorites drawer is open ââ */ 6644 body:has([data-favorites-drawer]:not([style*="display: none"])) .cft-container { 6645 display: none !important; 6646 } 6647 6648 /* ââ Mobile adjustments ââ */ 6649 @media (max-width: 639px) { 6650 .cft-container { 6651 bottom: 80px; 6652 } 6653 6654 .cft-tab { 6655 width: 66px; 6656 height: 82px; 6657 } 6658 6659 .cft-tab-bg-inner { 6660 width: 82px; 6661 height: 66px; 6662 } 6663 6664 .cft-tab-text { 6665 font-size: 9px; 6666 line-height: 10px; 6667 } 6668 6669 .cft-card { 6670 width: 270px; 6671 height: 180px; 6672 } 6673 } 6674</style> 6675 6676 6677 <div id="shopify-section-ai-chatbot" class="shopify-section contents"><link href="//printroom.co/cdn/shop/t/59/assets/ai-chatbot.css?v=112900874753543053291788472410" rel="stylesheet" type="text/css" media="all" /> 6678<data-island 6679 x-data=" 6680 AIChatbot({ 6681 apiEndpoint: "https:\/\/print-room-chatbot-api.vercel.app\/", 6682 questionsApiUrl: "https:\/\/print-room-chatbot-api.vercel.app\/", 6683 welcomeMessage: "Hi! I'm here to help you with your printing needs. How can I assist you today?", 6684 unavailableMessage: "Chat is temporarily unavailable. Please request a quote or contact us directly.", 6685 suggestedPrompts: [] 6686 }) 6687 " 6688 src="ai-chatbot" 6689 on="idle" 6690 id="ai-chatbot-ai-chatbot" 6691 class="ai-chatbot" 6692 data-color-scheme="scheme1" 6693 ><button 6694 @click="toggle()" 6695 class="ai-chatbot__trigger" 6696 :class="{ 'ai-chatbot__trigger--hidden': isOpen }" 6697 aria-label="Chat with us" 6698 type="button" 6699 > 6700 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 6701 <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path> 6702 </svg>
6703 <span>Chat with us</span> 6704 </button><template x-teleport="body"> 6705 <div 6706 x-show="isOpen" 6707 x-transition:enter="ai-chatbot-enter" 6708 x-transition:enter-start="ai-chatbot-enter" 6709 x-transition:enter-end="ai-chatbot-enter-active" 6710 x-transition:leave="ai-chatbot-leave" 6711 x-transition:leave-start="ai-chatbot-leave" 6712 x-transition:leave-end="ai-chatbot-leave-active" 6713 class="ai-chatbot__window" 6714 :class="{ 'ai-chatbot__window--minimized': isMinimized }" 6715 data-color-scheme="scheme1" 6716 role="dialog" 6717 aria-label="Chat with us" 6718 @keydown.escape="close()" 6719 ><div class="ai-chatbot__header"> 6720 <div class="ai-chatbot__header-title"> 6721 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 6722 <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> 6723 </svg> 6724 <span>Chat with us</span> 6725 </div> 6726 <div class="ai-chatbot__header-actions"> 6727 <button 6728 x-show="messages.length > 0 && !isMinimized" 6729 @click="clearHistory()" 6730 class="ai-chatbot__header-btn" 6731 type="button" 6732 :disabled="isLoading" 6733 aria-label="Clear history" 6734 > 6735 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 6736 <polyline points="3 6 5 6 21 6"></polyline> 6737 <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path> 6738 </svg> 6739 </button> 6740 <button 6741 @click="minimize()" 6742 class="ai-chatbot__header-btn" 6743 type="button"
6744 :aria-label="isMinimized ? 'Expand' : 'Minimize'" 6745 > 6746 <template x-if="isMinimized"> 6747 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 6748 <polyline points="15 3 21 3 21 9"></polyline> 6749 <polyline points="9 21 3 21 3 15"></polyline> 6750 <line x1="21" y1="3" x2="14" y2="10"></line> 6751 <line x1="3" y1="21" x2="10" y2="14"></line> 6752 </svg> 6753 </template> 6754 <template x-if="!isMinimized"> 6755 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 6756 <polyline points="4 14 10 14 10 20"></polyline> 6757 <polyline points="20 10 14 10 14 4"></polyline> 6758 <line x1="14" y1="10" x2="21" y2="3"></line> 6759 <line x1="3" y1="21" x2="10" y2="14"></line> 6760 </svg> 6761 </template> 6762 </button> 6763 <button 6764 @click="close()" 6765 class="ai-chatbot__header-btn" 6766 type="button" 6767 aria-label="Close" 6768 > 6769 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 6770 <line x1="18" y1="6" x2="6" y2="18"></line> 6771 <line x1="6" y1="6" x2="18" y2="18"></line> 6772 </svg> 6773 </button> 6774 </div> 6775 </div><div class="ai-chatbot__body" x-show="!isMinimized"><div class="ai-chatbot__messages" x-ref="messagesContainer"><template x-if="messages.length === 0"> 6776 <div class="ai-chatbot__welcome"> 6777 <svg class="ai-chatbot__welcome-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 6778 <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path> 6779 </svg> 6780 <p class="ai-chatbot__welcome-text" x-text="welcomeMessage"></p> 6781 <p class="ai-chatbot__welcome-subtext">Ask me anything about our products and services.</p> 6782 </div> 6783 </template><template x-for="(message, index) in messages" :key="message.id"> 6784 <div 6785 class="ai-chatbot__message-row" 6786 :class="'ai-chatbot__message-row--' + message.role" 6787 ><template x-if="message.role === 'system'"> 6788 <div class="ai-chatbot__message-content ai-chatbot__message-content--system" x-text="message.content"></div> 6789 </template><template x-if="message.role !== 'system'"> 6790 <div class="ai-chatbot__message-stack"><template x-if="message.role === 'staff'"> 6791 <div class="ai-chatbot__staff-meta"> 6792 <span class="ai-chatbot__staff-avatar" x-text="message.initials"></span> 6793 <span class="ai-chatbot__staff-name" x-text="message.senderName"></span> 6794 <span 6795 class="ai-chatbot__staff-time" 6796 x-show="message.timestamp" 6797 x-text="message.timestamp ? new Date(message.timestamp).toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' }) : ''" 6798 ></span> 6799 </div> 6800 </template> 6801 6802 <div 6803 class="ai-chatbot__message-bubble" 6804 :class="'ai-chatbot__message-bubble--' + message.role" 6805 ><div class="ai-chatbot__message-content"><span x-text="message.content"></span><span x-show="message.isStreaming && message.content" class="ai-chatbot__cursor"></span></div><template x-if="message.role === 'assistant' && message.options && message.options.choices.length > 0"> 6806 <div class="ai-chatbot__options" :class="{ 'ai-chatbot__options--submitted': message.optionsSubmitted }"> 6807 <p class="ai-chatbot__options-prompt" x-show="message.options.prompt" x-text="message.options.prompt"></p> 6808 <div class="ai-chatbot__options-list"> 6809 <template x-for="(choice, ci) in message.options.choices" :key="choice.value"> 6810 <button 6811 @click="selectOption(index, choice.value)" 6812 class="ai-chatbot__option-chip" 6813 :class="{ 6814 'ai-chatbot__option-chip--selected': message.selectedOptions.includes(choice.value), 6815 'ai-chatbot__option-chip--disabled': message.optionsSubmitted 6816 }" 6817 :disabled="message.optionsSubmitted" 6818 type="button" 6819 x-text="choice.label" 6820 ></button> 6821 </template> 6822 </div> 6823 <button 6824 x-show="message.options.multiSelect && !message.optionsSubmitted && message.selectedOptions.length > 0" 6825 @click="submitOptions(index)" 6826 class="ai-chatbot__options-submit" 6827 type="button" 6828 > 6829 Continue 6830 </button> 6831 </div> 6832 </template> 6833 </div> 6834 </div> 6835 </template> 6836 </div> 6837 </template><template x-if="isLoading && messages.length > 0 && !messages[messages.length - 1].content"> 6838 <div class="ai-chatbot__message-row ai-chatbot__message-row--assistant"> 6839 <div class="ai-chatbot__message-stack"> 6840 <div class="ai-chatbot__message-bubble ai-chatbot__message-bubble--assistant ai-chatbot__message-bubble--typing"> 6841 <div class="ai-chatbot__typing" aria-label="Assistant is typing">
6842 <span></span> 6843 <span></span> 6844 <span></span> 6845 </div> 6846 </div> 6847 </div> 6848 </div> 6849 </template> 6850 </div><div x-show="error" class="ai-chatbot__error"> 6851 <svg class="ai-chatbot__error-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 6852 <circle cx="12" cy="12" r="10"></circle> 6853 <line x1="12" y1="8" x2="12" y2="12"></line> 6854 <line x1="12" y1="16" x2="12.01" y2="16"></line> 6855 </svg> 6856 <div class="ai-chatbot__error-content"> 6857 <p class="ai-chatbot__error-text" x-text="error"></p> 6858 <div class="ai-chatbot__error-actions"> 6859 <button @click="openQuoteRequest()" class="ai-chatbot__error-action" type="button"> 6860 Request a quote 6861 </button> 6862 <a href="/pages/contact-us" class="ai-chatbot__error-action"> 6863 Contact us 6864 </a> 6865 </div> 6866 <button @click="clearError()" class="ai-chatbot__error-dismiss" type="button"> 6867 Dismiss 6868 </button> 6869 </div> 6870 </div><div x-show="messages.length === 0 && (getActivePrompts().length > 0 || questionsLoading)" class="ai-chatbot__prompts"> 6871 <p class="ai-chatbot__prompts-label">Try asking:</p><template x-if="questionsLoading && getActivePrompts().length === 0"> 6872 <div class="ai-chatbot__prompts-loading"> 6873 <span class="ai-chatbot__prompt-skeleton"></span> 6874 <span class="ai-chatbot__prompt-skeleton"></span> 6875 <span class="ai-chatbot__prompt-skeleton"></span> 6876 </div> 6877 </template><template x-for="(prompt, index) in getActivePrompts()" :key="index"> 6878 <button 6879 @click="useSuggestedPrompt(prompt)" 6880 class="ai-chatbot__prompt-btn" 6881 type="button" 6882 x-text="prompt" 6883 ></button> 6884 </template> 6885 </div><div x-show="ctaButton && ctaButton.show" x-cloak class="ai-chatbot__cta"> 6886 <button 6887 @click="handleCTAClick()" 6888 class="ai-chatbot__cta-btn" 6889 type="button" 6890 x-text="ctaButton?.text || 'Request a Quote'" 6891 ></button> 6892 <button 6893 @click="dismissCTA()" 6894 class="ai-chatbot__cta-dismiss" 6895 type="button" 6896 aria-label="Dismiss" 6897 > 6898 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 6899 <line x1="18" y1="6" x2="6" y2="18"></line> 6900 <line x1="6" y1="6" x2="18" y2="18"></line> 6901 </svg> 6902 </button> 6903 </div><div x-show="conversationStatus === 'resolved'" x-cloak class="ai-chatbot__resolved-banner"> 6904 Chat ended â send a message to start again. 6905 </div><div x-show="showContactAsk" x-cloak class="ai-chatbot__contact-ask"> 6906 <p class="ai-chatbot__contact-ask-prompt" x-show="contactAskMode === 'email_chip'">Leave your email in case you step away.</p> 6907 <p class="ai-chatbot__contact-ask-prompt" x-show="contactAskMode === 'progressive'">Mind sharing your name and email so we can follow up?</p> 6908 <form @submit.prevent="submitContact()" class="ai-chatbot__contact-ask-form"> 6909 <input 6910 x-show="contactAskMode !== 'email_chip' && !contactName" 6911 x-model="contactNameInput" 6912 type="text" 6913 class="ai-chatbot__contact-ask-input" 6914 placeholder="Your name" 6915 :disabled="contactSubmitting" 6916 > 6917 <input 6918 x-show="!contactEmail" 6919 x-model="contactEmailInput" 6920 type="email" 6921 class="ai-chatbot__contact-ask-input" 6922 placeholder="Your email" 6923 :disabled="contactSubmitting" 6924 > 6925 <button 6926 type="submit" 6927 class="ai-chatbot__contact-ask-submit" 6928 :disabled="contactSubmitting" 6929 > 6930 Send 6931 </button> 6932 <button 6933 type="button" 6934 @click="dismissContactAsk()" 6935 class="ai-chatbot__contact-ask-dismiss" 6936 aria-label="Dismiss" 6937 > 6938 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 6939 <line x1="18" y1="6" x2="6" y2="18"></line> 6940 <line x1="6" y1="6" x2="18" y2="18"></line> 6941 </svg> 6942 </button> 6943 </form> 6944 </div><div class="ai-chatbot__input-area"> 6945 <form @submit.prevent="sendMessage()" class="ai-chatbot__input-form"> 6946 <textarea 6947 x-ref="chatInput" 6948 x-model="inputText" 6949 @keydown="handleKeyDown($event)" 6950 class="ai-chatbot__input" 6951 placeholder="Type your message..." 6952 rows="1" 6953 :disabled="isLoading" 6954 ></textarea> 6955 <button 6956 type="submit" 6957 class="ai-chatbot__send-btn" 6958 :disabled="isLoading || !inputText.trim()" 6959 aria-label="Send" 6960 > 6961 <template x-if="isLoading"> 6962 <svg class="ai-chatbot__spinner" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 6963 <line x1="12" y1="2" x2="12" y2="6"></line> 6964 <line x1="12" y1="18" x2="12" y2="22"></line> 6965 <line x1="4.93" y1="4.93" x2="7.76" y2="7.76"></line> 6966 <line x1="16.24" y1="16.24" x2="19.07" y2="19.07"></line> 6967 <line x1="2" y1="12" x2="6" y2="12"></line> 6968 <line x1="18" y1="12" x2="22" y2="12"></line> 6969 <line x1="4.93" y1="19.07" x2="7.76" y2="16.24"></line> 6970 <line x1="16.24" y1="7.76" x2="19.07" y2="4.93"></line> 6971 </svg> 6972 </template> 6973 <template x-if="!isLoading"> 6974 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
6975 <line x1="22" y1="2" x2="11" y2="13"></line> 6976 <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon> 6977 </svg> 6978 </template> 6979 </button> 6980 </form><p 6981 class="ai-chatbot__disclaimer" 6982 x-show="conversationStatus === null || conversationStatus === 'bot'" 6983 > 6984 Responses are generated by AI and may be inaccurate. 6985 </p> 6986 </div> 6987 </div> 6988 </div> 6989 </template> 6990 </data-island> 6991</div> 6992 6993 6994 <section id="shopify-section-branding-service-cards" class="shopify-section branding-service-cards-section"><style data-shopify> 6995 .branding-floating-overlay { 6996 position: fixed; 6997 inset: 0; 6998 z-index: 9999; 6999 background: rgba(0, 0, 0, 0.5); 7000 opacity: 0; 7001 transition: opacity 300ms ease; 7002 pointer-events: none; 7003 } 7004 7005 .branding-floating-overlay.active { 7006 opacity: 1; 7007 pointer-events: auto; 7008 } 7009 7010 /* Floating card - matches carousel expanded card styling */ 7011 .branding-floating-card { 7012 position: fixed; 7013 z-index: 10000; 7014 background: rgb(var(--color-scheme-background, 255 255 255)); 7015 border-radius: 16px; 7016 box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.4); 7017 display: none; 7018 flex-direction: column; 7019 max-height: 85vh; 7020 overflow: hidden; 7021 /* No default top/left/bottom - JS controls position */ 7022 } 7023 7024 /* Close button - matches carousel style */ 7025 .branding-floating-card .branding-pill-close { 7026 position: absolute; 7027 top: 12px; 7028 right: 12px; 7029 z-index: 10; 7030 width: 32px; 7031 height: 32px; 7032 border-radius: 50%; 7033 background: rgba(255, 255, 255, 0.9); 7034 border: none; 7035 cursor: pointer; 7036 display: flex; 7037 align-items: center; 7038 justify-content: center; 7039 box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); 7040 transition: background 200ms ease; 7041 } 7042 7043 .branding-floating-card .branding-pill-close:hover { 7044 background: rgba(255, 255, 255, 1); 7045 } 7046 7047 .branding-floating-card .branding-pill-close svg { 7048 width: 16px; 7049 height: 16px; 7050 stroke: #333; 7051 } 7052 7053 /* Image link - matches carousel style */ 7054 .branding-floating-card .branding-pill-image-link { 7055 display: block; 7056 flex-shrink: 0; 7057 background: rgba(var(--color-scheme-text, 0 0 0), 0.05); 7058 min-height: 200px; 7059 } 7060 7061 .branding-floating-card .branding-pill-image-link.has-image { 7062 min-height: 0; 7063 } 7064 7065 .branding-floating-card .branding-pill-image { 7066 border-radius: 16px 16px 0 0; 7067 width: 100%; 7068 height: auto; 7069 max-height: 280px; 7070 object-fit: cover; 7071 display: block; 7072 } 7073 7074 .branding-floating-card .branding-pill-image:not([src]), 7075 .branding-floating-card .branding-pill-image[src=""] { 7076 display: none; 7077 } 7078 7079 /* Label button overlay - matches carousel style */ 7080 .branding-floating-card .branding-pill-label { 7081 display: none; /* Hidden in expanded state like carousel */ 7082 } 7083 7084 /* Expanded content - matches carousel style */ 7085 .branding-floating-card .branding-pill-content { 7086 padding: 20px; 7087 flex-shrink: 0; 7088 } 7089 7090 .branding-floating-card .branding-expanded-title { 7091 margin: 0 0 12px 0; 7092 font-size: 1.25rem; 7093 font-weight: 600; 7094 color: black; 7095 7096 } 7097 7098 .branding-floating-card .branding-expanded-loading { 7099 display: flex; 7100 align-items: center; 7101 justify-content: center; 7102 padding: 20px; 7103 } 7104 7105 .branding-floating-card .branding-expanded-spinner { 7106 width: 24px; 7107 height: 24px; 7108 border: 2px solid rgba(var(--color-scheme-text, 0 0 0), 0.1); 7109 border-top-color: rgb(var(--color-scheme-text, 0 0 0)); 7110 border-radius: 50%; 7111 animation: branding-pill-spin 0.8s linear infinite; 7112 } 7113 7114 @keyframes branding-pill-spin { 7115 to { transform: rotate(360deg); } 7116 } 7117 7118 .branding-floating-card .branding-expanded-description { 7119 margin-bottom: 16px; 7120 line-height: 1.6; 7121 color: black; 7122 } 7123 7124 .branding-floating-card .branding-expanded-description p { 7125 margin: 0; 7126 } 7127 7128 .branding-floating-card .branding-expanded-description p + p { 7129 margin-top: 0.75em; 7130 } 7131 7132 @media (max-width: 749px) { 7133 .branding-floating-card { 7134 width: calc(100vw - 48px) !important; 7135 left: 24px !important; 7136 max-width: none !important; 7137 } 7138 } 7139</style> 7140 7141<!-- Overlay backdrop --> 7142<div 7143 id="branding-floating-overlay" 7144 class="branding-floating-overlay" 7145 onclick="window.closeBrandingServiceCard()" 7146></div> 7147 7148<!-- Floating card - HTML structure matches carousel expanded cards --> 7149<div 7150 id="branding-floating-card" 7151 class="branding-floating-card color-scheme5" 7152> 7153 <!-- Close button (top right over image) --> 7154 <button type="button" class="branding-pill-close" onclick="window.closeBrandingServiceCard()"> 7155 <span class="sr-only">Close</span> 7156 <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> 7157 <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /> 7158 </svg> 7159 </button> 7160 7161 <!-- Image with link --> 7162 <a id="branding-card-image-link" href="#" class="branding-pill-image-link"> 7163 <img 7164 id="branding-card-image" 7165 class="branding-pill-image" 7166 src="" 7167 alt="" 7168 loading="lazy" 7169 width="300" 7170 height="300" 7171 > 7172 </a> 7173 7174 <!-- Label button (hidden in expanded state, like carousel) --> 7175 <a id="branding-card-label" href="#" class="branding-pill-label"></a> 7176 7177 <!-- Expanded content --> 7178 <div class="branding-pill-content"> 7179 <h3 id="branding-card-title" class="branding-expanded-title"></h3> 7180 <div id="branding-card-loading" class="branding-expanded-loading" style="display: none;"> 7181 <div class="branding-expanded-spinner"></div> 7182 </div> 7183 <div id="branding-card-description" class="branding-expanded-description"></div> 7184 </div> 7185</div> 7186
7187<script> 7188(function() { 7189 // Build service data from Shopify blocks 7190 // Key is the lowercase metafield value (e.g., "screen print", "custom neck tags") 7191 const brandingServiceData = { 7192 7193 'high density transfer': { 7194 title: "High density transfer", 7195 description: "\u003cp\u003eA high density transfer is a heat-applied decoration that creates a raised, textured print using layered ink, producing a bold, dimensional effect with sharp edges and strong durability on garments.\u003c\/p\u003e", 7196 image: '//printroom.co/cdn/shop/files/heat_transfer_2_1b6dd18d-7ae5-452a-a0ca-fef697ba6400.jpg?v=1761181341&width=800', 7197 imageAlt: "High density transfer", 7198 ctaText: "Learn more", 7199 ctaUrl: '#' 7200 }, 7201 7202 'printed seam tape': { 7203 title: "printed seam tape", 7204 description: "\u003cp\u003eAdd a custom touch to the inside of your cap with printed seam tape. This often-overlooked detail offers a unique way to showcase your brand, giving your caps a polished finish that stands out from the inside out. Fully customisable, itâs a small touch that makes a big impression.\u003c\/p\u003e", 7205 image: '//printroom.co/cdn/shop/files/speights_cap_inner_3.jpg?v=1743540305&width=800', 7206 imageAlt: "custom caps NZ", 7207 ctaText: "Learn more", 7208 ctaUrl: '#' 7209 }, 7210 7211 'knitted all-over': { 7212 title: "Knitted all-over", 7213 description: "\u003cp\u003eKnitted all-over designs weave patterns directly into the fabric of your custom socks, creating a seamless, durable look that wonât fade over time. Ideal for intricate, full-length designs with lasting quality.\u003c\/p\u003e", 7214 image: '//printroom.co/cdn/shop/files/knitted_all_over_detail.jpg?v=1772668725&width=800', 7215 imageAlt: "Knitted all-over", 7216 ctaText: "Learn more", 7217 ctaUrl: '#' 7218 }, 7219 7220 'dye-sublimation': { 7221 title: "Dye-sublimation", 7222 description: "\u003cp\u003eDye-sublimation allows vibrant, full-colour designs to be seamlessly printed on your custom socks. The process ensures high-quality, durable prints that wonât fade, perfect for intricate patterns or all-over designs.\u003c\/p\u003e", 7223 image: '//printroom.co/cdn/shop/files/dye_sub_detail.jpg?v=1772673144&width=800', 7224 imageAlt: "Dye-sublimation", 7225 ctaText: "Learn more", 7226 ctaUrl: '#' 7227 }, 7228 7229 'additional cushioning': { 7230 title: "Additional cushioning", 7231 description: "\u003cp\u003eAdd extra cushioning to your custom socks for improved comfort and support. The soft padding underfoot reduces impact, perfect for all-day wear or active use.\u003c\/p\u003e", 7232 image: '//printroom.co/cdn/shop/files/cushion_detail.jpg?v=1772673175&width=800', 7233 imageAlt: "Additional cushioning", 7234 ctaText: "Learn more", 7235 ctaUrl: '#' 7236 }, 7237 7238 'added grip': { 7239 title: "Added grip", 7240 description: "\u003cp\u003eEnhance your custom socks with added grip to prevent slipping! The textured grip on the sole ensures better traction, or adds an extra dimension to your custom product.\u003c\/p\u003e", 7241 image: '//printroom.co/cdn/shop/files/added_grip_detail.jpg?v=1772675209&width=800', 7242 imageAlt: "Added grip", 7243 ctaText: "Learn more", 7244 ctaUrl: '#' 7245 }, 7246 7247 'custom neck tags': { 7248 title: "Custom neck tags", 7249 description: "\u003cp\u003eMake your brand stand out with custom neck tags! Whether you choose woven labels or screen printing, our high-quality neck tags offer a professional finish and are ideal for showcasing your unique brand identity.\u003c\/p\u003e", 7250 image: '//printroom.co/cdn/shop/files/cardrona_4_2_936c38b5-e634-4f0f-b224-0c9ed7b76ed9.jpg?v=1648584454&width=800', 7251 imageAlt: "garment relabelling and custom neck tags christchurch", 7252 ctaText: "Learn more", 7253 ctaUrl: '#' 7254 }, 7255 7256 'screen print': { 7257 title: "Screen Printing", 7258 description: "\u003cp\u003eOur most popular print method for good reasonâit delivers \u003cstrong\u003etop-tier qual
7258ity\u003c\/strong\u003e, long-lasting results, and exceptional value for larger orders.\u003c\/p\u003e", 7259 image: '//printroom.co/cdn/shop/files/PrintRoomMay2024Image-16.jpg?v=1733350366&width=800', 7260 imageAlt: "Screen Printing", 7261 ctaText: "Learn more", 7262 ctaUrl: '#' 7263 }, 7264 7265 'embroidery': { 7266 title: "Embroidery", 7267 description: "\u003cp\u003eUnmatched in durability, embroidery is a simple choice for those wanting texture, dimension and a high-end finish.\u003c\/p\u003e", 7268 image: '//printroom.co/cdn/shop/files/The_print_room_custom_embroidery_new_zealand.jpg?v=1613753361&width=800', 7269 imageAlt: "Embroidery", 7270 ctaText: "Learn more", 7271 ctaUrl: '#' 7272 }, 7273 7274 'heat transfer': { 7275 title: "Heat Transfers", 7276 description: "\u003cp\u003ePerfect for producing vibrant, detail-rich prints that require low minimums.\u003c\/p\u003e", 7277 image: '//printroom.co/cdn/shop/files/heat_press_print_room.jpg?v=1776795804&width=800', 7278 imageAlt: "Heat Transfers", 7279 ctaText: "Learn more", 7280 ctaUrl: '/pages/heat-transfers' 7281 }, 7282 7283 'custom patches': { 7284 title: "Custom Patches", 7285 description: "\u003cp\u003eDurable and versatile, add dimension to your merch with embroidered, woven or iron-on custom patches.\u003c\/p\u003e", 7286 image: '//printroom.co/cdn/shop/files/PrintRoomApril2024Image-42_28acbdcf-7baf-4834-9201-752d656019ad.jpg?v=1754535298&width=800', 7287 imageAlt: "custom patches NZ", 7288 ctaText: "Learn more", 7289 ctaUrl: '#' 7290 }, 7291 7292 'custom packaging': { 7293 title: "Custom packaging", 7294 description: "\u003cp\u003eThe ultimate finishing touch; custom packaging. Itâs the first thing your customer sees, make the best impression possible and package your products inline with your brand.\u003c\/p\u003e", 7295 image: '//printroom.co/cdn/shop/files/socks_label.jpg?v=1743476398&width=800', 7296 imageAlt: "custom socks", 7297 ctaText: "Learn more", 7298 ctaUrl: '#' 7299 }, 7300 7301 'custom woven label': { 7302 title: "Custom woven label", 7303 description: "\u003cp\u003eGive all of the details you need while putting the finishing touches on your product.\u003c\/p\u003e", 7304 image: '//printroom.co/cdn/shop/files/garage_project_cap_4.1.jpg?v=1770086525&width=800', 7305 imageAlt: "Custom woven label", 7306 ctaText: "Learn more", 7307 ctaUrl: '#' 7308 }, 7309 7310 'pip tags': { 7311 title: "Pip tags", 7312 description: "\u003cp\u003eElevate your garments with custom pip tags. Perfect for adding subtle branding, a small detail with a big impact for your apparel collection.\u003c\/p\u003e", 7313 image: '//printroom.co/cdn/shop/files/cardrona_3_19a3035b-75a5-4fd0-9604-01d159cdc102.jpg?v=1648585469&width=800', 7314 imageAlt: "garment relabelling and custom neck tags nz", 7315 ctaText: "Learn more", 7316 ctaUrl: '#' 7317 }, 7318 7319 'additional print placements': { 7320 title: "Additional print placements", 7321 description: "\u003cp\u003eAdd extra visibility to your brand by adding additional prints\/decorations. Back of the cap, sleeve of your sweatshirt; you name it, we can most likely do it. Make the most of your products' full 360 degrees.\u003c\/p\u003e", 7322 image: '//printroom.co/cdn/shop/files/garage_project_cap_3.1.jpg?v=1770083144&width=800', 7323 imageAlt: "Additional print placements", 7324 ctaText: "Learn more", 7325 ctaUrl: '#' 7326 }, 7327 7328 'various attachments available': { 7329 title: "Various attachments available", 7330 description: "\u003cp\u003eMake the most of customisation and choose the attachment style that works for your project. Robust, intricate, elegantâ¦your choice.\u003c\/p\u003e", 7331 image: '//printroom.co/cdn/shop/files/pack-a-punch.jpg?v=1760925265&width=800', 7332 imageAlt: "Various attachments available", 7333 ctaText: "Learn more", 7334 ctaUrl: '#' 7335 }, 7336 7337 'add additional colours': { 7338 title: "Add additional colours", 7339 description: "\u003cp\u003eCreate more depth and complexity when your brand needs it. Specific limitations apply to each product. Consult your account manager for specific limitations.\u003c\/p\u003e", 7340 image: '//printroom.co/cdn/shop/files/ombre.jpg?v=1770253000&width=800', 7341 imageAlt: "Add additional colours", 7342 ctaText: "Learn more", 7343 ctaUrl: '#' 7344 }, 7345 7346 'various closures available': { 7347 title: "Various closures available", 7348 description: "\u003cp\u003eAchieve the result you want with control over what closure you go with.\u003c\/p\u003e", 7349 image: '//printroom.co/cdn/shop/files/closure_options_2.1_76d53ef9-c502-45b4-b915-66543d3c7f40.jpg?v=1769654951&width=800', 7350 imageAlt: "Various closures available", 7351 ctaText: "Learn more", 7352 ctaUrl: '#' 7353 }, 7354 7355 'glow in the dark': { 7356 title: "Glow in the dark", 7357 description: "\u003cp\u003eBe seenâ¦in the dark! Add a novel element to your product and have some fun with it.\u003c\/p\u003e", 7358 image: '//printroom.co/cdn/shop/files/glow_in_the_dark.jpg?v=1770253668&width=800', 7359 imageAlt: "Glow in the dark", 7360 ctaText: "Learn more", 7361 ctaUrl: '#' 7362 }, 7363 7364 'applique': { 7365 title: "Applique", 7366 description: "\u003cp\u003eAppliqué embroidery isa technique where small pieces of fabric are laser cut and layered and stitched onto a garment, adding texture to the design.\u003c\/p\u003e", 7367 image: '//printroom.co/cdn/shop/files/Screenshot-2026-04-22-at-6.18.38_AM.jpg?v=1776795959&width=800', 7368 imageAlt: "Applique", 7369 ctaText: "Learn more", 7370 ctaUrl: '#' 7371 }, 7372 7373 'spreadsheet': { 7374 title: "Spreadsheet", 7375 description: "\u003cp\u003eWe send you a formatted spreadsheet that can be shared around your year group for each student to input the
7375ir garment style, size and custom name. \u003c\/p\u003e", 7376 image: null, 7377 imageAlt: "Spreadsheet", 7378 ctaText: "Learn more", 7379 ctaUrl: '#' 7380 }, 7381 7382 'online portal': { 7383 title: "Online portal", 7384 description: "\u003cp\u003eWe setup an password portected online portal for your year group to log into and purchased or order their garments. \u003c\/p\u003e", 7385 image: '//printroom.co/cdn/shop/files/product_1db770e9-3325-4bd4-8636-6f4b6d5e566a_slot_5.jpg?v=1776753322&width=800', 7386 imageAlt: "Earth Positive Premium Jersey T-shirt EP185 T-shirt branded merchandise nz", 7387 ctaText: "Click", 7388 ctaUrl: '#' 7389 } 7390 7391 }; 7392 7393 // Also build hyphenated keys for matching 7394 const brandingServiceDataNormalized = {}; 7395 Object.keys(brandingServiceData).forEach(key => { 7396 // Store with original key 7397 brandingServiceDataNormalized[key] = brandingServiceData[key]; 7398 // Also store with hyphenated version 7399 const hyphenated = key.replace(/\s+/g, '-'); 7400 brandingServiceDataNormalized[hyphenated] = brandingServiceData[key]; 7401 // Also store with spaced version (in case key was hyphenated) 7402 const spaced = key.replace(/-/g, ' '); 7403 brandingServiceDataNormalized[spaced] = brandingServiceData[key]; 7404 }); 7405 7406 // Configuration from section settings 7407 const config = { 7408 maxWidth: 400, 7409 animationDuration: 300, 7410 showOverlay: false 7411 }; 7412 7413 // State 7414 let isCardOpen = false; 7415 let originRect = null; 7416 7417 // DOM elements 7418 const overlay = document.getElementById('branding-floating-overlay'); 7419 const card = document.getElementById('branding-floating-card'); 7420 const cardImageLink = document.getElementById('branding-card-image-link'); 7421 const cardImage = document.getElementById('branding-card-image'); 7422 const cardLabel = document.getElementById('branding-card-label'); 7423 const cardTitle = document.getElementById('branding-card-title'); 7424 const cardLoading = document.getElementById('branding-card-loading'); 7425 const cardDescription = document.getElementById('branding-card-description'); 7426 7427 // Find service data by matching the label text 7428 function findServiceData(label) { 7429 if (!label) return null; 7430 const searchKey = label.toLowerCase().trim(); 7431 const searchKeyHyphenated = searchKey.replace(/\s+/g, '-'); 7432 7433 // Direct match 7434 if (brandingServiceDataNormalized[searchKey]) { 7435 return brandingServiceDataNormalized[searchKey]; 7436 } 7437 7438 // Try hyphenated version 7439 if (brandingServiceDataNormalized[searchKeyHyphenated]) { 7440 return brandingServiceDataNormalized[searchKeyHyphenated]; 7441 } 7442 7443 // Partial match - check if any key is contained in the label or vice versa 7444 for (const key of Object.keys(brandingServiceDataNormalized)) { 7445 if (searchKey.includes(key) || key.includes(searchKey)) { 7446 return brandingServiceDataNormalized[key]; 7447 } 7448 } 7449 7450 return null; 7451 } 7452 7453 // Populate card content 7454 function populateCard(data, serviceUrl) { 7455 const url = data.ctaUrl || serviceUrl || '#'; 7456 7457 // Set image 7458 if (data.image) { 7459 cardImage.src = data.image; 7460 cardImage.alt = data.imageAlt || data.title || ''; 7461 cardImageLink.classList.add('has-image'); 7462 } else { 7463 cardImage.src = ''; 7464 cardImage.alt = ''; 7465 cardImageLink.classList.remove('has-image'); 7466 } 7467 7468 // Set links 7469 cardImageLink.href = url; 7470 cardLabel.href = url; 7471 cardLabel.textContent = data.title || ''; 7472 7473 // Set content 7474 cardTitle.textContent = data.title || ''; 7475 7476 // Handle description - if we have static content use it, otherwise fetch 7477 if (data.description && data.description.trim() !== '' && data.description !== '<p>Add a description of this branding service.</p>') { 7478 cardDescription.innerHTML = data.description; 7479 cardLoading.style.display = 'none'; 7480 } else { 7481 // Fetch description from service page 7482 cardDescription.innerHTML = ''; 7483 cardLoading.style.display = 'flex'; 7484 7485 if (url && url !== '#') { 7486 fetch(url) 7487 .then(response => response.text()) 7488 .then(html => { 7489 const parser = new DOMParser(); 7490 const doc = parser.parseFromString(html, 'text/html'); 7491 const main = doc.querySelector('main') || doc.querySelector('.page-content') || doc.querySelector('.shopify-section') || doc.body; 7492 let description = '<p>Discover our premium branding service.</p>'; 7493 if (main) { 7494 const firstP = main.querySelector('p'); 7495 if (firstP) description = '<p>' + firstP.textContent.trim() + '</p>'; 7496 } 7497 cardDescription.innerHTML = description; 7498 cardLoading.style.display = 'none'; 7499 }) 7500 .catch(() => { 7501 cardDescription.innerHTML = '<p>Discover our premium branding service.</p>'; 7502 cardLoading.style.display = 'none'; 7503 }); 7504 } else { 7505 cardDescription.innerHTML = '<p>Discover our premium branding service.</p>'; 7506 cardLoading.style.display = 'none'; 7507 } 7508 } 7509 } 7510 7511 // Show card with animation from button position 7512 function showCardWithData(data, buttonElement, serviceUrl) { 7513 if (!data) { 7514 console.warn('No service data provided'); 7515 return; 7516 } 7517 7518 // Get button position for animation origin 7519 const buttonRect = buttonElement 7520 ? buttonElement.getBoundingClientRect() 7521 : { left: window.innerWidth / 2 - 50, top: window.innerHeight / 2, width: 100, height: 40 }; 7522 7523 originRect = { ...buttonRect }; 7524 7525 // Populate content 7526 populateCard(data, serviceUrl); 7527 7528 // Calculate target dimensions 7529 const expandedWidth = Math.min(window.innerWidth - 40, config.maxWidth); 7530 const padding = 20; 7531 const headerHeight = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--header-height') || '0', 10); 7532 7533 // Center expanded card horizontally on the button's center 7534const buttonCenterX = buttonRect.left + (buttonRect.width / 2); 7535let targetLeft = buttonCenterX - (expandedWidth / 2); 7536 7537// Clamp to viewport bounds horizontally 7538targetLeft = Math.max(padding, Math.min(targetLeft, window.innerWidth - expandedWidth - padding)); 7539 7540// Position vertically: expand from button's top, but ensure it stays in viewport 7541// Start from the button's vertical position 7542let targetTop = buttonRect.top; 7543 7544// Get actual card content height or use a more realistic estimate 7545const cardContent = card.querySelector('.card__content') || card; 7546const estimatedCardHeight = cardContent.scrollHeight || 600; // Increased from 400 to 600 7547 7548// Calculate available space below and above the button 7549const spaceBelow = window.innerHeight - buttonRect.bottom - padding; 7550const spaceAbove = buttonRect.top - headerHeight - padding; 7551 7552// If card would go below viewport, shift it up 7553if (targetTop + estimatedCardHeight > window.innerHeight - padding) { 7554 targetTop = Math.max(headerHeight + padding, window.innerHeight - estimatedCardHeight - padding); 7555} 7556 7557// If card would go above header, shift it down 7558if (targetTop < headerHeight + padding) { 7559 targetTop = headerHeight + padding; 7560} 7561 7562// Final safety check: ensure card fits in viewport 7563const maxAllowedHeight = window.innerHeight - headerHeight - (padding * 2); 7564if (estimatedCardHeight > maxAllowedHeight) { 7565 targetTop = headerHeight + padding; 7566 card.style.maxHeight = maxAllowedHeight + 'px'; 7567 card.style.overflowY = 'auto'; 7568} 7569 7570 7571 // Show overlay 7572 if (config.showOverlay) { 7573 overlay.classList.add('active'); 7574 } 7575 7576 // Set initial state at EXACT button position 7577 card.style.position = 'fixed'; 7578 card.style.top = buttonRect.top + 'px'; 7579 card.style.left = buttonRect.left + 'px'; 7580 card.style.width = buttonRect.width + 'px'; 7581 card.style.height = buttonRect.height + 'px'; 7582 card.style.zIndex = '10000'; 7583 card.style.margin = '0'; 7584 card.style.display = 'flex'; 7585 card.style.opacity = '1'; 7586 card.style.pointerEvents = 'auto'; 7587 card.style.overflow = 'hidden';
7588 card.style.transition = 'none'; 7589 card.style.flexDirection = 'column'; 7590 card.style.borderRadius = '16px'; 7591 7592 // Force reflow to ensure initial position is applied 7593 card.getBoundingClientRect(); 7594 7595 // Now animate to expanded position 7596 requestAnimationFrame(() => { 7597 requestAnimationFrame(() => { 7598 card.style.transition = ` 7599 top ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1), 7600 left ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1), 7601 width ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1), 7602 height ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1) 7603 `; 7604 card.style.top = targetTop + 'px'; 7605 card.style.left = targetLeft + 'px'; 7606 card.style.width = expandedWidth + 'px'; 7607 card.style.height = 'auto'; 7608 }); 7609 }); 7610 7611 isCardOpen = true; 7612 } 7613 7614 // Close card with animation back to origin 7615 window.closeBrandingServiceCard = function() { 7616 if (!isCardOpen) return; 7617 7618 // Animate back to origin position (exactly like carousel collapseCard) 7619 if (originRect) { 7620 card.style.transition = ` 7621 top ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1), 7622 left ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1), 7623 width ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1), 7624 height ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1) 7625 `; 7626 card.style.top = originRect.top + 'px'; 7627 card.style.left = originRect.left + 'px'; 7628 card.style.width = originRect.width + 'px'; 7629 card.style.height = originRect.height + 'px'; 7630 card.style.overflow = 'hidden'; 7631 } 7632 7633 // Hide overlay 7634 overlay.classList.remove('active'); 7635 7636 // Clean up after animation 7637 setTimeout(() => { 7638 card.style.display = 'none'; 7639 card.style.transition = ''; 7640 card.style.top = ''; 7641 card.style.left = ''; 7642 card.style.width = ''; 7643 card.style.height = ''; 7644 card.style.opacity = ''; 7645 card.style.pointerEvents = ''; 7646 card.style.overflow = ''; 7647 isCardOpen = false; 7648 originRect = null; 7649 }, config.animationDuration); 7650 }; 7651 7652 // Event listener for pill button clicks 7653 // Alpine's $dispatch bubbles from the element through the DOM 7654 document.addEventListener('branding-modal:open', (event) => { 7655 // Prevent duplicate handling 7656 if (event._handled) return; 7657 event._handled = true; 7658 7659 const { label, url, element } = event.detail || {}; 7660 7661 // Get the pill text from the button element if available 7662 const pillText = element ? (element.querySelector('.branding-service-pill__text')?.textContent || label) : label; 7663 7664 // Find service data by matching the pill text 7665 const serviceData = findServiceData(pillText); 7666 if (!serviceData) { 7667 console.warn('No service data configured for:', pillText); 7668 return; 7669 } 7670 7671 // If a card is already open, close it first 7672 if (isCardOpen) { 7673 window.closeBrandingServiceCard(); 7674 setTimeout(() => { 7675 showCardWithData(serviceData, element, url); 7676 }, config.animationDuration + 50); 7677 } else { 7678 showCardWithData(serviceData, element, url); 7679 } 7680 }); 7681 7682 // Escape key handler 7683 document.addEventListener('keydown', (e) => { 7684 if (e.key === 'Escape' && isCardOpen) { 7685 window.closeBrandingServiceCard(); 7686 } 7687 }); 7688})(); 7689</script>
7689 7690 7691 7692</section> 7693 7694
7694<script src="//printroom.co/cdn/shop/t/59/assets/global.bundle.js?v=149077486339995821341790734057" type="module"></script>
7694 7695 7696
7696<script> 7697 window.Shopify = window.Shopify || {}; 7698 window.Shopify.locale = "en"; 7699 window.Shopify.currency = { 7700 active: "USD", 7701 rate: "" 7702 }; 7703 </script>
7703 7704
7704<script src="https://cdn.shopify.com/storefront/standard-actions.js" type="module" data-source-attribution="shopify.standard_actions"></script>
7704 7705</body> 7706</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.