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":"search","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":"search","theme":151830298694,"product":null,"collection":null,"page":null,"blog":null,"article":null,"app":null},"now":1791103102,"path":"\/search","locale_root_url":"\/","canonical_url":"https:\/\/printroom.co\/search","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\":\"search\",\"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\":\"search\",\"theme\":151830298694,\"product\":null,\"collection\":null,\"page\":null,\"blog\":null,\"article\":null,\"app\":null},\"now\":1791103102,\"path\":\"\\\/search\",\"locale_root_url\":\"\\\/\",\"canonical_url\":\"https:\\\/\\\/printroom.co\\\/search\",\"customer_id\":null,\"customer_id_signature\":\"a6111dc4847a5059d4622e3d27b184dd5cbae461b5d6fc459feab12efb47932d\",\"cart\":null}";Locksmith.jsonTagSignature="d0e376ff351f9a972ff38fa1144f6e894a4af5036350e1d42e93909fa0287950"</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: "search" 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/search"> 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 -->
274<!-- pageTitleTemplate: Shop %% search.terms %% at %% shop.name %% --> 275 <!-- pageTitleToParse": Search --> 276 <!-- pageTitleTruncateApplicable: true --> 277 278 <!-- pluginseo_pageTitleTemplateApplyToAll: true --> 279 <!-- pageTitleTruncateApplicable: true --><!-- Custom page title: Yes --><title>Shop at The Print Room | The Print Room</title> <!-- default to true --><!-- metaDescriptionTemplate: Find %% search.terms || default: 'it' %% here%% search.results || map: 'title' || take: '3' || join: ', ' || prepend_not_empty: ' including ' || append_not_empty: ' and more' %% at %% shop.name %% --> 280 <!-- metaDescriptionToParse": 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. --> 281 <!-- metaDescriptionTruncateApplicable: true --> 282 283 <!-- pluginseo_metaDescriptionTemplateApplyToAll: true --> 284 <!-- metaDescriptionTruncateApplicable: true --><!-- Yes --><meta name="description" content="Find it here at The Print Room" />
285<script data-desc="seo-breadcrumb-list" type="application/ld+json"> 286{ 287 "@context": "http://schema.org", 288 "@type": "BreadcrumbList", 289 "itemListElement": [] 290} 291</script>
291<script data-desc="seo-organization" type="application/ld+json"> 292 { 293 "@context": "http://schema.org", 294 "@type": "Organization", 295 "additionalType": "https://schema.org/OnlineStore", 296 "@id": "https://printroom.co#organization", 297 "name": "The Print Room", 298 "url": "https://printroom.co", 299 "description": "Find it here at The Print Room","logo": { 300 "type": "ImageObject", 301 "url": "https://printroom.co/cdn/shop/t/59/assets/pluginseo_structuredDataLogo_small.png?v=39003" 302 }, 303 "image": "https://printroom.co/cdn/shop/t/59/assets/pluginseo_structuredDataLogo_small.png?v=39003","areaServed": [{ "@type": "Country", "name": "Australia" }, 304 { "@type": "Country", "name": "New Zealand" }], 305 "sameAs": ["https://www.linkedin.com/company/theprintroom"] 306 } 307</script>
307<script data-desc="seo-website" type="application/ld+json"> 308 { 309 "@context": "http://schema.org", 310 "@type": "WebSite", 311 "name": "The Print Room", 312 "url": "https://printroom.co", 313 "inLanguage": "en", 314 "potentialAction": { 315 "@type": "SearchAction", 316 "target": "https://printroom.co/search?q={search_term_string}", 317 "query-input": "required name=search_term_string" 318 } 319 } 320</script>
320<meta name="pluginseo" content="Plug in SEO Plus" data-ptf="s-te_se-ap" data-mdf="s-te_se" /> 321 322 323
323<script type="esms-options"> 324 { 325 "noLoadEventRetriggers": true 326 } 327</script>
327 328
329<script> 330 if ( 331 !(HTMLScriptElement.supports && HTMLScriptElement.supports('importmap')) 332 ) { 333 const importMapShimScriptEl = document.createElement('script'); 334 importMapShimScriptEl.src = '//printroom.co/cdn/shop/t/59/assets/es-module-shims.bundle.min.js?v=98603786603752121101787098437' 335 importMapShimScriptEl.async = true; 336 337 document.currentScript.after(importMapShimScriptEl); 338 } 339</script>
vendor: 1 bytes, line 339
339
340<script async crossorigin fetchpriority="high" src="/cdn/shopifycloud/importmap-polyfill/es-modules-shim.2.4.0.js"></script>
vendor: 1 bytes, line 340
340
341<script type="importmap"> 342 { 343 "imports": { 344 "vendor": "//printroom.co/cdn/shop/t/59/assets/vendor.bundle.min.js?v=124729801276099409011787098433", 345 "deferrable-data": "//printroom.co/cdn/shop/t/59/assets/deferrable-data.bundle.js?v=160370895301608380811787098437", 346 "@supabase/supabase-js": "//printroom.co/cdn/shop/t/59/assets/supabase-js.bundle.js?v=151185893978749678631787098436", 347 "product": "//printroom.co/cdn/shop/t/59/assets/island-product.bundle.js?v=53162399053546849101790733316", 348 "quick-buy": "//printroom.co/cdn/shop/t/59/assets/island-quick-buy.bundle.js?v=147469616221971819701787098437", 349 "ai-chatbot": "//printroom.co/cdn/shop/t/59/assets/ai-chatbot.bundle.js?v=114215721854634402901788472409", 350 "leavers-quote-builder": "//printroom.co/cdn/shop/t/59/assets/leavers-quote-builder.bundle.js?v=140741536858912509621787098436", 351 "leavers-product-grid": "//printroom.co/cdn/shop/t/59/assets/leavers-product-grid.bundle.js?v=101839867699394922961787098435" 352 } 353 } 354</script>
354 355
356<script> 357 (function() { 358 var _originalAlert = window.alert; 359 window.alert = function(message) { 360 if (message && message.toLowerCase().includes('personalized text')) { 361 message = 'This field is required to place an order.'; 362 } 363 _originalAlert.call(window, message); 364 }; 365 })(); 366 </script>
366 367 368
368<script>window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.start');</script>
368<meta name="google-site-verification" content="r89mOlbEOfEjECOwEHOd5jrv5jGOJeGHPXM78LaGLXY"> 369<meta id="shopify-digital-wallet" name="shopify-digital-wallet" content="/7054289/digital_wallets/dialog"> 370<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"> 371<link rel="ucp" href="/.well-known/ucp" version="2026-08-25"><link rel="alternate" hreflang="x-default" href="https://theprintroom.nz/search"> 372<link rel="alternate" hreflang="en" href="https://theprintroom.nz/search"> 373<link rel="alternate" hreflang="en-AU" href="https://printroom.co/en-au/search"> 374<link rel="alternate" hreflang="en-CN" href="https://printroom.co/search"> 375<link rel="alternate" hreflang="en-FR" href="https://printroom.co/search"> 376<link rel="alternate" hreflang="en-GB" href="https://printroom.co/search"> 377<link rel="alternate" hreflang="en-US" href="https://printroom.co/search">
378<script async="async" src="/checkouts/internal/preloads.js?locale=en-US&default_configuration_id=488013894"></script>
378 379<link rel="preconnect" href="https://shop.app" crossorigin="anonymous">
380<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 380
380
381<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 381
381
382<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 382
382
383<script>var Shopify = Shopify || {}; 384Shopify.shop = "the-print-room.myshopify.com"; 385Shopify.locale = "en"; 386Shopify.currency = {"active":"USD","rate":"0.57265452"}; 387Shopify.country = "US"; 388Shopify.theme = {"name":"Print_Room_Co","id":151830298694,"schema_name":"Baseline","schema_version":"3.3.1","theme_store_id":null,"role":"main"}; 389Shopify.theme.handle = "null"; 390Shopify.theme.style = {"id":null,"handle":null}; 391Shopify.cdnHost = "printroom.co/cdn"; 392Shopify.routes = Shopify.routes || {}; 393Shopify.routes.root = "/"; 394Shopify.shopJsCdnBaseUrl = "https://cdn.shopify.com/shopifycloud/shop-js"; 395Shopify.SignInWithShop = Shopify.SignInWithShop || {}; 396Shopify.SignInWithShop.User = Shopify.SignInWithShop.User || {}; 397Shopify.SignInWithShop.User.recognized = false;</script>
vendor: 1 bytes, line 397
397
398<script type="module">!function(o){(o.Shopify=o.Shopify||{}).modules=!0}(window);</script>
vendor: 1 bytes, line 398
398
399<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 399
399
400<script> 401 window.ShopifyPay = window.ShopifyPay || {}; 402 window.ShopifyPay.apiHost = "shop.app\/pay"; 403 window.ShopifyPay.redirectState = null; 404</script>
vendor: 1 bytes, line 404
404
405<script> 406 window.Shopify = window.Shopify || {}; 407 window.Shopify.SignInWithShop = window.Shopify.SignInWithShop || {}; 408 window.Shopify.SignInWithShop.assetMetrics = { sampleRate: 0.25 }; 409 window.Shopify.SignInWithShop.eligible = true; 410</script>
vendor: 1 bytes, line 410
410
411<script id="shop-js-analytics" type="application/json">{"pageType":"search"}</script>
vendor: 1 bytes, line 411
411
412<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 412
412
413<script type="module"> 414 await import("https://cdn.shopify.com/shopifycloud/shop-js/modules/v2/loader.init-shop-cart-sync.en.esm.js"); 415 416 window.Shopify.SignInWithShop?.initShopCartSync?.({"fedCMEnabled":true,"windoidEnabled":true}); 417 418</script>
vendor: 1 bytes, line 418
418
419<script> 420 window.Shopify = window.Shopify || {}; 421 if (!window.Shopify.featureAssets) window.Shopify.featureAssets = {}; 422 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"]}; 423</script>
vendor: 1 bytes, line 423
423
424<script>(function() { 425 var isLoaded = false; 426 function asyncLoad() { 427 if (isLoaded) return; 428 isLoaded = true; 429 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"]; 430 for (var i = 0; i < urls.length; i++) { 431 var s = document.createElement('script'); 432 s.type = 'text/javascript'; 433 s.async = true; 434 s.src = urls[i]; 435 var x = document.getElementsByTagName('script')[0]; 436 x.parentNode.insertBefore(s, x); 437 } 438 }; 439 if(window.attachEvent) { 440 window.attachEvent('onload', asyncLoad); 441 } else { 442 window.addEventListener('load', asyncLoad, false); 443 } 444})();</script>
vendor: 1 bytes, line 444
444
445<script id="__st">var __st={"a":7054289,"offset":46800,"reqid":"18c727ce-3d91-45fa-8832-0f549c3f03a4-1791103102","pageurl":"printroom.co\/search","u":"0422feca5946","p":"searchresults"};</script>
vendor: 1 bytes, line 445
445
446<script>window.ShopifyPaypalV4VisibilityTracking = true;</script>
vendor: 1 bytes, line 446
446
447<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 447
447
448<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 448
448
449<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>
449<script crossorigin="anonymous" defer="defer" src="//printroom.co/cdn/shopifycloud/storefront/assets/shopify_pay/storefront-616277c7.js?v=20250812"></script>
vendor: 1 bytes, line 449
449
450<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 450
450
451<script> 452 window.Shopify = window.Shopify || {}; 453 window.Shopify.MCP = window.Shopify.MCP || {}; 454 window.Shopify.MCP.enabled = true; 455 window.Shopify.MCP.shop = "the-print-room.myshopify.com"; 456 window.Shopify.MCP.mcpEndpoint = "https:\/\/printroom.co\/api\/mcp"; 457 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"]}}]; 458</script>
vendor: 1 bytes, line 458
458
459<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=");})(); 460</script>
vendor: 1 bytes, line 460
460
461<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)}}; 462</script>
vendor: 1 bytes, line 462
462
463<script data-source-attribution="shopify.dynamic_checkout.buyer_consent"> 464 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); 465</script>
vendor: 1 bytes, line 465
465
466<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})}})); 467</script>
467 468<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"> 469<style id="shopify-accelerated-checkout-cart"> 470 #shopify-buyer-consent { 471 margin-top: 1em; 472 display: inline-block; 473 width: 100%; 474} 475 476#shopify-buyer-consent.hidden { 477 display: none; 478} 479 480#shopify-subscription-policy-button { 481 background: none; 482 border: none; 483 padding: 0; 484 text-decoration: underline; 485 font-size: inherit; 486 cursor: pointer; 487} 488 489#shopify-subscription-policy-button::before { 490 box-shadow: none; 491} 492 493 </style> 494
495<script id="shopify-cfh-end">window.performance && window.performance.mark && window.performance.mark('shopify.content_for_header.end');</script>
495 496 497 498 499 500 <link 501 rel="preload" 502 as="font" 503 href="//printroom.co/cdn/fonts/dm_sans/dmsans_n5.8a0f1984c77eb7186ceb87c4da2173ff65eb012e.woff2" 504 type="font/woff2" 505 crossorigin 506 > 507 508 509 510 <link 511 rel="preload" 512 as="font" 513 href="//printroom.co/cdn/fonts/dm_sans/dmsans_n4.ec80bd4dd7e1a334c969c265873491ae56018d72.woff2" 514 type="font/woff2" 515 crossorigin 516 > 517 518 519 520<style data-shopify> 521 @font-face { 522 font-family: "DM Sans"; 523 font-weight: 400; 524 font-style: normal; 525 font-display: swap; 526 src: url("//printroom.co/cdn/fonts/dm_sans/dmsans_n4.ec80bd4dd7e1a334c969c265873491ae56018d72.woff2") format("woff2"), 527 url("//printroom.co/cdn/fonts/dm_sans/dmsans_n4.87bdd914d8a61247b911147ae68e754d695c58a6.woff") format("woff"); 528} 529 530 @font-face { 531 font-family: "DM Sans"; 532 font-weight: 500; 533 font-style: normal; 534 font-display: swap; 535 src: url("//printroom.co/cdn/fonts/dm_sans/dmsans_n5.8a0f1984c77eb7186ceb87c4da2173ff65eb012e.woff2") format("woff2"), 536 url("//printroom.co/cdn/fonts/dm_sans/dmsans_n5.9ad2e755a89e15b3d6c53259daad5fc9609888e6.woff") format("woff"); 537} 538 539@font-face { 540 font-family: "DM Sans"; 541 font-weight: 700; 542 font-style: normal; 543 font-display: swap; 544 src: url("//printroom.co/cdn/fonts/dm_sans/dmsans_n7.97e21d81502002291ea1de8aefb79170c6946ce5.woff2") format("woff2"), 545 url("//printroom.co/cdn/fonts/dm_sans/dmsans_n7.af5c214f5116410ca1d53a2090665620e78e2e1b.woff") format("woff"); 546} 547@font-face { 548 font-family: "DM Sans"; 549 font-weight: 400; 550 font-style: italic; 551 font-display: swap; 552 src: url("//printroom.co/cdn/fonts/dm_sans/dmsans_i4.b8fe05e69ee95d5a53155c346957d8cbf5081c1a.woff2") format("woff2"), 553 url("//printroom.co/cdn/fonts/dm_sans/dmsans_i4.403fe28ee2ea63e142575c0aa47684d65f8c23a0.woff") format("woff"); 554} 555@font-face { 556 font-family: "DM Sans"; 557 font-weight: 700; 558 font-style: italic; 559 font-display: swap; 560 src: url("//printroom.co/cdn/fonts/dm_sans/dmsans_i7.52b57f7d7342eb7255084623d98ab83fd96e7f9b.woff2") format("woff2"), 561 url("//printroom.co/cdn/fonts/dm_sans/dmsans_i7.d5e14ef18a1d4a8ce78a4187580b4eb1759c2eda.woff") format("woff"); 562} 563@font-face { 564 font-family: "DM Sans"; 565 font-weight: 700; 566 font-style: normal; 567 font-display: swap; 568 src: url("//printroom.co/cdn/fonts/dm_sans/dmsans_n7.97e21d81502002291ea1de8aefb79170c6946ce5.woff2") format("woff2"), 569 url("//printroom.co/cdn/fonts/dm_sans/dmsans_n7.af5c214f5116410ca1d53a2090665620e78e2e1b.woff") format("woff"); 570} 571</style> 572 573<style>:root { 574 575 --font-size-xs: 0.64rem; 576 --font-size-sm: 0.8rem; 577 --font-size-base: 1rem; 578 --font-size-lg: 1.25rem; 579 --font-size-xl: 1.563rem; 580 --font-size-2xl: 1.953rem; 581 --font-size-3xl: 2.441rem; 582 --font-size-4xl: 3.052rem; 583 --font-size-5xl: 3.815rem; 584 --font-size-6xl: 4.768rem; 585 --font-size-7xl: 5.96rem; 586 --font-size-8xl: 7.451rem; 587 --font-size-9xl: 9.313rem; 588 589 --type-scale-n-2: var(--font-size-xs); 590 --type-scale-n-1: var(--font-size-sm); 591 --type-scale-n0: var(--font-size-base); 592 --type-scale-n1: var(--font-size-lg); 593 --type-scale-n2: var(--font-size-xl); 594 --type-scale-n3: var(--font-size-2xl); 595 --type-scale-n4: var(--font-size-3xl); 596 --type-scale-n5: var(--font-size-4xl); 597 --type-scale-n6: var(--font-size-5xl); 598 --type-scale-n7: var(--font-size-6xl); 599 --type-scale-n8: var(--font-size-7xl); 600 --type-scale-n9: var(--font-size-8xl); 601 --type-scale-n10: var(--font-size-9xl); 602 603 --base-font-size: 93.75%; 604 --base-font-size-from-settings: 15; 605 --base-line-height: 1.2; 606 --heading-line-height: 1; 607 608 font-size: var(--base-font-size); 609 line-height: var(--base-line-height); 610 611 --heading-font-stack: "DM Sans", sans-serif; 612 --heading-font-weight: 500; 613 --heading-font-style: normal; 614 615 616 --body-font-stack: "DM Sans", sans-serif; 617 --body-font-weight: 400; 618 --body-font-bold: FontDrop; 619 --body-font-bold-italic: FontDrop; 620 621 --color-gridline: 30 35 38; 622 --gridline-width: 0px; 623 624 --text-border-width: 1px; 625 --checkbox-width: 1px; 626 627 --font-heading: "DM Sans", sans-serif; 628 --font-body: "DM Sans", sans-serif; 629 --font-body-weight: 400; 630 --font-body-style: normal; 631 --font-body-bold-weight: bold; 632 633 --heading-letterspacing: -0.025em; 634 --heading-capitalize: none; 635 --heading-decoration: none; 636 637 --standard-heading-size: var(--type-scale-n3); 638 --feature-heading-size: var(--type-scale-n4); 639 --secondary-heading-size: var(--type-scale-n2); 640 641 --body-copy-transform: none; 642 643 --wrapperWidth: 100vw; 644 --gutter: 0px; 645 --rowHeight: calc((var(--wrapperWidth) - (11 * var(--gutter))) / 12); 646 647 --global-scrolling-items-speed-multiplier: 1; 648 649 --add-to-cart-button-height: 44px; 650 --checkout-button-height: 44px; 651 652 --spacing: 1rem; 653 --spacing-double: 2rem; 654 --spacing-half: 0.5rem; 655 656 /* Equivalent to px-2 */ 657 --section-horizontal-spacing-mobile: 0.5rem; 658 /* Equivalent to px-4 */ 659 --section-horizontal-spacing-desktop: 1rem; 660 661 --section-horizontal-spacing: var(--section-horizontal-spacing-mobile); 662 663 --icon-thickness: 1.5; 664 665 /** 666 * Buttons 667 */ 668 --button-text-transform: none; 669 --button-after-content: '\00a0\2192'; 670 --button-border-radius: 9999px; 671 672 /** 673 * Links 674 */ 675 --links-bottom-border-width: var(--text-border-width); 676 --links-bottom-padding: 0.25rem; 677 --links-text-transform: none; 678 --links-after-content: '\00a0\2192'; 679 --links-before-content: '\2190\00a0'; 680 681 background-color: rgb(var(--color-scheme-background)); 682 color: rgb(var(--color-scheme-text)); 683 } 684 685 @media (min-width: 1024px) { 686 :root { 687 --standard-heading-size: var(--type-scale-n5); 688 --feature-heading-size: var(--type-scale-n6); 689 --secondary-heading-size: var(--type-scale-n3); 690 691 --section-horizontal-spacing: var(--section-horizontal-spacing-desktop); 692 } 693 } 694 695 :root, 696 697 [data-color-scheme="scheme1"] { 698 --color-scheme-text: 43 57 144; 699 --color-scheme-background: 255 255 255; 700 --color-scheme-accent: 248 250 244; 701 --color-scheme-accent-contrast: 43 57 144; 702 --color-scheme-secondary: 30 35 38; 703 } 704 705 [data-color-scheme="scheme2"] { 706 --color-scheme-text: 30 35 38; 707 --color-scheme-background: 241 255 165; 708 --color-scheme-accent: 194 194 194; 709 --color-scheme-accent-contrast: 30 35 38; 710 --color-scheme-secondary: 30 35 38; 711 } 712 713 [data-color-scheme="scheme3"] { 714 --color-scheme-text: 248 250 244; 715 --color-scheme-background: 43 57 144; 716 --color-scheme-accent: 248 250 244; 717 --color-scheme-accent-contrast: 241 255 165; 718 --color-scheme-secondary: 43 57 144; 719 } 720 721 [data-color-scheme="scheme4"] { 722 --color-scheme-text: 248 250 244; 723 --color-scheme-background: 30 35 38; 724 --color-scheme-accent: 248 250 244; 725 --color-scheme-accent-contrast: 30 35 38; 726 --color-scheme-secondary: 248 250 244; 727 } 728 729 [data-color-scheme="scheme5"] { 730 --color-scheme-text: 30 35 38; 731 --color-scheme-background: 255 255 255; 732 --color-scheme-accent: 30 35 38; 733 --color-scheme-accent-contrast: 255 255 255; 734 --color-scheme-secondary: 30 35 38; 735 } 736 737 [data-color-scheme="scheme-62a93d7b-1ea3-42af-a18d-30461b13240a"] { 738 --color-scheme-text: 255 255 255; 739 --color-scheme-background: 255 255 255; 740 --color-scheme-accent: 255 255 255; 741 --color-scheme-accent-contrast: 255 255 255; 742 --color-scheme-secondary: 255 255 255; 743 } 744 745 [data-color-scheme="scheme-7c315ead-1873-415d-a1a8-a7722419ef69"] { 746 --color-scheme-text: 43 57 144; 747 --color-scheme-background: 255 255 255; 748 --color-scheme-accent: 30 35 38; 749 --color-scheme-accent-contrast: 30 35 38; 750 --color-scheme-secondary: 30 35 38; 751 } 752 753 [data-color-scheme="scheme-6641fd8c-0fdd-4ed9-bd94-b490824d6125"] { 754 --color-scheme-text: 30 35 38; 755 --color-scheme-background: 72 127 249; 756 --color-scheme-accent: 248 250 244; 757 --color-scheme-accent-contrast: 30 35 38; 758 --color-scheme-secondary: 30 35 38; 759 } 760 761 762 [data-color-scheme] { 763 --payment-terms-background-color: rgb(var(--color-scheme-background)); 764 765 --button-color-border: var(--color-scheme-text); 766 --button-color-background: var(--color-scheme-accent); 767 --button-color-text: var(--color-scheme-accent-contrast); 768 --button-color-border-hover: var(--color-scheme-text); 769 --button-color-background-hover: var(--color-scheme-text); 770 --button-color-text-hover: var(--color-scheme-background); 771 } 772 773 ::selection { 774 background-color: rgb(var(--color-scheme-accent)); 775 color: rgb(var(--color-scheme-accent-contrast)); 776 } 777
778 @keyframes scrolling-items { 779 0% { 780 transform: translate3d(0, 0, 0); 781 } 782 783 100% { 784 transform: translate3d(-50%, 0, 0); 785 } 786 } 787</style> 788 789<style id="generated-critical-css"> 790image-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}} 791</style> 792<style id="manual-critical-css"> 793 html { 794 background-color: rgb(var(--color-primary-background)); 795 color: rgb(var(--color-primary-text)); 796 font-size: var(--base-font-size); 797 line-height: var(--base-line-height); 798 } 799 800 [x-cloak] { 801 display: none; 802 } 803 804 data-island { 805 display: block; 806 } 807 808 html.no-js [x-cloak].no-js-undo-cloak { 809 display: revert; 810 } 811 812 body { 813 display: flex; 814 flex-direction: column; 815 min-height: 100vh; 816 } 817 818 @media (min-width: 768px) { 819 [md\:undo-x-cloak-block] { 820 display: block; 821 } 822 } 823 824 @media (max-width: 767px) { 825 [max-md\:undo-x-cloak-block] { 826 display: block; 827 } 828 } 829</style> 830 831 <style> 832 :root { 833 /* ââ Colors ââ */ 834 --pr-blue: #2B3990; 835 --pr-blue-hover: #232e75; 836 --pr-bright-blue: #487FF9; /* matches product-page volume-pricing table */ 837 --pr-bright-blue-hover: #3D6CD4; 838 --pr-bright-blue-rgb: 72 127 249; 839 --pr-bright-blue-hover-rgb: 61 108 212; 840 --dusky-purple: #4B4D72; 841 --dusky-purple-hover: #3d3f5e; 842 --slider-green: #658a6a; 843 --off-white: #FBFBF6; 844 --pill-bg: #EEE; 845 --pill-bg-hover: #e2e2e2; 846 --cant-find-bg: #EFFE9C; 847 848 /* ââ Typography ââ */ 849 --font-family: 'DM Sans', sans-serif;
850 --title-modal-size: 2.75rem; /* 44px */ 851 --title-modal-tracking: -0.05em; /* -2.2px */ 852 --title-drawer-size: 41px; 853 --title-drawer-tracking: -2px; 854 --body-size: 0.9375rem; /* 15px */ 855 --label-size: 0.8125rem; /* 13px */ 856 --pill-font-size: 0.66rem; /* ~10.65px */ 857 --cta-font-size: 1.5rem; /* 24px */ 858 --submit-font-size: 1.5rem; /* 24px */ 859 --input-font-size: 0.875rem; /* 14px */ 860 861 /* ââ Borders ââ */ 862 --border-modal: 2px solid black; 863 --border-drawer-left: 2px solid black; 864 --border-pill: 0.666px solid black; 865 --border-input: 1px solid black; 866 --border-cta: 2px solid var(--dusky-purple); 867 --border-chip: 0.4px solid black; 868 869 /* ââ Radii ââ */ 870 --radius-modal: 27px; 871 --radius-pill: 9999px; 872 --radius-input: 9999px; 873 --radius-textarea: 10px; 874 --radius-submit: 50px; 875 --radius-cta: 40px; 876 --radius-chip: 24px; 877 --radius-popover: 16px; 878 879 /* ââ Shadows ââ */ 880 --shadow-modal: 0 4px 13px 2px rgba(0, 0, 0, 0.1); 881 --shadow-popover: 0 10px 25px rgba(0, 0, 0, 0.1); 882 --shadow-slider-thumb: 0 2px 6px rgba(0, 0, 0, 0.15); 883 --shadow-focus: 0 0 0 3px rgba(43, 57, 144, 0.1); 884 885 /* ââ Sizing ââ */ 886 --product-image-drawer: 90px; 887 --product-image-modal: 53px; 888 --pill-height: 23px; 889 --submit-height: 70px; 890 --submit-max-width: 351px; 891 --start-quote-height: 79px; 892 --input-min-height: 2.75rem; /* 44px */ 893 --slider-thumb-size: 24px; 894 --slider-track-height: 6px; 895 --cta-width: 153px; 896 --cta-height: 47px; 897 --chip-width: 90px; 898 --chip-height: 21px; 899 900 /* ââ Aliases (backward compat) ââ */ 901 --color-quote-accent: var(--pr-blue); 902 } 903</style> 904 905 906 <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'"> 907 <noscript><link rel="stylesheet" href="//printroom.co/cdn/shop/t/59/assets/base.bundle.css?v=77867960145098054751787098434"></noscript> 908 909 <link rel="preload" href="//printroom.co/cdn/shop/t/59/assets/styles.css?v=1691680456440492591789529106" as="style" onload="this.onload=null;this.rel='stylesheet'"> 910 <noscript><link rel="stylesheet" href="//printroom.co/cdn/shop/t/59/assets/styles.css?v=1691680456440492591789529106"></noscript> 911 912<meta property="og:site_name" content="The Print Room"> 913<meta property="og:locale" content="en"><meta property="og:locale:alternate" content="en_NZ"><meta property="og:url" content="https://printroom.co/search"><meta property="og:title" content=" 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928Shop at The Print Room 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944| The Print Room 945"> 946<meta property="og:type" content="website"> 947<meta property="og:description" content="Find it here at The Print Room"> 948<meta property="og:image" content="https://printroom.co/cdn/shop/files/PrintRoomNovember2024-13_507c1311-d6fa-40ae-ae11-a74b59c4faec.jpg?v=1753319129"> 949<meta 950 property="og:image:secure_url" 951 content="https://printroom.co/cdn/shop/files/PrintRoomNovember2024-13_507c1311-d6fa-40ae-ae11-a74b59c4faec.jpg?v=1753319129" 952 > 953 <meta property="og:image:width" content="2048"> 954 <meta property="og:image:height" content="1367"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content=" 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969Shop at The Print Room 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985| The Print Room 986"> 987<meta name="twitter:description" content="Find it here at The Print Room">
988<script> 989 window.THEMENAME = 'Baseline'; 990 window.THEMEVERSION = '3.0.0'; 991 992 document.documentElement.className = document.documentElement.className.replace('no-js', 'js'); 993 994 function debounce(fn, wait) { 995 let t; 996 return (...args) => { 997 clearTimeout(t); 998 t = setTimeout(() => fn.apply(this, args), wait); 999 }; 1000 } 1001 1002 window.theme = { 1003 strings: { 1004 loading: "Loading", 1005 itemCountOne: "{{ count }} item", 1006 itemCountOther: "{{ count }} items", 1007 addToCart: "Add to cart", 1008 soldOut: "Sold out", 1009 unavailable: "Unavailable", 1010 regularPrice: "Regular price", 1011 salePrice: "Sale price", 1012 sale: "Sale", 1013 unitPrice: "Unit price", 1014 unitPriceSeparator: "per", 1015 cartEmpty: "Your cart is currently empty.", 1016 cartCookies: "Enable cookies to use the shopping cart", 1017 update: "Update", 1018 quantity: "Quantity", 1019 discountedTotal: "Discounted total", 1020 regularTotal: "Regular total", 1021 priceColumn: "See Price column for discount details.", 1022 addedToCart: "Added to Cart!", 1023 cartError: "There was an error while updating your cart. Please try again.", 1024 cartAddError: "All {{ title }} are in your cart.", 1025 shippingCalculatorResultsTitleOne: "There is 1 rate:",
1026 shippingCalculatorResultsTitleMany: "There are {{ count }} rates:", 1027 }, 1028 routes: { 1029 root_url: "\/", 1030 predictive_search_url: "\/search\/suggest", 1031 cart_url: "\/cart", 1032 cart_add_url: "\/cart\/add", 1033 cart_change_url: "\/cart\/change", 1034 cart_update_url: "\/cart\/update", 1035 cart_clear_url: "\/cart\/clear", 1036 }, 1037 moneyFormat: "${{amount}}", 1038 moneyWithCurrencyFormat: "${{amount}} USD", 1039 get defaultMoneyFormat() { 1040 return this.moneyFormat; 1041 }, 1042 cartItemCount: 0, 1043 settings: { 1044 cartType: "page", 1045 openDrawerOnAddToCart: false 1046 }, 1047 info: { 1048 name: 'Baseline', 1049 } 1050 }; 1051</script>
vendor: 1 bytes, line 1051
1051
1052<script src="//printroom.co/cdn/shop/t/59/assets/utils.js?v=84782252304122448471787098437" defer></script>
1052 1053
1053<script src="//printroom.co/cdn/shop/t/59/assets/images.js?v=56710371490645595961787098434" defer></script>
1053 1054
1054<script> 1055 window.themeEventsDebugMode = false; 1056 </script>
1056 1057
1057<script src="//printroom.co/cdn/shop/t/59/assets/theme-events.js?v=133344252210966700221787098437" defer></script>
1057 1058 1059 1060 1061 1062 1063 <!-- "snippets/shogun-head.liquid" was not rendered, the associated app was uninstalled --> 1064
1064<script type="text/javascript"> 1065window.PunchoutSettings = { 1066 "cloud_url": "https://cloud.punchoutexpress.com", 1067 "token": "ba56ba1530c75285dc7e1f854b4ad1a1", 1068 "checkout_selector": "#main-cart-footer div.items-center", 1069 "checkout_text": "Transfer Cart", 1070 "cancel_selector": "#main-cart-footer div.items-center", 1071 "cancel_text": "Cancel", 1072 "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", 1073 "cart_container_selector": "#CartContainer,#CartDrawer,#ajaxifyModal" 1074 }; 1075</script>
1075 1076 1077 <!-- Punchout Cloud -->
1078<script src="https://cdn.cloud.punchoutexpress.com/cloud/assets-shopify/0.2.0/punchout.min.js?v5_24_0" defer="defer"></script>
1078 1079<style type="text/css">.btn-punchout-cancel {margin-left: 10px;}</style> 1080<!-- /Punchout Cloud --> 1081 1082 1083
1084<script> 1085(function() { 1086 console.log('[TWOA Punchout] Script loaded'); 1087 1088 // Check if we're on the Te Wananga page and Locksmith is present 1089 const isTWOAPage = window.location.pathname.includes('te-wananga-o-aotearoa'); 1090 console.log('[TWOA Punchout] Is TWOA page:', isTWOAPage); 1091 console.log('[TWOA Punchout] Current path:', window.location.pathname); 1092 1093 if (isTWOAPage) { 1094 // Check if punchout session is already active 1095 const urlParams = new URLSearchParams(window.location.search); 1096 const hasPunchoutSession = urlParams.has('punchout_sess_id'); 1097 console.log('[TWOA Punchout] Has punchout session:', hasPunchoutSession); 1098 1099 if (!hasPunchoutSession) { 1100 console.log('[TWOA Punchout] No punchout session detected, will auto-activate'); 1101 1102 // Wait for page to fully load, then activate punchout 1103 window.addEventListener('load', function() { 1104 // Check if there's a Locksmith password form visible 1105 const hasPasswordForm = document.querySelector('form[data-locksmith-form], input[type="password"][name*="lock"]'); 1106 1107 console.log('[TWOA Punchout] Page loaded - Has password form:', !!hasPasswordForm); 1108 1109 if (!hasPasswordForm) { 1110 // No password form = user has access, activate punchout immediately 1111 console.log('[TWOA Punchout] â Access granted - activating punchout session'); 1112 const punchoutId = Date.now().toString() + Math.random().toString(36).substring(2, 15); 1113 const newUrl = new URL(window.location.href); 1114 newUrl.searchParams.set('punchout_sess_id', punchoutId); 1115 1116 // Store in sessionStorage to persist across page navigation 1117 sessionStorage.setItem('twoa_punchout_active', 'true'); 1118 sessionStorage.setItem('twoa_punchout_id', punchoutId); 1119 console.log('[TWOA Punchout] Session ID:', punchoutId); 1120 1121 // Redirect with punchout parameter 1122 console.log('[TWOA Punchout] Redirecting to:', newUrl.toString()); 1123 window.location.href = newUrl.toString(); 1124 } else { 1125 console.log('[TWOA Punchout] Password form detected, waiting for login...'); 1126 1127 // Watch for form submission / successful login 1128 const checkForAccess = setInterval(function() { 1129 const formStillVisible = document.querySelector('form[data-locksmith-form], input[type="password"][name*="lock"]'); 1130 1131 if (!formStillVisible) { 1132 console.log('[TWOA Punchout] â Password form disappeared - activating punchout'); 1133 clearInterval(checkForAccess); 1134 1135 const punchoutId = Date.now().toString() + Math.random().toString(36).substring(2, 15); 1136 sessionStorage.setItem('twoa_punchout_active', 'true'); 1137 sessionStorage.setItem('twoa_punchout_id', punchoutId); 1138 1139 const newUrl = new URL(window.location.href); 1140 newUrl.searchParams.set('punchout_sess_id', punchoutId); 1141 window.location.href = newUrl.toString(); 1142 } 1143 }, 500); 1144 1145 // Stop after 30 seconds 1146 setTimeout(() => clearInterval(checkForAccess), 30000); 1147 } 1148 }); 1149 } else { 1150 // If punchout is already active, store it in session 1151 console.log('[TWOA Punchout] Punchout already active, storing in session'); 1152 sessionStorage.setItem('twoa_punchout_active', 'true'); 1153 sessionStorage.setItem('twoa_punchout_id', urlParams.get('punchout_sess_id')); 1154 } 1155 } 1156 1157 // Apply punchout session to all pages if Te Wananga session is active 1158 const storedPunchoutActive = sessionStorage.getItem('twoa_punchout_active'); 1159 const storedPunchoutId = sessionStorage.getItem('twoa_punchout_id'); 1160 console.log('[TWOA Punchout] Session storage - Active:', storedPunchoutActive, 'ID:', storedPunchoutId); 1161 1162 if (storedPunchoutActive === 'true' && storedPunchoutId) { 1163 const urlParams = new URLSearchParams(window.location.search); 1164 if (!urlParams.has('punchout_sess_id')) { 1165 console.log('[TWOA Punchout] Applying stored punchout session to current page'); 1166 const newUrl = new URL(window.location.href); 1167 newUrl.searchParams.set('punchout_sess_id', storedPunchoutId); 1168 window.history.replaceState({}, '', newUrl.toString()); 1169 console.log('[TWOA Punchout] URL updated:', newUrl.toString()); 1170 1171 // Reinitialize punchout if the script is loaded 1172 if (window.PunchoutCloud && window.PunchoutCloud.init) { 1173 console.log('[TWOA Punchout] Reinitializing PunchoutCloud'); 1174 window.PunchoutCloud.init(); 1175 } 1176 } 1177 } 1178})(); 1179</script>
1179 1180 1181<!-- BEGIN app block: shopify://apps/one-tree-planted/blocks/index/1cbac389-d687-4afb-9e8a-26b6535fa1c2 -->
1181<script src="https://cdn.shopify.com/extensions/01a0f89b-d3f4-7fbc-a0d8-5474ae165888/reforestation-app-16/assets/script.js" defer></script>
1181 1182<!-- END app block -->
1182<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>
1182 1183<link href="https://monorail-edge.shopifysvc.com" rel="dns-prefetch">
1184<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: "search"};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 1184
1184
1185<script> 1186 window.__TREKKIE_SHIM_QUEUE = window.__TREKKIE_SHIM_QUEUE || []; 1187</script>
vendor: 1 bytes, line 1187
1187
1188<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}
1188).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"}
1188,{"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":"86469376-1484-4bac-adc3-19ddf07d7df6","pageType":"searchresults","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\",{}],[\"search_submitted\",{\"searchResult\":{\"query\":\"\",\"productVariants\":[]}}]]"});})();</script>
1188<script> 1189 window.ShopifyAnalytics = window.ShopifyAnalytics || {}; 1190 window.ShopifyAnalytics.meta = window.ShopifyAnalytics.meta || {}; 1191 window.ShopifyAnalytics.meta.currency = 'USD'; 1192 var meta = {"products":[],"page":{"pageType":"searchresults","requestId":"18c727ce-3d91-45fa-8832-0f549c3f03a4-1791103102"}}; 1193 for (var attr in meta) { 1194 window.ShopifyAnalytics.meta[attr] = meta[attr]; 1195 } 1196</script>
vendor: 1 bytes, line 1196
1196
1197<script class="analytics"> 1198 (function () { 1199 var customDocumentWrite = function(content) { 1200 var jquery = null; 1201 1202 if (window.jQuery) { 1203 jquery = window.jQuery; 1204 } else if (window.Checkout && window.Checkout.$) { 1205 jquery = window.Checkout.$; 1206 } 1207 1208 if (jquery) { 1209 jquery('body').append(content); 1210 } 1211 }; 1212 1213 var hasLoggedConversion = function(token) { 1214 if (token) { 1215 return document.cookie.indexOf('loggedConversion=' + token) !== -1; 1216 } 1217 return false; 1218 } 1219 1220 var setCookieIfConversion = function(token) { 1221 if (token) { 1222 var twoMonthsFromNow = new Date(Date.now()); 1223 twoMonthsFromNow.setMonth(twoMonthsFromNow.getMonth() + 2); 1224 1225 document.cookie = 'loggedConversion=' + token + '; expires=' + twoMonthsFromNow; 1226 } 1227 } 1228 1229 var trekkie = window.ShopifyAnalytics.lib = window.trekkie = window.trekkie || []; 1230 window.ShopifyAnalytics.lib.trekkie = window.trekkie; 1231 if (trekkie.integrations) { 1232 return; 1233 } 1234 trekkie.methods = [ 1235 'identify', 1236 'page', 1237 'ready', 1238 'track', 1239 'trackForm', 1240 'trackLink' 1241 ]; 1242 trekkie.factory = function(method) { 1243 return function() { 1244 var args = Array.prototype.slice.call(arguments); 1245 args.unshift(method); 1246 trekkie.push(args); 1247 if (method == 'track' || method == 'page') { 1248 var pageUrl; 1249 try { 1250 pageUrl = window.location.href; 1251 } catch (e) {} 1252 var pageReferrer; 1253 try { 1254 pageReferrer = document.referrer; 1255 } catch (e) {} 1256 try { 1257 if (window.__TREKKIE_SHIM_QUEUE == null) { 1258 window.__TREKKIE_SHIM_QUEUE = []; 1259 } 1260 window.__TREKKIE_SHIM_QUEUE.push({ 1261 from: 'trekkie-stub', 1262 method: method, 1263 args: args.slice(1), 1264 pageContext: { 1265 url: pageUrl, 1266 referrer: pageReferrer 1267 } 1268 }); 1269 } catch (e) { 1270 // no-op 1271 } 1272 } 1273 return trekkie; 1274 }; 1275 }; 1276 for (var i = 0; i < trekkie.methods.length; i++) { 1277 var key = trekkie.methods[i]; 1278 trekkie[key] = trekkie.factory(key); 1279 } 1280 trekkie.load = function(config) { 1281 trekkie.config = config || {}; 1282 trekkie.config.initialDocumentCookie = document.cookie; 1283 var first = document.getElementsByTagName('script')[0]; 1284var script = document.createElement('script'); 1285script.type = 'text/javascript'; 1286script.onerror = function(e) { 1287 var scriptFallback = document.createElement('script'); 1288 scriptFallback.type = 'text/javascript'; 1289 scriptFallback.onerror = function(error) { 1290 var Monorail = { 1291 produce: function produce(monorailDomain, schemaId, payload) { 1292 var currentMs = new Date().getTime(); 1293 var event = { 1294 schema_id: schemaId, 1295 payload: payload, 1296 metadata: { 1297 event_created_at_ms: currentMs, 1298 event_sent_at_ms: currentMs 1299 } 1300 }; 1301 return Monorail.sendRequest("https://" + monorailDomain + "/v1/produce", JSON.stringify(event)); 1302 }, 1303 sendRequest: function sendRequest(endpointUrl, payload) { 1304 // Try the sendBeacon API 1305 if (window && window.navigator && typeof window.navigator.sendBeacon === 'function' && typeof window.Blob === 'function' && !Monorail.isIos12()) { 1306 var blobData = new window.Blob([payload], { 1307 type: 'text/plain' 1308 }); 1309 1310 if (window.navigator.sendBeacon(endpointUrl, blobData)) { 1311 return true; 1312 } // sendBeacon was not successful 1313 1314 } // XHR beacon 1315 1316 var xhr = new XMLHttpRequest(); 1317 1318 try { 1319 xhr.open('POST', endpointUrl); 1320 xhr.setRequestHeader('Content-Type', 'text/plain'); 1321 xhr.send(payload); 1322 } catch (e) { 1323 console.log(e); 1324 } 1325 1326 return false; 1327 }, 1328 isIos12: function isIos12() { 1329 return window.navigator.userAgent.lastIndexOf('iPhone; CPU iPhone OS 12_') !== -1 || window.navigator.userAgent.lastIndexOf('iPad; CPU OS 12_') !== -1; 1330 } 1331 }; 1332 Monorail.produce('monorail-edge.shopifysvc.com', 1333 'trekkie_storefront_load_errors/1.1', 1334 {shop_id: 7054289, 1335 theme_id: 151830298694, 1336 app_name: "storefront", 1337 context_url: window.location.href, 1338 source_url: "//printroom.co/cdn/s/trekkie.storefront.2f6d7d7ede7d24234881a9cd5f47e679642fa1f6.min.js"}); 1339 1340 }; 1341 scriptFallback.async = true; 1342 scriptFallback.src = '//printroom.co/cdn/s/trekkie.storefront.2f6d7d7ede7d24234881a9cd5f47e679642fa1f6.min.js'; 1343 first.parentNode.insertBefore(scriptFallback, first); 1344}; 1345script.async = true; 1346script.src = '//printroom.co/cdn/s/trekkie.storefront.2f6d7d7ede7d24234881a9cd5f47e679642fa1f6.min.js'; 1347first.parentNode.insertBefore(script, first); 1348 1349 }; 1350 trekkie.load( 1351 {"Trekkie":{"appName":"storefront","development":false,"defaultAttributes":{"shopId":7054289,"isMerchantRequest":null,"themeId":151830298694,"themeCityHash":"18288446332362764096","contentLanguage":"en","currency":"USD","eventMetadataId":"86469376-1484-4bac-adc3-19ddf07d7df6"},"isServerSideCookieWritingEnabled":true,"monorailRegion":"shop_domain","enabledBetaFlags":["764d78cb","8450a54b","7ee89bf1","4c64608a"]},"Session Attribution":{},"S2S":{"facebookCapiEnabled":false,"source":"trekkie-storefront-renderer","apiClientId":580111}} 1352 ); 1353 1354 var loaded = false;
1355 trekkie.ready(function() { 1356 if (loaded) return; 1357 loaded = true; 1358 1359 window.ShopifyAnalytics.lib = window.trekkie; 1360 1361 var originalDocumentWrite = document.write; 1362 document.write = customDocumentWrite; 1363 try { window.ShopifyAnalytics.merchantGoogleAnalytics.call(this); } catch(error) {}; 1364 document.write = originalDocumentWrite; 1365 1366 var match = window.location.pathname.match(/checkouts\/(.+)\/(thank_you|post_purchase)/) 1367 var token = match? match[1]: undefined; 1368 if (!hasLoggedConversion(token)) { 1369 setCookieIfConversion(token); 1370 window.ShopifyAnalytics.lib.track("Performed Search",{"query":null},undefined,undefined,{"shopifyEmitted":true}); 1371 } 1372 }); 1373 1374 window.ShopifyAnalytics.lib.page(null,{"pageType":"searchresults","requestId":"18c727ce-3d91-45fa-8832-0f549c3f03a4-1791103102","shopifyEmitted":true}); 1375 1376 var eventsListenerScript = document.createElement('script'); 1377 eventsListenerScript.async = true; 1378 eventsListenerScript.src = "//printroom.co/cdn/shopifycloud/storefront/assets/shop_events_listener-4e26a9ce.js"; 1379 document.getElementsByTagName('head')[0].appendChild(eventsListenerScript); 1380})();</script>
1380 1381
1381<script> 1382 if (!window.ga || (window.ga && typeof window.ga !== 'function')) { 1383 window.ga = function ga() { 1384 (window.ga.q = window.ga.q || []).push(arguments); 1385 if (window.Shopify && window.Shopify.analytics && typeof window.Shopify.analytics.publish === 'function') { 1386 window.Shopify.analytics.publish("ga_stub_called", {}, {sendTo: "google_osp_migration"}); 1387 } 1388 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."); 1389 }; 1390 if (window.Shopify && window.Shopify.analytics && typeof window.Shopify.analytics.publish === 'function') { 1391 window.Shopify.analytics.publish("ga_stub_initialized", {}, {sendTo: "google_osp_migration"}); 1392 } 1393 } 1394</script>
vendor: 1 bytes, line 1394
1394
1395<script 1396 defer 1397 src="https://printroom.co/cdn/shopifycloud/perf-kit/shopify-perf-kit-3.9.4.min.js" 1398 data-application="storefront-renderer" 1399 data-shop-id="7054289" 1400 data-render-region="gcp-us-central1" 1401 data-page-type="search" 1402 data-theme-instance-id="151830298694" 1403 data-theme-name="Baseline" 1404 data-theme-version="3.3.1" 1405 data-monorail-region="shop_domain" 1406 data-resource-timing-sampling-rate="10" 1407 data-shs="true" 1408 data-shs-beacon="true" 1409 data-shs-export-with-fetch="true" 1410 data-shs-logs-sample-rate="1" 1411 data-shs-beacon-endpoint="https://printroom.co/api/collect" 1412></script>
1412 1413<meta name="shopify-y" content="e4426a17-5781-4221-b0ff-7ddfa46cfe08" data-expiration="1822660702000"><meta name="shopify-s" content="b0f24b04-0196-4b09-9a3c-a9fdf7157950" data-expiration="1791104902000"><meta name="new-cookie-storage-activated" content="t"> 1414</head> 1415 1416 <body> 1417<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-W9DFFGB" 1418 height="0" width="0" style="display:none;visibility:hidden" title="gtm"></iframe></noscript> 1419 1420 <a class="skip-link" href="#MainContent">Skip to content</a> 1421 1422 <!-- BEGIN sections: header-group --> 1423<div id="shopify-section-sections--21296457187398__geo_market_banner" class="shopify-section shopify-section-group-header-group contents"> 1424 <style data-shopify> 1425 #shopify-section-sections--21296457187398__geo_market_banner [data-geo-market-banner] { 1426 position: sticky; 1427 top: 0; 1428 left: 0; 1429 right: 0; 1430 z-index: 40; 1431 display: block; 1432 width: 100%; 1433 padding: 0; 1434 border-bottom: 1px solid rgba(248, 250, 244, 0.18); 1435 background: #2b3990; 1436 color: #f8faf4; 1437 box-shadow: 0 14px 30px rgba(19, 27, 68, 0.18); 1438 pointer-events: auto; 1439 } 1440 1441 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__inner { 1442 display: grid; 1443 grid-template-columns: minmax(0, 1fr) auto; 1444 align-items: center; 1445 gap: 1rem 1.5rem; 1446 padding: 0.95rem var(--section-horizontal-spacing); 1447 } 1448 1449 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__message { 1450 margin: 0; 1451 max-width: 48rem; 1452 color: inherit; 1453 font-family: var(--font-body); 1454 font-size: var(--font-size-base); 1455 font-style: var(--font-body-style); 1456 font-weight: 500; 1457 letter-spacing: -0.01em; 1458 line-height: 1.45; 1459 } 1460 1461 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__actions { 1462 display: flex; 1463 flex-wrap: wrap; 1464 align-items: center; 1465 justify-content: flex-end; 1466 gap: 0.75rem; 1467 justify-self: end; 1468 } 1469 1470 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__button, 1471 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss { 1472 display: inline-flex; 1473 min-height: 2.875rem; 1474 align-items: center; 1475 justify-content: center; 1476 gap: 0.45rem; 1477 border-style: solid; 1478 border-width: var(--text-border-width); 1479 border-radius: var(--button-border-radius); 1480 font-family: var(--font-body); 1481 font-size: var(--font-size-base); 1482 font-style: var(--font-body-style); 1483 font-weight: 600; 1484 line-height: 1; 1485 text-decoration: none; 1486 text-transform: var(--button-text-transform); 1487 white-space: nowrap; 1488 transition: 1489 transform 0.18s ease, 1490 box-shadow 0.18s ease, 1491 background-color 0.18s ease, 1492 border-color 0.18s ease, 1493 color 0.18s ease, 1494 opacity 0.18s ease; 1495 } 1496 1497 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__button { 1498 padding: 0.8rem 1.35rem; 1499 border: 1px solid rgba(255, 255, 255, 0.12); 1500 background: #fbfbf6; 1501 box-shadow: 0 12px 24px rgba(14, 21, 52, 0.14); 1502 color: #2b3990; 1503 } 1504 1505 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss { 1506 padding: 0.8rem 1rem; 1507 border-color: rgba(248, 250, 244, 0.32); 1508 background: rgba(248, 250, 244, 0.08); 1509 box-shadow: none; 1510 color: inherit; 1511 opacity: 0.96; 1512 } 1513 1514 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss-icon { 1515 font-size: 0.95rem; 1516 line-height: 1; 1517 } 1518 1519 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__button:focus-visible, 1520 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss:focus-visible { 1521 outline: 2px solid #f8faf4; 1522 outline-offset: 2px; 1523 } 1524 1525 @media (hover: hover) and (pointer: fine) { 1526 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__button:hover, 1527 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss:hover { 1528 transform: translateY(-1px); 1529 } 1530 1531 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__button:hover { 1532 background: #ffffff; 1533 box-shadow: 0 16px 30px rgba(14, 21, 52, 0.18); 1534 } 1535 1536 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss:hover { 1537 border-color: rgba(248, 250, 244, 0.56); 1538 background: rgba(248, 250, 244, 0.16); 1539 opacity: 1; 1540 } 1541 } 1542 1543 @media (max-width: 767px) { 1544 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__inner { 1545 grid-template-columns: 1fr; 1546 align-items: stretch; 1547 gap: 0.9rem; 1548 } 1549 1550 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__message { 1551 max-width: none; 1552 } 1553 1554 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__actions { 1555 width: 100%; 1556 display: grid; 1557 grid-template-columns: 1fr; 1558 justify-content: stretch; 1559 justify-self: stretch; 1560 } 1561 1562 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__button { 1563 width: 100%; 1564 } 1565 1566 #shopify-section-sections--21296457187398__geo_market_banner .geo-market-banner__dismiss { 1567 justify-self: start; 1568 } 1569 } 1570 </style> 1571 1572 <data-island 1573 data-color-scheme="scheme3" 1574 x-data="GeoMarketBanner({ 1575 enabled: true, 1576 nzTargetUrl: "https:\/\/theprintroom.nz", 1577 intlTargetUrl: "https:\/\/printroom.co", 1578 auTargetUrl: "https:\/\/www.printroom.co\/en-au", 1579 messages: { 1580 fromInternational: "You're on our international site.", 1581 fromNz: "You're on our New Zealand site.", 1582 fromAu: "You're on our Australia site.", 1583 switchToNz: "Switch to New Zealand", 1584 switchToAu: "Switch to Australia", 1585 switchToInternational: "Switch to international",
1586 dismiss: "Dismiss" 1587 } 1588 })" 1589 role="region" 1590 aria-label="Regional site selector" 1591 x-show="shown" 1592 x-transition:enter="transition duration-300 motion-reduce:duration-0 outline-0" 1593 x-transition:enter-start="-translate-y-full" 1594 x-transition:enter-end="translate-y-0" 1595 x-transition:leave="transition duration-200 motion-reduce:duration-0 outline-0" 1596 x-transition:leave-start="translate-y-0" 1597 x-transition:leave-end="-translate-y-full" 1598 @keydown.escape.window="dismiss" 1599 id="sections--21296457187398__geo_market_banner" 1600 data-geo-market-banner 1601 style="display: none;" 1602 on="idle" 1603 src="//printroom.co/cdn/shop/t/59/assets/island-geo-market-banner.bundle.js?v=76971093760605141431787098434" 1604 > 1605 <div class="geo-market-banner__inner"> 1606 <p class="geo-market-banner__message"> 1607 <span x-text="message"></span> 1608 </p> 1609 <div class="geo-market-banner__actions"> 1610 <a 1611 class="geo-market-banner__button" 1612 :href="targetUrl" 1613 x-text="ctaLabel" 1614 @click="acceptSwitch($event)" 1615 ></a> 1616 <button 1617 class="geo-market-banner__dismiss" 1618 type="button" 1619 @click="dismiss" 1620 :aria-label="dismissLabel" 1621 > 1622 <span x-text="dismissLabel"></span> 1623 <span class="geo-market-banner__dismiss-icon" aria-hidden="true">Ã</span> 1624 </button> 1625 </div> 1626 </div> 1627 </data-island> 1628 1629 1630 1631</div><div id="shopify-section-sections--21296457187398__header" class="shopify-section shopify-section-group-header-group section-header relative z-20"> 1632 1633 1634<style data-shopify> 1635 1636 #shopify-section-sections--21296457187398__header { 1637 position: sticky; 1638 top: 0; 1639 z-index: 30; 1640 } 1641 1642 :root { 1643 --sticky-header-height: 66px; 1644 } 1645 1646 1647 #shopify-section-sections--21296457187398__header { 1648 --logo-max-width: 80px; 1649 } 1650 @media (min-width: 1024px) { 1651 #shopify-section-sections--21296457187398__header { 1652 --logo-max-width: 90px; 1653 } 1654 } 1655</style> 1656 1657<data-island 1658 x-data="Header" 1659 class="block" 1660 :class="{ 'is-stuck' : isStuck }" 1661 1662 data-sticky="true" 1663 1664 1665 data-color-scheme="scheme1" 1666 data-overlay-header-with-sticky="false" 1667 data-overlay-text-color-scheme="scheme1" 1668 id="sections--21296457187398__header" 1669 role="banner" 1670 data-theme-header 1671> 1672 1673 <sticky-header-height-helper hidden></sticky-header-height-helper> 1674 1675 <header 1676 x-ref="header" 1677 class="relative z-10 text-scheme-text header-glass" 1678 data-color-scheme="scheme1" 1679 > 1680 <nav 1681 class="relative hidden lg:block" 1682 aria-label="Primary" 1683 > 1684 <div class="flex items-stretch px-section-horizontal-spacing justify-between flex-wrap "> 1685 <div class="flex items-stretch"> 1686 1687 <div class="flex"> 1688 <a 1689 href="/" 1690 class="break-word my-auto inline-block py-4" 1691 > 1692 1693 1694 <div class="max-w-[var(--logo-max-width)]"> 1695 1696<img 1697 src="//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=90" 1698 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 1699 " 1700 width="543" 1701 height="397" 1702 loading="eager" 1703 1704 sizes="(min-width: 1024px) 90px, 80px" 1705 1706 alt="The Print Room" 1707 1708 > 1709 1710 1711 1712 </div> 1713 1714 1715 </a> 1716 </div> 1717 1718 1719 </div> 1720 1721 1722 1723 1724 1725 <a 1726 1727 class="flex py-4 relative self-stretch inline-flex flex-col" 1728 href="/collections/product-library" 1729 >
1730 <span class="m-auto inline-block">Products</span></a> 1731 1732 1733<data-island 1734 x-data="{ 1735 expanded: false, 1736 hoverTimeout: null, 1737 openDropdown() { 1738 clearTimeout(this.hoverTimeout); 1739 this.expanded = true; 1740 this.$nextTick(() => { 1741 const header = this.$el.closest('header'); 1742 const dd = this.$el.querySelector('.dropdown-glass'); 1743 if (header && dd) { 1744 header.style.setProperty('--dropdown-h', dd.offsetHeight + 'px'); 1745 } 1746 }); 1747 }, 1748 closeDropdown() { 1749 this.hoverTimeout = setTimeout(() => { 1750 this.expanded = false; 1751 }, 150); 1752 } 1753 }" 1754 @mouseenter="openDropdown()" 1755 @mouseleave="closeDropdown()" 1756 @focusin="openDropdown()" 1757 @focusout="if ($event.relatedTarget && !$el.contains($event.relatedTarget)) closeDropdown()" 1758 class="no-js-focus-wrapper flex self-stretch header-dropdown" 1759 1760 > 1761 <button 1762 class="inline-flex py-4 items-center header-menu-item" 1763 @click="expanded = !expanded" 1764 :aria-expanded="expanded ? true : 'false'" 1765 aria-controls="menu0" 1766 > 1767 <span class="inline-block pr-1">Services</span><span 1768 class="mr-1 inline-block h-3 w-3 origin-center align-middle" 1769 x-show="!expanded" 1770 ><svg 1771 class="theme-icon" 1772 xmlns="http://www.w3.org/2000/svg" 1773 fill="none" 1774 viewBox="0 0 24 24" 1775> 1776 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 1777</svg> 1778</span> 1779 <span 1780 class="mr-1 inline-block h-3 w-3 origin-center align-middle" 1781 x-show="expanded" 1782 style="display: none;" 1783 ><svg 1784 class="theme-icon" 1785 xmlns="http://www.w3.org/2000/svg" 1786 fill="none" 1787 viewBox="0 0 24 24" 1788> 1789 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 1790</svg> 1791</span></button> 1792 <div 1793 id="menu0" 1794 class="no-js-focus-container absolute top-full z-20 dropdown-glass text-scheme-text bottom-auto left-0 w-full" 1795 x-cloak 1796 x-show="expanded" 1797 x-transition:enter="transition ease-out duration-300 motion-reduce:duration-0" 1798 x-transition:enter-start="opacity-0 -translate-y-2 scale-[0.98]" 1799 x-transition:enter-end="opacity-100 translate-y-0 scale-100" 1800 x-transition:leave="transition ease-in duration-200 motion-reduce:duration-0" 1801 x-transition:leave-start="opacity-100 translate-y-0 scale-100" 1802 x-transition:leave-end="opacity-0 -translate-y-1 scale-[0.99]" 1803 style="transform-origin: top center;" 1804 data-color-scheme="" 1805 ><div class=" text-left"><div class="grid gap-gutter bg-gridline-color grid-cols-4"> 1806 1807 <div class="bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text"> 1808 <a 1809 1810 class="font-heading inline-block py-1" 1811 href="/pages/services" 1812 > 1813 Services 1814 </a> 1815 </div> 1816 1817 1818 1819 1820<div class="bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text"> 1821 <h2 class="font-heading mb-2"> 1822 1823 <a 1824 1825 class="inline-block py-1" 1826 href="/pages/product-capabilities" 1827 1828 > 1829 Production capabilities 1830 </a> 1831 1832 </h2> 1833 <ul><li class=""> 1834 <a 1835 1836 class="inline-block py-1" 1837 href="/pages/custom-manufactured" 1838 >Custom-manufactured</a> 1839 </li><li class=""> 1840 <a 1841 1842 class="inline-block py-1" 1843 href="/pages/screen-printing" 1844 >Screen printing</a> 1845 </li><li class=""> 1846 <a 1847 1848 class="inline-block py-1" 1849 href="/pages/embroidery" 1850 >Embroidery</a> 1851 </li><li class=""> 1852 <a 1853 1854 class="inline-block py-1" 1855 href="/pages/heat-transfers" 1856 >Heat transfers</a> 1857 </li><li class=""> 1858 <a 1859 1860 class="inline-block py-1" 1861 href="/pages/finishing" 1862 >Finishing</a> 1863 </li></ul> 1864 </div><div class="bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text"> 1865 <h2 class="font-heading mb-2"> 1866 1867 <a 1868 1869 class="inline-block py-1" 1870 href="/pages/partner-services" 1871 1872 > 1873 Partner services 1874 </a> 1875 1876 </h2> 1877 <ul><li class=""> 1878 <a 1879 1880 class="inline-block py-1" 1881 href="/pages/client-portal" 1882 >Client portal</a> 1883 </li><li class=""> 1884 <a 1885 1886 class="inline-block py-1" 1887 href="/pages/fundraising-pre-orders" 1888 >Fundraise & pre-order</a> 1889 </li><li class=""> 1890 <a 1891 1892 class="inline-block py-1" 1893 href="/pages/repurpose-initiative" 1894 >Repurpose initiative</a> 1895 </li></ul> 1896 </div><div class="bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text"> 1897 <h2 class="font-heading mb-2"> 1898 1899 <a 1900 1901 class="inline-block py-1" 1902 href="/pages/popular-services" 1903 1904 > 1905 Popular services 1906 </a> 1907 1908 </h2> 1909 <ul><li class=""> 1910 <a 1911 1912 class="inline-block py-1" 1913 href="/pages/school-leavers-gear" 1914 >School leavers gear</a> 1915 </li><li class=""> 1916 <a 1917 1918 class="inline-block py-1" 1919 href="/pages/tshirt-printing" 1920 >Custom t-shirt printing</a> 1921 </li></ul> 1922 </div> 1923</div></div></div> 1924 </data-island> 1925 1926 1927 1928 1929 <a 1930 1931 class="flex py-4 relative self-stretch inline-flex flex-col" 1932 href="/pages/responsibility" 1933 >
1934 <span class="m-auto inline-block">Responsibility</span></a> 1935 1936 1937<data-island 1938 x-data="{ 1939 expanded: false, 1940 hoverTimeout: null, 1941 openDropdown() { 1942 clearTimeout(this.hoverTimeout); 1943 this.expanded = true; 1944 this.$nextTick(() => { 1945 const header = this.$el.closest('header'); 1946 const dd = this.$el.querySelector('.dropdown-glass'); 1947 if (header && dd) { 1948 header.style.setProperty('--dropdown-h', dd.offsetHeight + 'px'); 1949 } 1950 }); 1951 }, 1952 closeDropdown() { 1953 this.hoverTimeout = setTimeout(() => { 1954 this.expanded = false; 1955 }, 150); 1956 } 1957 }" 1958 @mouseenter="openDropdown()" 1959 @mouseleave="closeDropdown()" 1960 @focusin="openDropdown()" 1961 @focusout="if ($event.relatedTarget && !$el.contains($event.relatedTarget)) closeDropdown()" 1962 class="no-js-focus-wrapper flex self-stretch header-dropdown" 1963 style="position: relative;" 1964 > 1965 <button 1966 class="inline-flex py-4 items-center header-menu-item" 1967 @click="expanded = !expanded" 1968 :aria-expanded="expanded ? true : 'false'" 1969 aria-controls="menu1" 1970 > 1971 <span class="inline-block pr-1">Our story</span><span 1972 class="mr-1 inline-block h-3 w-3 origin-center align-middle" 1973 x-show="!expanded" 1974 ><svg 1975 class="theme-icon" 1976 xmlns="http://www.w3.org/2000/svg" 1977 fill="none" 1978 viewBox="0 0 24 24" 1979> 1980 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 1981</svg> 1982</span> 1983 <span 1984 class="mr-1 inline-block h-3 w-3 origin-center align-middle" 1985 x-show="expanded" 1986 style="display: none;" 1987 ><svg 1988 class="theme-icon" 1989 xmlns="http://www.w3.org/2000/svg" 1990 fill="none" 1991 viewBox="0 0 24 24" 1992> 1993 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 1994</svg> 1995</span></button> 1996 <div 1997 id="menu1" 1998 class="no-js-focus-container absolute top-full z-20 dropdown-glass text-scheme-text gs-dropdown-content nav-dropdown-content" 1999 x-cloak 2000 x-show="expanded" 2001 x-transition:enter="transition ease-out duration-300 motion-reduce:duration-0" 2002 x-transition:enter-start="opacity-0 -translate-y-2 scale-[0.98]" 2003 x-transition:enter-end="opacity-100 translate-y-0 scale-100" 2004 x-transition:leave="transition ease-in duration-200 motion-reduce:duration-0" 2005 x-transition:leave-start="opacity-100 translate-y-0 scale-100" 2006 x-transition:leave-end="opacity-0 -translate-y-1 scale-[0.99]" 2007 style="transform-origin: top left;" 2008 data-color-scheme="" 2009 ><a 2010 href="/pages/in-good-company-with" 2011 2012 >In good company withâ¦</a><a 2013 href="/pages/about-print-room" 2014 2015 >Our origins</a></div> 2016 </data-island> 2017 2018<data-island 2019 x-data="{ 2020 expanded: false, 2021 hoverTimeout: null, 2022 openDropdown() { 2023 clearTimeout(this.hoverTimeout); 2024 this.expanded = true; 2025 this.$nextTick(() => { 2026 const header = this.$el.closest('header'); 2027 const dd = this.$el.querySelector('.dropdown-glass'); 2028 if (header && dd) { 2029 header.style.setProperty('--dropdown-h', dd.offsetHeight + 'px'); 2030 } 2031 }); 2032 }, 2033 closeDropdown() { 2034 this.hoverTimeout = setTimeout(() => { 2035 this.expanded = false; 2036 }, 150); 2037 } 2038 }" 2039 @mouseenter="openDropdown()" 2040 @mouseleave="closeDropdown()" 2041 @focusin="openDropdown()" 2042 @focusout="if ($event.relatedTarget && !$el.contains($event.relatedTarget)) closeDropdown()" 2043 class="no-js-focus-wrapper flex items-center self-stretch header-dropdown" 2044 style="position: relative;" 2045 > 2046 <button 2047 class="gs-pill" 2048 :class="{ 'is-active': expanded }" 2049 @click="expanded = !expanded" 2050 :aria-expanded="expanded ? 'true' : 'false'" 2051 >
2052 <span>Get started +</span> 2053 </button> 2054 <div 2055 class="no-js-focus-container absolute top-full z-20 dropdown-glass text-scheme-text gs-dropdown-content" 2056 x-cloak 2057 x-show="expanded" 2058 x-transition:enter="transition ease-out duration-300 motion-reduce:duration-0" 2059 x-transition:enter-start="opacity-0 -translate-y-2" 2060 x-transition:enter-end="opacity-100 translate-y-0" 2061 x-transition:leave="transition ease-in duration-200 motion-reduce:duration-0" 2062 x-transition:leave-start="opacity-100 translate-y-0" 2063 x-transition:leave-end="opacity-0 -translate-y-1" 2064 style="transform-origin: top left;" 2065 data-color-scheme="" 2066 ><a href="/collections/product-library">Start a project</a><a href="/pages/book-a-call">Book a call</a></div> 2067 </data-island> 2068 2069 2070<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="/search" /><div class="flex gap-4 justify-end max-lg:hidden"><div class="inline-block shrink-0 select-none"> 2071 <h2 class="sr-only" id="country-heading-header"> 2072 Country/region 2073 </h2> 2074 <data-island 2075 class="relative" 2076 x-data="{ expanded: false }" 2077 @keydown.escape.prevent.stop="expanded = false" 2078 @click.outside="expanded = false" 2079 > 2080 <button 2081 type="button" 2082 class="text-base py-4" 2083 :aria-expanded="expanded" 2084 aria-controls="country-list-header" 2085 aria-describedby="country-heading-header" 2086 @click.prevent="expanded = ! expanded" 2087 > 2088 United States (USD 2089 $) 2090 <span 2091 class="rotate ml-1 inline-block w-3 origin-center transform fill-current transition" 2092 :class="{ 'rotate-180': expanded }" 2093 > 2094 <svg 2095 class="theme-icon" 2096 xmlns="http://www.w3.org/2000/svg" 2097 fill="none" 2098 viewBox="0 0 24 24" 2099> 2100 <path stroke="currentColor" d="M1.5 7 12 17.5 22.5 7" vector-effect="non-scaling-stroke"/> 2101</svg> 2102 2103 </span> 2104 </button> 2105 <div 2106 class="absolute top-full left-0 right-auto" 2107 x-show="expanded" 2108 style="display: none;" 2109 > 2110 <ul 2111 id="country-list-header" 2112 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" 2113 x-transition:enter="transition ease duration-300" 2114 x-transition:enter-start="opacity-0" 2115 x-transition:enter-end="opacity-100" 2116 x-transition:leave="transition ease duration-300" 2117 x-transition:leave-start="opacity-100" 2118 x-transition:leave-end="opacity-0" 2119 :aria-hidden="! expanded" 2120 > 2121 2122 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2123 <button 2124 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2125 type="button" 2126 2127 @click.prevent="$refs.input.value = 'AU'; $root.closest('form').submit();" 2128 > 2129 <span class="border-transparent border-b-text">Australia (AUD 2130 $)</span 2131 > 2132 </button> 2133 </li> 2134 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2135 <button 2136 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2137 type="button" 2138 2139 @click.prevent="$refs.input.value = 'CN'; $root.closest('form').submit();" 2140 >
2141 <span class="border-transparent border-b-text">China (CNY 2142 Â¥)</span 2143 > 2144 </button> 2145 </li> 2146 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2147 <button 2148 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2149 type="button" 2150 2151 @click.prevent="$refs.input.value = 'FR'; $root.closest('form').submit();" 2152 > 2153 <span class="border-transparent border-b-text">France (EUR 2154 â¬)</span 2155 > 2156 </button> 2157 </li> 2158 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2159 <button 2160 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2161 type="button" 2162 2163 @click.prevent="$refs.input.value = 'NZ'; $root.closest('form').submit();" 2164 > 2165 <span class="border-transparent border-b-text">New Zealand (NZD 2166 $)</span 2167 > 2168 </button> 2169 </li> 2170 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2171 <button 2172 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2173 type="button" 2174 2175 @click.prevent="$refs.input.value = 'GB'; $root.closest('form').submit();" 2176 > 2177 <span class="border-transparent border-b-text">United Kingdom (GBP 2178 £)</span 2179 > 2180 </button> 2181 </li> 2182 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2183 <button 2184 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2185 type="button" 2186 2187 aria-current="true" 2188 2189 @click.prevent="$refs.input.value = 'US'; $root.closest('form').submit();" 2190 > 2191 <span class="border-scheme-text border-b-text">United States (USD 2192 $)</span 2193 > 2194 </button> 2195 </li></ul> 2196 </div> 2197 2198 <input 2199 x-ref="input" 2200 type="hidden" 2201 name="country_code" 2202 id="CountrySelector" 2203 value="US" 2204 > 2205 </data-island> 2206 </div></div></form></div> 2207 <div class="flex items-stretch whitespace-nowrap"> 2208 <data-island 2209 x-data="{ searchOpen: false }" 2210 class="contents" 2211> 2212 <a 2213 x-ref="searchToggle" 2214 @click.prevent="searchOpen = true" 2215 @keydown.space.prevent="searchOpen = true" 2216 class="inline-flex py-4 h-full" 2217 href="/search" 2218 :role="`button`" 2219 ><span class="sr-only">Search</span> 2220 <span class="my-auto inline-block h-6 w-6 align-middle"><svg 2221 class="theme-icon" 2222 xmlns="http://www.w3.org/2000/svg" 2223 fill="none" 2224 viewBox="0 0 24 24" 2225> 2226 <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"/> 2227</svg> 2228</span></a> 2229 2230 <data-island 2231 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" 2232 x-cloak 2233 x-show="searchOpen" 2234 x-transition:enter="ease duration-200" 2235 x-transition:enter-start="opacity-0" 2236 x-transition:enter-end="opacity-100" 2237 x-transition:leave="ease duration-200" 2238 x-transition:leave-start="opacity-100" 2239 x-transition:leave-end="opacity-0" 2240 2241 x-data="PredictiveSearch('product,collection,article,page,query')" 2242 x-trap.inert.noscroll="resultsOpen" 2243 @keyup="onKeyup" 2244 @keydown="onKeydown" 2245 @click.outside.prevent="close()" 2246 @keyup.escape.prevent.stop="close(true, $refs.searchToggle)" 2247 @focusin.window="( searchOpen && ! $root.contains($event.target) ) && close()" 2248 style="--results-height: calc(100vh - var(--header-group-height) - var(--search-bar-height) + var(--gridline-width));" 2249 src="//printroom.co/cdn/shop/t/59/assets/island-predictive-search.bundle.js?v=181601895277339900721787098435" 2250 2251 x-ref="searchComponent" 2252 data-color-scheme="scheme1" 2253 on="idle" 2254 > 2255 <div 2256 class="w-full whitespace-normal" 2257 > 2258 <form 2259 action="/search" 2260 method="get" 2261 class="predictive-search-form input-group search" 2262 role="search" 2263 > 2264 <input type="hidden" name="options[prefix]" value="last"><label 2265 for="search-logo_left_menu_spread-desktop" 2266 class="hidden" 2267 >Submit</label> 2268 2269 <div 2270 class="flex items-center justify-between" 2271 > 2272 <button 2273 class="mr-4 py-2" 2274 aria-label="Submit" 2275 type="submit" 2276 >
2277 <span class="inline-block h-6 w-6 align-middle"><svg 2278 class="theme-icon" 2279 xmlns="http://www.w3.org/2000/svg" 2280 fill="none" 2281 viewBox="0 0 24 24" 2282> 2283 <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"/> 2284</svg> 2285</span> 2286 <span class="sr-only">Submit</span> 2287 </button> 2288 <input 2289 id="search-logo_left_menu_spread-desktop" 2290 type="search" 2291 name="q" 2292 value="" 2293 placeholder="Search" 2294 class="font-body block w-full bg-transparent placeholder-current" 2295 aria-label="Search" 2296 data-search-input 2297 2298 :aria-expanded="resultsOpen" 2299 :aria-activedescendant="resultsOpen ? 'predictive-search-results' : false" 2300 aria-owns="predictive-search-results" 2301 aria-controls="predictive-search-results" 2302 aria-autocomplete="list" 2303 autocorrect="off" 2304 autocomplete="off" 2305 autocapitalize="off" 2306 spellcheck="false" 2307 x-ref="input" 2308 x-model.debounce.300="rawQuery" 2309 @focus="onFocus" 2310 2311 > 2312 <button 2313 class="ml-4 py-2" 2314 2315 @click="close()" 2316 2317 type="button" 2318 > 2319 <span class="sr-only">Close</span> 2320 <span class="inline-block h-6 w-6 align-middle"><svg 2321 class="theme-icon" 2322 xmlns="http://www.w3.org/2000/svg" 2323 fill="none" 2324 viewBox="0 0 24 24" 2325> 2326 <path stroke="currentColor" d="m1.5 1.5 21 21m0-21-21 21" vector-effect="non-scaling-stroke"/> 2327</svg> 2328</span> 2329 </button> 2330 </div><div 2331 tabindex="-1" 2332 x-cloak 2333 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" 2334 > 2335 <template x-if="loading"> 2336 <div class="border-b-gridline border-gridline-color bg-scheme-background"> 2337 <div 2338 class="mx-auto py-6 text-center" 2339 > 2340 <div>Loading…</div> 2341 </div> 2342 </div> 2343 </template> 2344 <template x-if="resultsOpen"> 2345 <div 2346 x-show="!loading && resultsHTML && resultsOpen" 2347 class="px-section max-h-[--results-height] scroll-py-5 overflow-hidden overflow-y-auto border-b-gridline border-gridline-color bg-scheme-background" 2348 x-html-if-set="resultsHTML" 2349 ></div> 2350 </template> 2351 </div> 2352 <span 2353 class="predictive-search-status sr-only" 2354 role="status" 2355 aria-hidden="true" 2356 ></span></form> 2357 </div> 2358 </data-island> 2359</data-island> 2360 2361 </div> 2362 2363 2364 <div class="flex items-stretch whitespace-nowrap gap-4"><style> 2365 @keyframes quote-badge-pulse { 2366 0% { transform: scale(1); } 2367 50% { transform: scale(1.22); } 2368 100% { transform: scale(1); } 2369 } 2370 2371 @keyframes quote-icon-pulse { 2372 0% { transform: scale(1); } 2373 50% { transform: scale(1.12); } 2374 100% { transform: scale(1); } 2375 } 2376 2377 .quote-badge-animate { 2378 animation: quote-badge-pulse 0.4s ease-in-out; 2379 } 2380 .quote-icon-animate { 2381 animation: quote-icon-pulse 0.4s ease-in-out; 2382 } 2383 .quote-badge { 2384 min-width: 1.3rem; 2385 padding-inline: 0.22rem; 2386 box-shadow: 0 10px 24px rgba(43, 57, 144, 0.22); 2387 } 2388 .quote-tooltip { 2389 position: absolute; 2390 top: calc(100% + 8px); 2391 right: -10px; 2392 width: 152px; 2393 padding: 15px 16px; 2394 border-radius: 20px; 2395 font-size: 14px; 2396 font-style: italic; 2397 line-height: 17px; 2398 color: #000; 2399 background: #FBFBF6; 2400 border: 1px solid #000; 2401 box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.15); 2402 z-index: 1000; 2403 cursor: pointer; 2404 white-space: normal; 2405 text-align: left; 2406 } 2407 .quote-tooltip::before { 2408 content: ''; 2409 position: absolute; 2410 top: -7px; 2411 right: 24px; 2412 width: 14px; 2413 height: 14px; 2414 background: #FBFBF6; 2415 border-top: 1px solid #000; 2416 border-left: 1px solid #000; 2417 transform: rotate(45deg); 2418 } 2419 @media (max-width: 640px) { 2420 .quote-tooltip { 2421 right: -10px; 2422 } 2423 } 2424</style> 2425 2426<div 2427 class="relative" 2428 x-data="{ 2429 showTooltip: false,
2430 tooltipDismissed: false, 2431 animating: false, 2432 tooltipTimer: null, 2433 dismissTooltip() { 2434 this.showTooltip = false; 2435 this.tooltipDismissed = true; 2436 if (this.tooltipTimer) clearTimeout(this.tooltipTimer); 2437 if (this.tooltipDelayTimer) clearTimeout(this.tooltipDelayTimer); 2438 }, 2439 tooltipDelayTimer: null, 2440 triggerTooltip() { 2441 try { 2442 if (this.tooltipDismissed || sessionStorage.getItem('psstShown')) return; 2443 } catch (error) { 2444 if (this.tooltipDismissed) return; 2445 } 2446 if (this.tooltipDelayTimer) clearTimeout(this.tooltipDelayTimer); 2447 this.tooltipDelayTimer = setTimeout(() => { 2448 if (this.tooltipDismissed) return; 2449 try { sessionStorage.setItem('psstShown', '1'); } catch(e) {} 2450 this.showTooltip = true; 2451 if (this.tooltipTimer) clearTimeout(this.tooltipTimer); 2452 this.tooltipTimer = setTimeout(() => { this.showTooltip = false; }, 15000); 2453 }, 5000); 2454 }, 2455 pulseIcon() { 2456 this.animating = true; 2457 setTimeout(() => { this.animating = false; }, 450); 2458 } 2459 }" 2460 @quote-item-added.document="pulseIcon(); triggerTooltip()" 2461> 2462 <a 2463 href="/pages/general-quote" 2464 class="inline-flex min-h-10 items-center py-4 h-full" 2465 :role="`button`" 2466 :aria-expanded="$store.modals.rightDrawer.contents === 'favorites'" 2467 @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 })" 2468 @keydown.space.prevent="$store.modals.open('favorites'); dismissTooltip()" 2469 aria-label="Open your quote" 2470 ><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"> 2471 <svg 2472 aria-hidden="true" 2473 focusable="false" 2474 role="presentation" 2475 class="icon icon-quote-list-outline" 2476 viewBox="0 0 24 24" 2477 fill="none" 2478 ><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> 2479 <line x1="10" y1="7.5" x2="17.5" y2="7.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 2480 <circle cx="7.5" cy="11" r="1" fill="currentColor"></circle> 2481 <line x1="10" y1="11" x2="17.5" y2="11" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 2482 <circle cx="7.5" cy="14.5" r="1" fill="currentColor"></circle> 2483 <line x1="10" y1="14.5" x2="17.5" y2="14.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 2484 <circle cx="7.5" cy="18" r="1" fill="currentColor"></circle> 2485 <line x1="10" y1="18" x2="17.5" y2="18" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 2486 </svg> 2487</span> 2488</span><span 2489 x-show="$store.favorites.count > 0" 2490 x-cloak 2491 class="quote-badge absolute flex items-center justify-center rounded-full text-[10px] font-bold" 2492 style="background-color: #4B4D72; color: #fff; width: 18px; height: 18px; top: -7px; right: -8px;" 2493 :class="{ 'quote-badge-animate': animating }" 2494 x-text="$store.favorites.count" 2495 ></span> 2496 <span class="sr-only" x-text="'Your Quote: ' + $store.favorites.countWithText()"> 2497 Your Quote: 0 items 2498 </span> 2499 </div></a><div 2500 x-show="showTooltip" 2501 x-transition:enter="transition ease-out duration-200" 2502 x-transition:enter-start="opacity-0 translate-y-1" 2503 x-transition:enter-end="opacity-100 translate-y-0" 2504 x-transition:leave="transition ease-in duration-150" 2505 x-transition:leave-start="opacity-100" 2506 x-transition:leave-end="opacity-0" 2507 x-cloak 2508 class="quote-tooltip" 2509 @click="dismissTooltip()" 2510 > 2511 Hi, your favourite products are here. 2512 </div> 2513</div> 2514 2515 <a 2516 href="/cart" 2517 class="inline-flex py-4 h-full" 2518 2519 ><div class="pointer-events-none relative my-auto align-middle"> 2520 <span 2521 x-show="$store.cartCount.count > 0" 2522 class="absolute right-0 top-1 h-2 w-2 rounded-full" 2523 style="background-color: #f1ffa5;" 2524 ></span>
2525 <span class="inline-block h-6 w-6 fill-current align-top [&_*]:pointer-events-none"><svg 2526 class="theme-icon" 2527 xmlns="http://www.w3.org/2000/svg" 2528 fill="none" 2529 viewBox="0 0 24 24" 2530> 2531 <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"/> 2532</svg> 2533</span> 2534 <span class="sr-only" x-text="$store.cartCount.countWithText()"> 2535 25360 items 2537 </span> 2538 </div></a> 2539 </div> 2540 </div> 2541 </div> 2542 2543 2544 </nav> 2545 2546 2547 <nav 2548 aria-label="Header" 2549 class="lg:hidden" 2550 > 2551 <div class="flex items-center justify-between px-section-horizontal-spacing lg:relative"> 2552 <div class="flex gap-2 items-center"> 2553 2554 <div> 2555 <a 2556 href="/" 2557 class="break-word my-auto inline-block py-4" 2558 > 2559 2560 2561 <div class="max-w-[var(--logo-max-width)]"> 2562 2563<img 2564 src="//printroom.co/cdn/shop/files/printroom_primary_logo.svg?v=1704916358&width=90" 2565 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 2566 " 2567 width="543" 2568 height="397" 2569 loading="eager" 2570 2571 sizes="(min-width: 1024px) 90px, 80px" 2572 2573 alt="The Print Room" 2574 2575 > 2576 2577 2578 2579 </div> 2580 2581 2582 </a> 2583 </div> 2584 2585 2586 </div> 2587 2588 2589 2590 <div class="flex justify-end gap-2 text-right"> 2591 2592 <button 2593 class="inline-block no-js:hidden py-4" 2594 :aria-expanded="$store.modals.leftDrawer.contents === 'sidebar'" 2595 @click="$store.modals.open('sidebar')" 2596 ><span class="sr-only pointer-events-none">Menu</span> 2597 <span class="pointer-events-none inline-block h-6 w-6 align-middle"><svg 2598 class="theme-icon" 2599 xmlns="http://www.w3.org/2000/svg" 2600 fill="none" 2601 viewBox="0 0 24 24" 2602> 2603 <path stroke="currentColor" d="M1 7.364h22M1 15.636h22" vector-effect="non-scaling-stroke"/> 2604</svg> 2605</span></button> 2606 2607 2608 2609 2610 2611 <div class="whitespace-nowrap lg:ml-4"> 2612 <data-island 2613 x-data="{ searchOpen: false }" 2614 class="contents" 2615> 2616 <a 2617 x-ref="searchToggle" 2618 @click.prevent="searchOpen = true" 2619 @keydown.space.prevent="searchOpen = true" 2620 class="inline-flex py-4 h-full" 2621 href="/search" 2622 :role="`button`" 2623 ><span class="sr-only">Search</span> 2624 <span class="my-auto inline-block h-6 w-6 align-middle"><svg 2625 class="theme-icon" 2626 xmlns="http://www.w3.org/2000/svg" 2627 fill="none" 2628 viewBox="0 0 24 24" 2629> 2630 <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"/> 2631</svg> 2632</span></a> 2633 2634 <data-island 2635 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" 2636 x-cloak 2637 x-show="searchOpen" 2638 x-transition:enter="ease duration-200" 2639 x-transition:enter-start="opacity-0" 2640 x-transition:enter-end="opacity-100" 2641 x-transition:leave="ease duration-200" 2642 x-transition:leave-start="opacity-100" 2643 x-transition:leave-end="opacity-0" 2644 2645 x-data="PredictiveSearch('product,collection,article,page,query')" 2646 x-trap.inert.noscroll="resultsOpen" 2647 @keyup="onKeyup" 2648 @keydown="onKeydown" 2649 @click.outside.prevent="close()" 2650 @keyup.escape.prevent.stop="close(true, $refs.searchToggle)" 2651 @focusin.window="( searchOpen && ! $root.contains($event.target) ) && close()" 2652 style="--results-height: calc(100vh - var(--header-group-height) - var(--search-bar-height) + var(--gridline-width));" 2653 src="//printroom.co/cdn/shop/t/59/assets/island-predictive-search.bundle.js?v=181601895277339900721787098435" 2654 2655 x-ref="searchComponent" 2656 data-color-scheme="scheme1" 2657 on="idle" 2658 > 2659 <div 2660 class="w-full whitespace-normal" 2661 > 2662 <form 2663 action="/search" 2664 method="get" 2665 class="predictive-search-form input-group search" 2666 role="search" 2667 > 2668 <input type="hidden" name="options[prefix]" value="last"><label 2669 for="search-logo_left_menu_spread-mobile" 2670 class="hidden" 2671 >Submit</label> 2672 2673 <div 2674 class="flex items-center justify-between" 2675 > 2676 <button 2677 class="mr-4 py-2" 2678 aria-label="Submit" 2679 type="submit" 2680 >
2681 <span class="inline-block h-6 w-6 align-middle"><svg 2682 class="theme-icon" 2683 xmlns="http://www.w3.org/2000/svg" 2684 fill="none" 2685 viewBox="0 0 24 24" 2686> 2687 <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"/> 2688</svg> 2689</span> 2690 <span class="sr-only">Submit</span> 2691 </button> 2692 <input 2693 id="search-logo_left_menu_spread-mobile" 2694 type="search" 2695 name="q" 2696 value="" 2697 placeholder="Search" 2698 class="font-body block w-full bg-transparent placeholder-current" 2699 aria-label="Search" 2700 data-search-input 2701 2702 :aria-expanded="resultsOpen" 2703 :aria-activedescendant="resultsOpen ? 'predictive-search-results' : false" 2704 aria-owns="predictive-search-results" 2705 aria-controls="predictive-search-results" 2706 aria-autocomplete="list" 2707 autocorrect="off" 2708 autocomplete="off" 2709 autocapitalize="off" 2710 spellcheck="false" 2711 x-ref="input" 2712 x-model.debounce.300="rawQuery" 2713 @focus="onFocus" 2714 2715 > 2716 <button 2717 class="ml-4 py-2" 2718 2719 @click="close()" 2720 2721 type="button" 2722 > 2723 <span class="sr-only">Close</span> 2724 <span class="inline-block h-6 w-6 align-middle"><svg 2725 class="theme-icon" 2726 xmlns="http://www.w3.org/2000/svg" 2727 fill="none" 2728 viewBox="0 0 24 24" 2729> 2730 <path stroke="currentColor" d="m1.5 1.5 21 21m0-21-21 21" vector-effect="non-scaling-stroke"/> 2731</svg> 2732</span> 2733 </button> 2734 </div><div 2735 tabindex="-1" 2736 x-cloak 2737 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" 2738 > 2739 <template x-if="loading"> 2740 <div class="border-b-gridline border-gridline-color bg-scheme-background"> 2741 <div 2742 class="mx-auto py-6 text-center" 2743 > 2744 <div>Loading…</div> 2745 </div> 2746 </div> 2747 </template> 2748 <template x-if="resultsOpen"> 2749 <div 2750 x-show="!loading && resultsHTML && resultsOpen" 2751 class="px-section max-h-[--results-height] scroll-py-5 overflow-hidden overflow-y-auto border-b-gridline border-gridline-color bg-scheme-background" 2752 x-html-if-set="resultsHTML" 2753 ></div> 2754 </template> 2755 </div> 2756 <span 2757 class="predictive-search-status sr-only" 2758 role="status" 2759 aria-hidden="true" 2760 ></span></form> 2761 </div> 2762 </data-island> 2763</data-island> 2764 2765 </div> 2766 2767<div class="inline-block shrink-0 select-none whitespace-nowrap lg:ml-4"> 2768 <data-island 2769 class="relative" 2770 x-data="{ expanded: false }" 2771 @keydown.escape.prevent.stop="expanded = false" 2772 @click.outside="expanded = false" 2773 > 2774 <button 2775 type="button" 2776 class="inline-flex py-4 h-full" 2777 :aria-expanded="expanded" 2778 aria-controls="currency-list-header" 2779 @click.prevent="expanded = ! expanded" 2780 aria-label="Currency selector" 2781 > 2782 <span class="my-auto inline-flex items-center gap-1"> 2783 <span class="inline-block h-6 w-6 align-middle"> 2784 <svg class="theme-icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> 2785 <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="1.5" vector-effect="non-scaling-stroke" fill="none"/> 2786 <path stroke="currentColor" stroke-width="1.5" d="M12 6v12M8 10h8M8 14h8" vector-effect="non-scaling-stroke"/> 2787</svg> 2788 </span> 2789 <span class="text-xs font-medium">USD</span> 2790 </span>
2791 <span 2792 class="rotate ml-1 inline-block w-3 origin-center transform fill-current transition my-auto" 2793 :class="{ 'rotate-180': expanded }" 2794 > 2795 <svg 2796 class="theme-icon" 2797 xmlns="http://www.w3.org/2000/svg" 2798 fill="none" 2799 viewBox="0 0 24 24" 2800> 2801 <path stroke="currentColor" d="M1.5 7 12 17.5 22.5 7" vector-effect="non-scaling-stroke"/> 2802</svg> 2803 2804 </span> 2805 </button> 2806 <div 2807 class="absolute top-full right-0" 2808 x-show="expanded" 2809 style="display: none;" 2810 > 2811 <form method="post" action="/localization" accept-charset="UTF-8" enctype="multipart/form-data"> 2812 <input type="hidden" name="form_type" value="localization"> 2813 <input type="hidden" name="utf8" value="â"> 2814 <input type="hidden" name="_method" value="put"> 2815 <input type="hidden" name="return_to" value="/search"> 2816 <ul 2817 id="currency-list-header" 2818 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" 2819 x-transition:enter="transition ease duration-300" 2820 x-transition:enter-start="opacity-0" 2821 x-transition:enter-end="opacity-100" 2822 x-transition:leave="transition ease duration-300" 2823 x-transition:leave-start="opacity-100" 2824 x-transition:leave-end="opacity-0" 2825 :aria-hidden="! expanded" 2826 > 2827 2828 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2829 <button 2830 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2831 type="submit" 2832 name="country_code" 2833 value="AU" 2834 2835 > 2836 <span class="border-transparent border-b-text">AUD $<span class="ml-2 text-xs opacity-70">Australia</span></span 2837 > 2838 </button> 2839 </li> 2840 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2841 <button 2842 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2843 type="submit" 2844 name="country_code" 2845 value="CN" 2846 2847 > 2848 <span class="border-transparent border-b-text">CNY Â¥<span class="ml-2 text-xs opacity-70">China</span></span 2849 > 2850 </button> 2851 </li> 2852 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2853 <button 2854 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2855 type="submit" 2856 name="country_code" 2857 value="FR" 2858 2859 > 2860 <span class="border-transparent border-b-text">EUR â¬<span class="ml-2 text-xs opacity-70">France</span></span 2861 > 2862 </button> 2863 </li> 2864 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2865 <button 2866 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2867 type="submit" 2868 name="country_code" 2869 value="NZ" 2870 2871 >
2872 <span class="border-transparent border-b-text">NZD $<span class="ml-2 text-xs opacity-70">New Zealand</span></span 2873 > 2874 </button> 2875 </li> 2876 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2877 <button 2878 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2879 type="submit" 2880 name="country_code" 2881 value="GB" 2882 2883 > 2884 <span class="border-transparent border-b-text">GBP £<span class="ml-2 text-xs opacity-70">United Kingdom</span></span 2885 > 2886 </button> 2887 </li> 2888 <li class="flex items-center bg-scheme-background px-4 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 2889 <button 2890 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 2891 type="submit" 2892 name="country_code" 2893 value="US" 2894 2895 aria-current="true" 2896 2897 > 2898 <span class="border-scheme-text border-b-text">USD $<span class="ml-2 text-xs opacity-70">United States</span></span 2899 > 2900 </button> 2901 </li></ul> 2902 </form> 2903 </div> 2904 </data-island> 2905 </div><div class="flex items-center whitespace-nowrap gap-2 lg:ml-4"><style> 2906 @keyframes quote-badge-pulse { 2907 0% { transform: scale(1); } 2908 50% { transform: scale(1.22); } 2909 100% { transform: scale(1); } 2910 } 2911 2912 @keyframes quote-icon-pulse { 2913 0% { transform: scale(1); } 2914 50% { transform: scale(1.12); } 2915 100% { transform: scale(1); } 2916 } 2917 2918 .quote-badge-animate { 2919 animation: quote-badge-pulse 0.4s ease-in-out; 2920 } 2921 .quote-icon-animate { 2922 animation: quote-icon-pulse 0.4s ease-in-out; 2923 } 2924 .quote-badge { 2925 min-width: 1.3rem; 2926 padding-inline: 0.22rem; 2927 box-shadow: 0 10px 24px rgba(43, 57, 144, 0.22); 2928 } 2929 .quote-tooltip { 2930 position: absolute; 2931 top: calc(100% + 8px); 2932 right: -10px; 2933 width: 152px; 2934 padding: 15px 16px; 2935 border-radius: 20px; 2936 font-size: 14px; 2937 font-style: italic; 2938 line-height: 17px; 2939 color: #000; 2940 background: #FBFBF6; 2941 border: 1px solid #000; 2942 box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.15); 2943 z-index: 1000; 2944 cursor: pointer; 2945 white-space: normal; 2946 text-align: left; 2947 } 2948 .quote-tooltip::before { 2949 content: ''; 2950 position: absolute; 2951 top: -7px; 2952 right: 24px; 2953 width: 14px; 2954 height: 14px; 2955 background: #FBFBF6; 2956 border-top: 1px solid #000; 2957 border-left: 1px solid #000; 2958 transform: rotate(45deg); 2959 } 2960 @media (max-width: 640px) { 2961 .quote-tooltip { 2962 right: -10px; 2963 } 2964 } 2965</style> 2966 2967<div 2968 class="relative" 2969 x-data="{ 2970 showTooltip: false, 2971 tooltipDismissed: false, 2972 animating: false, 2973 tooltipTimer: null, 2974 dismissTooltip() { 2975 this.showTooltip = false; 2976 this.tooltipDismissed = true; 2977 if (this.tooltipTimer) clearTimeout(this.tooltipTimer); 2978 if (this.tooltipDelayTimer) clearTimeout(this.tooltipDelayTimer); 2979 }, 2980 tooltipDelayTimer: null, 2981 triggerTooltip() { 2982 try { 2983 if (this.tooltipDismissed || sessionStorage.getItem('psstShown')) return; 2984 } catch (error) { 2985 if (this.tooltipDismissed) return; 2986 } 2987 if (this.tooltipDelayTimer) clearTimeout(this.tooltipDelayTimer); 2988 this.tooltipDelayTimer = setTimeout(() => { 2989 if (this.tooltipDismissed) return; 2990 try { sessionStorage.setItem('psstShown', '1'); } catch(e) {} 2991 this.showTooltip = true; 2992 if (this.tooltipTimer) clearTimeout(this.tooltipTimer); 2993 this.tooltipTimer = setTimeout(() => { this.showTooltip = false; }, 15000); 2994 }, 5000); 2995 }, 2996 pulseIcon() { 2997 this.animating = true; 2998 setTimeout(() => { this.animating = false; }, 450); 2999 } 3000 }" 3001 @quote-item-added.document="pulseIcon(); triggerTooltip()" 3002> 3003 <a 3004 href="/pages/general-quote" 3005 class="inline-flex min-h-10 items-center py-4 h-full" 3006 :role="`button`" 3007 :aria-expanded="$store.modals.rightDrawer.contents === 'favorites'" 3008 @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 })" 3009 @keydown.space.prevent="$store.modals.open('favorites'); dismissTooltip()" 3010 aria-label="Open your quote" 3011 ><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"> 3012 <svg 3013 aria-hidden="true" 3014 focusable="false" 3015 role="presentation" 3016 class="icon icon-quote-list-outline"
3017 viewBox="0 0 24 24" 3018 fill="none" 3019 ><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> 3020 <line x1="10" y1="7.5" x2="17.5" y2="7.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 3021 <circle cx="7.5" cy="11" r="1" fill="currentColor"></circle> 3022 <line x1="10" y1="11" x2="17.5" y2="11" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 3023 <circle cx="7.5" cy="14.5" r="1" fill="currentColor"></circle> 3024 <line x1="10" y1="14.5" x2="17.5" y2="14.5" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 3025 <circle cx="7.5" cy="18" r="1" fill="currentColor"></circle> 3026 <line x1="10" y1="18" x2="17.5" y2="18" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></line> 3027 </svg> 3028</span> 3029</span><span 3030 x-show="$store.favorites.count > 0" 3031 x-cloak 3032 class="quote-badge absolute flex items-center justify-center rounded-full text-[10px] font-bold" 3033 style="background-color: #4B4D72; color: #fff; width: 18px; height: 18px; top: -7px; right: -8px;" 3034 :class="{ 'quote-badge-animate': animating }" 3035 x-text="$store.favorites.count" 3036 ></span> 3037 <span class="sr-only" x-text="'Your Quote: ' + $store.favorites.countWithText()"> 3038 Your Quote: 0 items 3039 </span> 3040 </div></a><div 3041 x-show="showTooltip" 3042 x-transition:enter="transition ease-out duration-200" 3043 x-transition:enter-start="opacity-0 translate-y-1" 3044 x-transition:enter-end="opacity-100 translate-y-0" 3045 x-transition:leave="transition ease-in duration-150" 3046 x-transition:leave-start="opacity-100" 3047 x-transition:leave-end="opacity-0" 3048 x-cloak 3049 class="quote-tooltip" 3050 @click="dismissTooltip()" 3051 > 3052 Hi, your favourite products are here. 3053 </div> 3054</div> 3055 3056 <a 3057 href="/cart" 3058 class="inline-flex py-4 h-full" 3059 3060 ><div class="pointer-events-none relative my-auto align-middle"> 3061 <span 3062 x-show="$store.cartCount.count > 0" 3063 class="absolute right-0 top-1 h-2 w-2 rounded-full" 3064 style="background-color: #f1ffa5;" 3065 ></span> 3066 <span class="inline-block h-6 w-6 fill-current align-top [&_*]:pointer-events-none"><svg 3067 class="theme-icon" 3068 xmlns="http://www.w3.org/2000/svg" 3069 fill="none" 3070 viewBox="0 0 24 24" 3071> 3072 <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"/> 3073</svg> 3074</span> 3075 <span class="sr-only" x-text="$store.cartCount.countWithText()"> 3076 30770 items 3078 </span> 3079 </div></a> 3080 </div> 3081 </div> 3082 </div> 3083 </nav> 3084 </header> 3085</data-island><noscript> 3086 <style data-shopify> 3087 .no-js-focus-wrapper:focus-within .no-js-focus-container { 3088 display: block !important; 3089 } 3090 3091 </style> 3092</noscript> 3093 3094<style> 3095 /* ââ Get Started pill + dropdown ââ */ 3096 .gs-pill { 3097 display: inline-flex; 3098 align-items: center; 3099 padding: 0 20px; 3100 height: 39px; 3101 border: 1px solid #2a3a8e; 3102 border-radius: 40px; 3103 background: transparent; 3104 color: #2a3a8e; 3105 font-size: 17.3px; 3106 font-family: 'DM Sans', sans-serif; 3107 font-weight: 400; 3108 line-height: 24px; 3109 cursor: pointer; 3110 white-space: nowrap; 3111 transition: background-color 0.25s ease, color 0.25s ease; 3112 } 3113 3114 .gs-pill:hover, 3115 .gs-pill.is-active { 3116 background-color: #2b3990; 3117 color: #f9fafb; 3118 } 3119 3120 .gs-dropdown-content { 3121 display: flex; 3122 flex-direction: column; 3123 gap: 6px; 3124 padding: 10px 20px 14px; 3125 left: 0; 3126 } 3127 3128 .gs-dropdown-content a { 3129 color: #2a3a8e; 3130 font-size: 17.3px; 3131 font-family: 'DM Sans', sans-serif; 3132 font-weight: 400; 3133 text-decoration: none; 3134 white-space: nowrap; 3135 line-height: 32px; 3136 } 3137 3138 .gs-dropdown-content a:hover { 3139 opacity: 0.7; 3140 } 3141 3142 /* Nav dropdowns (e.g. "Our story") nudged left to sit under the menu label */ 3143 .nav-dropdown-content { 3144 left: -12px; 3145 } 3146 3147 .quote-pill-button { 3148 display: inline-block; 3149 padding: 1rem 2rem; 3150 border-radius: 9999px; 3151 cursor: pointer; 3152 border: 0; 3153 background-color: #f1ffa5; 3154 transition: all 0.5s ease; 3155 color: #1F2937; 3156 text-decoration: none; 3157 font-weight: 600; 3158 font-size: 1.1em; 3159 } 3160 3161 .quote-pill-button:hover { 3162 transform: scale(1.2); 3163 } 3164 3165 .quote-pill-button:active { 3166 transform: scale(1.07); 3167 transition: 100ms; 3168 } 3169
3170 .start-design-button { 3171 display: inline-block; 3172 padding: 1rem 2rem; 3173 border-radius: 9999px; 3174 cursor: pointer; 3175 border: 0; 3176 background-color: #2b3990; 3177 transition: all 0.5s ease; 3178 color: #ffffff; 3179 text-decoration: none; 3180 font-weight: 600; 3181 font-size: 1.1em; 3182 } 3183 3184 .start-design-button:hover { 3185 transform: scale(1.2); 3186 } 3187 3188 .start-design-button:active { 3189 transform: scale(1.07); 3190 transition: 100ms; 3191 } 3192 3193 @keyframes float { 3194 0%, 100% { 3195 transform: translateY(0px); 3196 } 3197 50% { 3198 transform: translateY(-6px); 3199 } 3200 } 3201 3202 .beta-badge { 3203 position: absolute; 3204 top: -8px; 3205 right: -8px; 3206 background-color: #f1ffa5; 3207 color: #1e2326; 3208 font-size: 0.65em; 3209 font-weight: 700; 3210 padding: 0.25rem 0.5rem; 3211 border-radius: 9999px; 3212 text-transform: uppercase; 3213 letter-spacing: 0.5px; 3214 box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); 3215 z-index: 10; 3216 animation: float 2s ease-in-out infinite; 3217 } 3218</style> 3219 3220 3221 3222
3222<script> 3223 if (!customElements.get('sticky-header-height-helper')) { 3224 class StickyHeaderHeightHelper extends HTMLElement { 3225 constructor() { 3226 super(); 3227 } 3228 3229 connectedCallback() { 3230 const headerEl = this.closest('[data-theme-header]'); 3231 3232 if (headerEl && headerEl.getAttribute('data-sticky')) { 3233 document.documentElement.style.setProperty( 3234 '--sticky-header-height', 3235 `${headerEl.getBoundingClientRect().height}px` 3236 ); 3237 } else { 3238 3239 document.documentElement.style.setProperty( 3240 '--sticky-header-height', 3241 '0px' 3242 ); 3243 } 3244 } 3245 } 3246 3247 customElements.define( 3248 'sticky-header-height-helper', 3249 StickyHeaderHeightHelper 3250 ); 3251 } 3252 </script>
3252 3253 3254 3255<style> #shopify-section-sections--21296457187398__header .bg-scheme-background {border-bottom: 1px solid #2b3990;} </style></div> 3256<!-- END sections: header-group --> 3257<div id="shopify-section-menu-drawer" class="shopify-section"> 3258 3259<data-island 3260 3261 x-data 3262 3263 x-init="initTeleport($root); $store.modals.register('sidebar', 'leftDrawer');" 3264 on="idle" 3265> 3266 <template data-should-teleport="#left-drawer-slot"> 3267 <template 3268 id="sidebar" 3269 x-if="$store.modals.leftDrawer.contents === 'sidebar'" 3270 > 3271 3272 <div 3273 3274 data-modal-label="Menu" 3275 > 3276 <div class="sticky top-0 z-1 flex items-center justify-between border-b-gridline border-gridline-color px-section-horizontal-spacing py-4"> 3277 <div aria-hidden="true"> </div> 3278 <button 3279 @click.prevent="$store.modals.close('sidebar')" 3280 class="absolute right-0 top-0 block h-full" 3281 type="button" 3282 > 3283 <span class="sr-only">Close</span> 3284 <div class="my-auto mr-section-horizontal-spacing h-6 w-6"><svg 3285 class="theme-icon" 3286 xmlns="http://www.w3.org/2000/svg" 3287 fill="none" 3288 viewBox="0 0 24 24" 3289> 3290 <path stroke="currentColor" d="m1.5 1.5 21 21m0-21-21 21" vector-effect="non-scaling-stroke"/> 3291</svg> 3292</div> 3293 </button> 3294 </div> 3295 <nav 3296 3297 aria-label="Primary" 3298 > 3299 <ul><li 3300 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 3301 ><a class="inline-block py-4 w-full text-heading-standard" href="/collections/product-library"> 3302 Products 3303 </a></li><li 3304 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 3305 ><data-island class="contents" x-data="{ expanded: false }"><button 3306 class="relative block w-full text-left inline-block py-4 w-full text-heading-standard ease pr-10 transition font-body" 3307 x-bind:aria-expanded="expanded ? true : 'false'" 3308 @click="expanded = ! expanded" 3309 aria-controls="accordion0" 3310 > 3311 Services 3312 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3313 class="inline-block w-full origin-center" 3314 x-show="!expanded" 3315 ><svg 3316 class="theme-icon" 3317 xmlns="http://www.w3.org/2000/svg" 3318 fill="none" 3319 viewBox="0 0 24 24" 3320> 3321 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3322</svg> 3323</span> 3324 <span 3325 class="inline-block w-full origin-center" 3326 x-show="expanded" 3327 style="display: none;" 3328 ><svg 3329 class="theme-icon" 3330 xmlns="http://www.w3.org/2000/svg" 3331 fill="none" 3332 viewBox="0 0 24 24" 3333> 3334 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3335</svg> 3336</span></span> 3337 </button> 3338 <ul 3339 id="accordion0" 3340 class="no-js-focus-container pb-2 pl-4" 3341 x-show="expanded" 3342 x-cloak 3343 ><li class="no-js-focus-wrapper"><data-island class="contents" x-data="{ expanded: false }" > 3344 <button 3345 class="relative w-full text-left inline-block py-1 pr-10" 3346 x-bind:aria-expanded="expanded ? true : 'false'" 3347 @click="expanded = ! expanded" 3348 aria-controls="accordion1" 3349 > 3350 Production capabilities 3351 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3352 class="inline-block w-full origin-center" 3353 x-show="!expanded" 3354 ><svg 3355 class="theme-icon" 3356 xmlns="http://www.w3.org/2000/svg" 3357 fill="none" 3358 viewBox="0 0 24 24" 3359> 3360 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3361</svg> 3362</span>
3363 <span 3364 class="inline-block w-full origin-center" 3365 x-show="expanded" 3366 style="display: none;" 3367 ><svg 3368 class="theme-icon" 3369 xmlns="http://www.w3.org/2000/svg" 3370 fill="none" 3371 viewBox="0 0 24 24" 3372> 3373 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3374</svg> 3375</span></span> 3376 </button> 3377 <ul 3378 id="accordion1" 3379 class="no-js-focus-container px-2 pb-2 pt-1" 3380 x-show="expanded" 3381 x-cloak 3382 ><li> 3383 <a 3384 class="inline-block py-1 " 3385 href="/pages/custom-manufactured" 3386 > 3387 Custom-manufactured 3388 </a> 3389 </li><li> 3390 <a 3391 class="inline-block py-1 " 3392 href="/pages/screen-printing" 3393 > 3394 Screen printing 3395 </a> 3396 </li><li> 3397 <a 3398 class="inline-block py-1 " 3399 href="/pages/embroidery" 3400 > 3401 Embroidery 3402 </a> 3403 </li><li> 3404 <a 3405 class="inline-block py-1 " 3406 href="/pages/heat-transfers" 3407 > 3408 Heat transfers 3409 </a> 3410 </li><li> 3411 <a 3412 class="inline-block py-1 " 3413 href="/pages/finishing" 3414 > 3415 Finishing 3416 </a> 3417 </li></ul> 3418 </data-island></li><li class="no-js-focus-wrapper"><data-island class="contents" x-data="{ expanded: false }" > 3419 <button 3420 class="relative w-full text-left inline-block py-1 pr-10" 3421 x-bind:aria-expanded="expanded ? true : 'false'" 3422 @click="expanded = ! expanded" 3423 aria-controls="accordion2" 3424 > 3425 Partner services 3426 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3427 class="inline-block w-full origin-center" 3428 x-show="!expanded" 3429 ><svg 3430 class="theme-icon" 3431 xmlns="http://www.w3.org/2000/svg" 3432 fill="none" 3433 viewBox="0 0 24 24" 3434> 3435 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3436</svg> 3437</span> 3438 <span 3439 class="inline-block w-full origin-center" 3440 x-show="expanded" 3441 style="display: none;" 3442 ><svg 3443 class="theme-icon" 3444 xmlns="http://www.w3.org/2000/svg" 3445 fill="none" 3446 viewBox="0 0 24 24" 3447> 3448 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3449</svg> 3450</span></span> 3451 </button> 3452 <ul 3453 id="accordion2" 3454 class="no-js-focus-container px-2 pb-2 pt-1" 3455 x-show="expanded" 3456 x-cloak 3457 ><li> 3458 <a 3459 class="inline-block py-1 " 3460 href="/pages/client-portal" 3461 > 3462 Client portal 3463 </a> 3464 </li><li> 3465 <a 3466 class="inline-block py-1 " 3467 href="/pages/fundraising-pre-orders" 3468 > 3469 Fundraise & pre-order 3470 </a> 3471 </li><li> 3472 <a 3473 class="inline-block py-1 " 3474 href="/pages/repurpose-initiative" 3475 > 3476 Repurpose initiative 3477 </a> 3478 </li></ul> 3479 </data-island></li><li class="no-js-focus-wrapper"><data-island class="contents" x-data="{ expanded: false }" > 3480 <button 3481 class="relative w-full text-left inline-block py-1 pr-10" 3482 x-bind:aria-expanded="expanded ? true : 'false'" 3483 @click="expanded = ! expanded" 3484 aria-controls="accordion3" 3485 > 3486 Popular services
3487 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3488 class="inline-block w-full origin-center" 3489 x-show="!expanded" 3490 ><svg 3491 class="theme-icon" 3492 xmlns="http://www.w3.org/2000/svg" 3493 fill="none" 3494 viewBox="0 0 24 24" 3495> 3496 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3497</svg> 3498</span> 3499 <span 3500 class="inline-block w-full origin-center" 3501 x-show="expanded" 3502 style="display: none;" 3503 ><svg 3504 class="theme-icon" 3505 xmlns="http://www.w3.org/2000/svg" 3506 fill="none" 3507 viewBox="0 0 24 24" 3508> 3509 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3510</svg> 3511</span></span> 3512 </button> 3513 <ul 3514 id="accordion3" 3515 class="no-js-focus-container px-2 pb-2 pt-1" 3516 x-show="expanded" 3517 x-cloak 3518 ><li> 3519 <a 3520 class="inline-block py-1 " 3521 href="/pages/school-leavers-gear" 3522 > 3523 School leavers gear 3524 </a> 3525 </li><li> 3526 <a 3527 class="inline-block py-1 " 3528 href="/pages/tshirt-printing" 3529 > 3530 Custom t-shirt printing 3531 </a> 3532 </li></ul> 3533 </data-island></li></ul> 3534 </data-island></li><li 3535 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 3536 ><a class="inline-block py-4 w-full text-heading-standard" href="/pages/responsibility"> 3537 Responsibility 3538 </a></li><li 3539 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 3540 ><data-island class="contents" x-data="{ expanded: false }"><button 3541 class="relative block w-full text-left inline-block py-4 w-full text-heading-standard ease pr-10 transition font-body" 3542 x-bind:aria-expanded="expanded ? true : 'false'" 3543 @click="expanded = ! expanded" 3544 aria-controls="accordion4" 3545 > 3546 Our story 3547 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3548 class="inline-block w-full origin-center" 3549 x-show="!expanded" 3550 ><svg 3551 class="theme-icon" 3552 xmlns="http://www.w3.org/2000/svg" 3553 fill="none" 3554 viewBox="0 0 24 24" 3555> 3556 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3557</svg> 3558</span> 3559 <span 3560 class="inline-block w-full origin-center" 3561 x-show="expanded" 3562 style="display: none;" 3563 ><svg 3564 class="theme-icon" 3565 xmlns="http://www.w3.org/2000/svg" 3566 fill="none" 3567 viewBox="0 0 24 24" 3568> 3569 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3570</svg> 3571</span></span> 3572 </button> 3573 <ul 3574 id="accordion4" 3575 class="no-js-focus-container pb-2 pl-4" 3576 x-show="expanded" 3577 x-cloak 3578 ><li class="no-js-focus-wrapper"><a 3579 class="inline-block py-1 " 3580 href="/pages/in-good-company-with" 3581 > 3582 In good company with⦠3583 </a></li><li class="no-js-focus-wrapper"><a 3584 class="inline-block py-1 " 3585 href="/pages/about-print-room" 3586 > 3587 Our origins 3588 </a></li></ul> 3589 </data-island></li><li 3590 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gr
3590idline-color first-of-type:border-t-0" 3591 ><data-island class="contents" x-data="{ expanded: false }"><button 3592 class="relative block w-full text-left inline-block py-4 w-full text-heading-standard ease pr-10 transition font-body" 3593 x-bind:aria-expanded="expanded ? true : 'false'" 3594 @click="expanded = ! expanded" 3595 aria-controls="accordion5" 3596 > 3597 Get started 3598 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3599 class="inline-block w-full origin-center" 3600 x-show="!expanded" 3601 ><svg 3602 class="theme-icon" 3603 xmlns="http://www.w3.org/2000/svg" 3604 fill="none" 3605 viewBox="0 0 24 24" 3606> 3607 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3608</svg> 3609</span> 3610 <span 3611 class="inline-block w-full origin-center" 3612 x-show="expanded" 3613 style="display: none;" 3614 ><svg 3615 class="theme-icon" 3616 xmlns="http://www.w3.org/2000/svg" 3617 fill="none" 3618 viewBox="0 0 24 24" 3619> 3620 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3621</svg> 3622</span></span> 3623 </button> 3624 <ul 3625 id="accordion5" 3626 class="no-js-focus-container pb-2 pl-4" 3627 x-show="expanded" 3628 x-cloak 3629 ><li class="no-js-focus-wrapper"><a 3630 class="inline-block py-1 " 3631 href="/collections/product-library" 3632 > 3633 Start a project 3634 </a></li><li class="no-js-focus-wrapper"><a 3635 class="inline-block py-1 " 3636 href="/pages/book-a-call" 3637 > 3638 Book a call 3639 </a></li></ul> 3640 </data-island></li></ul> 3641 </nav> 3642 <div class="border-t-gridline border-gridline-color"> 3643 <nav class="my-6" aria-label="Secondary"> 3644 <ul></ul> 3645 </nav> 3646 3647 3648 <div class="my-6 px-section-horizontal-spacing"> 3649 <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="/search" /><div class="flex gap-4 flex-col gap-y-0"><div class="inline-block shrink-0 select-none"> 3650 <h2 class="sr-only" id="country-heading-sidebar"> 3651 Country/region 3652 </h2> 3653 <data-island 3654 class="relative" 3655 x-data="{ expanded: false }" 3656 @keydown.escape.prevent.stop="expanded = false" 3657 @click.outside="expanded = false" 3658 > 3659 <button 3660 type="button" 3661 class="text-base py-2" 3662 :aria-expanded="expanded" 3663 aria-controls="country-list-sidebar" 3664 aria-describedby="country-heading-sidebar" 3665 @click.prevent="expanded = ! expanded" 3666 > 3667 United States (USD 3668 $) 3669 <span 3670 class="rotate ml-1 inline-block w-3 origin-center transform fill-current transition" 3671 :class="{ 'rotate-180': expanded }" 3672 > 3673 <svg 3674 class="theme-icon" 3675 xmlns="http://www.w3.org/2000/svg" 3676 fill="none" 3677 viewBox="0 0 24 24" 3678> 3679 <path stroke="currentColor" d="M1.5 7 12 17.5 22.5 7" vector-effect="non-scaling-stroke"/> 3680</svg> 3681 3682 </span> 3683 </button> 3684 <div 3685 class="absolute bottom-[calc(100%_+_0.5rem)] right-auto left-0" 3686 x-show="expanded" 3687 style="display: none;" 3688 > 3689 <ul 3690 id="country-list-sidebar" 3691 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
3691idline-color bg-gridline-color text-base" 3692 x-transition:enter="transition ease duration-300" 3693 x-transition:enter-start="opacity-0" 3694 x-transition:enter-end="opacity-100" 3695 x-transition:leave="transition ease duration-300" 3696 x-transition:leave-start="opacity-100" 3697 x-transition:leave-end="opacity-0" 3698 :aria-hidden="! expanded" 3699 > 3700 3701 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 3702 <button 3703 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 3704 type="button" 3705 3706 @click.prevent="$refs.input.value = 'AU'; $root.closest('form').submit();" 3707 > 3708 <span class="border-transparent border-b-text">Australia (AUD 3709 $)</span 3710 > 3711 </button> 3712 </li> 3713 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 3714 <button 3715 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 3716 type="button" 3717 3718 @click.prevent="$refs.input.value = 'CN'; $root.closest('form').submit();" 3719 > 3720 <span class="border-transparent border-b-text">China (CNY 3721 Â¥)</span 3722 > 3723 </button> 3724 </li> 3725 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 3726 <button 3727 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 3728 type="button" 3729 3730 @click.prevent="$refs.input.value = 'FR'; $root.closest('form').submit();" 3731 > 3732 <span class="border-transparent border-b-text">France (EUR 3733 â¬)</span 3734 > 3735 </button> 3736 </li> 3737 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 3738 <button 3739 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 3740 type="button" 3741 3742 @click.prevent="$refs.input.value = 'NZ'; $root.closest('form').submit();" 3743 > 3744 <span class="border-transparent border-b-text">New Zealand (NZD 3745 $)</span 3746 > 3747 </button> 3748 </li> 3749 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 3750 <button 3751 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 3752 type="button" 3753 3754 @click.prevent="$refs.input.value = 'GB'; $root.closest('form').submit();" 3755 > 3756 <span class="border-transparent border-b-text">United Kingdom (GBP 3757 £)</span 3758 > 3759 </button> 3760 </li> 3761 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 3762 <button 3763 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 3764 type="button" 3765 3766 aria-current="true" 3767 3768 @click.prevent="$refs.input.value = 'US'; $root.closest('form').submit();" 3769 > 3770 <span class="border-scheme-text border-b-text">United States (USD 3771 $)</span 3772 > 3773 </button> 3774 </li></ul> 3775 </div> 3776 3777 <input 3778 x-ref="input" 3779 type="hidden" 3780 name="country_code" 3781 id="CountrySelector" 3782 value="US" 3783 > 3784 </data-island> 3785 </div></div></form> 3786 </div> 3787 3788 3789 3790<form 3791 class="my-6 px-section-horizontal-spacing" 3792 action="/search" 3793 method="get" 3794 role="search" 3795 > 3796 <div class="flex w-full max-w-xs items-end"> 3797 <label for="menu-drawer-search" class="sr-only">Search</label> 3798 <input 3799 class="min-w-0 flex-auto border-b-text border-current bg-transparent py-1.5 placeholder-current" 3800 id="menu-drawer-search" 3801 type="text" 3802 name="q" 3803 placeholder="Search" 3804 > 3805 <button 3806 class="px-1" 3807 type="submit" 3808 >
3809 <span class="inline-block h-6 w-6"><svg 3810 class="theme-icon" 3811 xmlns="http://www.w3.org/2000/svg" 3812 fill="none" 3813 viewBox="0 0 24 24" 3814> 3815 <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"/> 3816</svg> 3817</span> 3818 <span class="sr-only">Submit</span> 3819 </button> 3820 </div> 3821 </form> 3822 </div> 3823 </div> 3824 3825 </template> 3826 </template> 3827</data-island> 3828 3829<noscript> 3830 <section class="section-sidebar"> 3831 <div class="px-section-horizontal-spacing py-2 text-right"> 3832 <button 3833 class="inline-flex items-center justify-center py-2 " 3834 data-menu-drawer-toggle 3835 > 3836 <span class="mr-2 inline-block h-6 w-6 align-middle"><svg 3837 class="theme-icon" 3838 xmlns="http://www.w3.org/2000/svg" 3839 fill="none" 3840 viewBox="0 0 24 24" 3841> 3842 <path stroke="currentColor" d="M1 4.545h22M1 12h22M1 19.455h22" vector-effect="non-scaling-stroke"/> 3843</svg> 3844</span> 3845 <span>Menu</span> 3846 </button> 3847 </div> 3848 <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"> 3849 3850 <div 3851 3852 data-modal-label="Menu" 3853 > 3854 <div class="sticky top-0 z-1 flex items-center justify-between border-b-gridline border-gridline-color px-section-horizontal-spacing py-4"> 3855 <div aria-hidden="true"> </div> 3856 <button 3857 @click.prevent="$store.modals.close('sidebar')" 3858 class="absolute right-0 top-0 block h-full" 3859 type="button" 3860 > 3861 <span class="sr-only">Close</span> 3862 <div class="my-auto mr-section-horizontal-spacing h-6 w-6"><svg 3863 class="theme-icon" 3864 xmlns="http://www.w3.org/2000/svg" 3865 fill="none" 3866 viewBox="0 0 24 24" 3867> 3868 <path stroke="currentColor" d="m1.5 1.5 21 21m0-21-21 21" vector-effect="non-scaling-stroke"/> 3869</svg> 3870</div> 3871 </button> 3872 </div> 3873 <nav 3874 3875 aria-label="Primary" 3876 > 3877 <ul><li 3878 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 3879 ><a class="inline-block py-4 w-full text-heading-standard" href="/collections/product-library"> 3880 Products 3881 </a></li><li 3882 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 3883 ><data-island class="contents" x-data="{ expanded: false }"><button 3884 class="relative block w-full text-left inline-block py-4 w-full text-heading-standard ease pr-10 transition font-body" 3885 x-bind:aria-expanded="expanded ? true : 'false'" 3886 @click="expanded = ! expanded" 3887 aria-controls="accordion0" 3888 > 3889 Services 3890 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3891 class="inline-block w-full origin-center" 3892 x-show="!expanded" 3893 ><svg 3894 class="theme-icon" 3895 xmlns="http://www.w3.org/2000/svg" 3896 fill="none" 3897 viewBox="0 0 24 24" 3898> 3899 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3900</svg> 3901</span> 3902 <span 3903 class="inline-block w-full origin-center" 3904 x-show="expanded" 3905 style="display: none;" 3906 ><svg 3907 class="theme-icon" 3908 xmlns="http://www.w3.org/2000/svg" 3909 fill="none" 3910 viewBox="0 0 24 24" 3911> 3912 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3913</svg> 3914</span></span> 3915 </button> 3916 <ul 3917 id="accordion0" 3918 class="no-js-focus-container pb-2 pl-4" 3919 x-show="expanded" 3920 x-cloak 3921 ><li class="no-js-focus-wrapper"><data-island class="contents" x-data="{ expanded: false }" > 3922 <button 3923 class="relative w-full text-left inline-block py-1 pr-10" 3924 x-bind:aria-expanded="expanded ? true : 'false'" 3925 @click="expanded = ! expanded" 3926 aria-controls="accordion1" 3927 > 3928 Production capabilities
3929 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 3930 class="inline-block w-full origin-center" 3931 x-show="!expanded" 3932 ><svg 3933 class="theme-icon" 3934 xmlns="http://www.w3.org/2000/svg" 3935 fill="none" 3936 viewBox="0 0 24 24" 3937> 3938 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 3939</svg> 3940</span> 3941 <span 3942 class="inline-block w-full origin-center" 3943 x-show="expanded" 3944 style="display: none;" 3945 ><svg 3946 class="theme-icon" 3947 xmlns="http://www.w3.org/2000/svg" 3948 fill="none" 3949 viewBox="0 0 24 24" 3950> 3951 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 3952</svg> 3953</span></span> 3954 </button> 3955 <ul 3956 id="accordion1" 3957 class="no-js-focus-container px-2 pb-2 pt-1" 3958 x-show="expanded" 3959 x-cloak 3960 ><li> 3961 <a 3962 class="inline-block py-1 " 3963 href="/pages/custom-manufactured" 3964 > 3965 Custom-manufactured 3966 </a> 3967 </li><li> 3968 <a 3969 class="inline-block py-1 " 3970 href="/pages/screen-printing" 3971 > 3972 Screen printing 3973 </a> 3974 </li><li> 3975 <a 3976 class="inline-block py-1 " 3977 href="/pages/embroidery" 3978 > 3979 Embroidery 3980 </a> 3981 </li><li> 3982 <a 3983 class="inline-block py-1 " 3984 href="/pages/heat-transfers" 3985 > 3986 Heat transfers 3987 </a> 3988 </li><li> 3989 <a 3990 class="inline-block py-1 " 3991 href="/pages/finishing" 3992 > 3993 Finishing 3994 </a> 3995 </li></ul> 3996 </data-island></li><li class="no-js-focus-wrapper"><data-island class="contents" x-data="{ expanded: false }" > 3997 <button 3998 class="relative w-full text-left inline-block py-1 pr-10" 3999 x-bind:aria-expanded="expanded ? true : 'false'" 4000 @click="expanded = ! expanded" 4001 aria-controls="accordion2" 4002 > 4003 Partner services 4004 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 4005 class="inline-block w-full origin-center" 4006 x-show="!expanded" 4007 ><svg 4008 class="theme-icon" 4009 xmlns="http://www.w3.org/2000/svg" 4010 fill="none" 4011 viewBox="0 0 24 24" 4012> 4013 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 4014</svg> 4015</span> 4016 <span 4017 class="inline-block w-full origin-center" 4018 x-show="expanded" 4019 style="display: none;" 4020 ><svg 4021 class="theme-icon" 4022 xmlns="http://www.w3.org/2000/svg" 4023 fill="none" 4024 viewBox="0 0 24 24" 4025> 4026 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 4027</svg> 4028</span></span> 4029 </button> 4030 <ul 4031 id="accordion2" 4032 class="no-js-focus-container px-2 pb-2 pt-1" 4033 x-show="expanded" 4034 x-cloak 4035 ><li> 4036 <a 4037 class="inline-block py-1 " 4038 href="/pages/client-portal" 4039 > 4040 Client portal 4041 </a> 4042 </li><li> 4043 <a 4044 class="inline-block py-1 " 4045 href="/pages/fundraising-pre-orders" 4046 > 4047 Fundraise & pre-order 4048 </a> 4049 </li><li> 4050 <a 4051 class="inline-block py-1 " 4052 href="/pages/repurpose-initiative" 4053 > 4054 Repurpose initiative 4055 </a> 4056 </li></ul> 4057 </data-island></li><li class="no-js-focus-wrapper"><data-island class="contents" x-data="{ expanded: false }" > 4058 <button 4059 class="relative w-full text-left inline-block py-1 pr-10" 4060 x-bind:aria-expanded="expanded ? true : 'false'" 4061 @click="expanded = ! expanded" 4062 aria-controls="accordion3" 4063 > 4064 Popular services
4065 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 4066 class="inline-block w-full origin-center" 4067 x-show="!expanded" 4068 ><svg 4069 class="theme-icon" 4070 xmlns="http://www.w3.org/2000/svg" 4071 fill="none" 4072 viewBox="0 0 24 24" 4073> 4074 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 4075</svg> 4076</span> 4077 <span 4078 class="inline-block w-full origin-center" 4079 x-show="expanded" 4080 style="display: none;" 4081 ><svg 4082 class="theme-icon" 4083 xmlns="http://www.w3.org/2000/svg" 4084 fill="none" 4085 viewBox="0 0 24 24" 4086> 4087 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 4088</svg> 4089</span></span> 4090 </button> 4091 <ul 4092 id="accordion3" 4093 class="no-js-focus-container px-2 pb-2 pt-1" 4094 x-show="expanded" 4095 x-cloak 4096 ><li> 4097 <a 4098 class="inline-block py-1 " 4099 href="/pages/school-leavers-gear" 4100 > 4101 School leavers gear 4102 </a> 4103 </li><li> 4104 <a 4105 class="inline-block py-1 " 4106 href="/pages/tshirt-printing" 4107 > 4108 Custom t-shirt printing 4109 </a> 4110 </li></ul> 4111 </data-island></li></ul> 4112 </data-island></li><li 4113 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 4114 ><a class="inline-block py-4 w-full text-heading-standard" href="/pages/responsibility"> 4115 Responsibility 4116 </a></li><li 4117 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gridline-color first-of-type:border-t-0" 4118 ><data-island class="contents" x-data="{ expanded: false }"><button 4119 class="relative block w-full text-left inline-block py-4 w-full text-heading-standard ease pr-10 transition font-body" 4120 x-bind:aria-expanded="expanded ? true : 'false'" 4121 @click="expanded = ! expanded" 4122 aria-controls="accordion4" 4123 > 4124 Our story 4125 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 4126 class="inline-block w-full origin-center" 4127 x-show="!expanded" 4128 ><svg 4129 class="theme-icon" 4130 xmlns="http://www.w3.org/2000/svg" 4131 fill="none" 4132 viewBox="0 0 24 24" 4133> 4134 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 4135</svg> 4136</span> 4137 <span 4138 class="inline-block w-full origin-center" 4139 x-show="expanded" 4140 style="display: none;" 4141 ><svg 4142 class="theme-icon" 4143 xmlns="http://www.w3.org/2000/svg" 4144 fill="none" 4145 viewBox="0 0 24 24" 4146> 4147 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 4148</svg> 4149</span></span> 4150 </button> 4151 <ul 4152 id="accordion4" 4153 class="no-js-focus-container pb-2 pl-4" 4154 x-show="expanded" 4155 x-cloak 4156 ><li class="no-js-focus-wrapper"><a 4157 class="inline-block py-1 " 4158 href="/pages/in-good-company-with" 4159 > 4160 In good company with⦠4161 </a></li><li class="no-js-focus-wrapper"><a 4162 class="inline-block py-1 " 4163 href="/pages/about-print-room" 4164 > 4165 Our origins 4166 </a></li></ul> 4167 </data-island></li><li 4168 class="no-js-focus-wrapper break-word px-section-horizontal-spacing border-t-gridline border-gr
4168idline-color first-of-type:border-t-0" 4169 ><data-island class="contents" x-data="{ expanded: false }"><button 4170 class="relative block w-full text-left inline-block py-4 w-full text-heading-standard ease pr-10 transition font-body" 4171 x-bind:aria-expanded="expanded ? true : 'false'" 4172 @click="expanded = ! expanded" 4173 aria-controls="accordion5" 4174 > 4175 Get started 4176 <span class="absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 transform items-center"><span 4177 class="inline-block w-full origin-center" 4178 x-show="!expanded" 4179 ><svg 4180 class="theme-icon" 4181 xmlns="http://www.w3.org/2000/svg" 4182 fill="none" 4183 viewBox="0 0 24 24" 4184> 4185 <path stroke="currentColor" d="M12 1v22M1 12h22" vector-effect="non-scaling-stroke"/> 4186</svg> 4187</span> 4188 <span 4189 class="inline-block w-full origin-center" 4190 x-show="expanded" 4191 style="display: none;" 4192 ><svg 4193 class="theme-icon" 4194 xmlns="http://www.w3.org/2000/svg" 4195 fill="none" 4196 viewBox="0 0 24 24" 4197> 4198 <path stroke="currentColor" d="M1 12h22" vector-effect="non-scaling-stroke"/> 4199</svg> 4200</span></span> 4201 </button> 4202 <ul 4203 id="accordion5" 4204 class="no-js-focus-container pb-2 pl-4" 4205 x-show="expanded" 4206 x-cloak 4207 ><li class="no-js-focus-wrapper"><a 4208 class="inline-block py-1 " 4209 href="/collections/product-library" 4210 > 4211 Start a project 4212 </a></li><li class="no-js-focus-wrapper"><a 4213 class="inline-block py-1 " 4214 href="/pages/book-a-call" 4215 > 4216 Book a call 4217 </a></li></ul> 4218 </data-island></li></ul> 4219 </nav> 4220 <div class="border-t-gridline border-gridline-color"> 4221 <nav class="my-6" aria-label="Secondary"> 4222 <ul></ul> 4223 </nav> 4224 4225 4226 <div class="my-6 px-section-horizontal-spacing"> 4227 <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="/search" /><div class="flex gap-4 flex-col gap-y-0"><div class="inline-block shrink-0 select-none"> 4228 <h2 class="sr-only" id="country-heading-sidebar"> 4229 Country/region 4230 </h2> 4231 <data-island 4232 class="relative" 4233 x-data="{ expanded: false }" 4234 @keydown.escape.prevent.stop="expanded = false" 4235 @click.outside="expanded = false" 4236 > 4237 <button 4238 type="button" 4239 class="text-base py-2" 4240 :aria-expanded="expanded" 4241 aria-controls="country-list-sidebar" 4242 aria-describedby="country-heading-sidebar" 4243 @click.prevent="expanded = ! expanded" 4244 > 4245 United States (USD 4246 $) 4247 <span 4248 class="rotate ml-1 inline-block w-3 origin-center transform fill-current transition" 4249 :class="{ 'rotate-180': expanded }" 4250 > 4251 <svg 4252 class="theme-icon" 4253 xmlns="http://www.w3.org/2000/svg" 4254 fill="none" 4255 viewBox="0 0 24 24" 4256> 4257 <path stroke="currentColor" d="M1.5 7 12 17.5 22.5 7" vector-effect="non-scaling-stroke"/> 4258</svg> 4259 4260 </span> 4261 </button> 4262 <div 4263 class="absolute bottom-[calc(100%_+_0.5rem)] right-auto left-0" 4264 x-show="expanded" 4265 style="display: none;" 4266 > 4267 <ul 4268 id="country-list-sidebar" 4269 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
4269idline-color bg-gridline-color text-base" 4270 x-transition:enter="transition ease duration-300" 4271 x-transition:enter-start="opacity-0" 4272 x-transition:enter-end="opacity-100" 4273 x-transition:leave="transition ease duration-300" 4274 x-transition:leave-start="opacity-100" 4275 x-transition:leave-end="opacity-0" 4276 :aria-hidden="! expanded" 4277 > 4278 4279 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 4280 <button 4281 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 4282 type="button" 4283 4284 @click.prevent="$refs.input.value = 'AU'; $root.closest('form').submit();" 4285 > 4286 <span class="border-transparent border-b-text">Australia (AUD 4287 $)</span 4288 > 4289 </button> 4290 </li> 4291 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 4292 <button 4293 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 4294 type="button" 4295 4296 @click.prevent="$refs.input.value = 'CN'; $root.closest('form').submit();" 4297 > 4298 <span class="border-transparent border-b-text">China (CNY 4299 Â¥)</span 4300 > 4301 </button> 4302 </li> 4303 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 4304 <button 4305 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 4306 type="button" 4307 4308 @click.prevent="$refs.input.value = 'FR'; $root.closest('form').submit();" 4309 > 4310 <span class="border-transparent border-b-text">France (EUR 4311 â¬)</span 4312 > 4313 </button> 4314 </li> 4315 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 4316 <button 4317 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 4318 type="button" 4319 4320 @click.prevent="$refs.input.value = 'NZ'; $root.closest('form').submit();" 4321 > 4322 <span class="border-transparent border-b-text">New Zealand (NZD 4323 $)</span 4324 > 4325 </button> 4326 </li> 4327 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 4328 <button 4329 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 4330 type="button" 4331 4332 @click.prevent="$refs.input.value = 'GB'; $root.closest('form').submit();" 4333 > 4334 <span class="border-transparent border-b-text">United Kingdom (GBP 4335 £)</span 4336 > 4337 </button> 4338 </li> 4339 <li class="flex items-center bg-scheme-background px-2 py-2 coarse-pointer:min-h-[44px] coarse-pointer:min-w-[44px]"> 4340 <button 4341 class="break-word text-left [text-wrap:balance] hover:text-scheme-accent" 4342 type="button" 4343 4344 aria-current="true" 4345 4346 @click.prevent="$refs.input.value = 'US'; $root.closest('form').submit();" 4347 > 4348 <span class="border-scheme-text border-b-text">United States (USD 4349 $)</span 4350 > 4351 </button> 4352 </li></ul> 4353 </div> 4354 4355 <input 4356 x-ref="input" 4357 type="hidden" 4358 name="country_code" 4359 id="CountrySelector" 4360 value="US" 4361 > 4362 </data-island> 4363 </div></div></form> 4364 </div> 4365 4366 4367 4368<form 4369 class="my-6 px-section-horizontal-spacing" 4370 action="/search" 4371 method="get" 4372 role="search" 4373 > 4374 <div class="flex w-full max-w-xs items-end"> 4375 <label for="menu-drawer-search" class="sr-only">Search</label> 4376 <input 4377 class="min-w-0 flex-auto border-b-text border-current bg-transparent py-1.5 placeholder-current" 4378 id="menu-drawer-search" 4379 type="text" 4380 name="q" 4381 placeholder="Search" 4382 > 4383 <button 4384 class="px-1" 4385 type="submit" 4386 >
4387 <span class="inline-block h-6 w-6"><svg 4388 class="theme-icon" 4389 xmlns="http://www.w3.org/2000/svg" 4390 fill="none" 4391 viewBox="0 0 24 24" 4392> 4393 <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"/> 4394</svg> 4395</span> 4396 <span class="sr-only">Submit</span> 4397 </button> 4398 </div> 4399 </form> 4400 </div> 4401 </div> 4402 4403 </div> 4404 </section> 4405 4406 <style> 4407 .section-sidebar { 4408 display: block !important; 4409 } 4410 4411 @media (min-width: 1024px) { 4412 .section-sidebar { 4413 display: none !important; 4414 } 4415 } 4416 4417 .sidebar-container { 4418 position: static; 4419 width: 100%; 4420 max-width: 100%; 4421 border-right: 0; 4422 display: none; 4423 } 4424 4425 .section-sidebar:focus-within .sidebar-container { 4426 display: block !important; 4427 } 4428 </style> 4429</noscript> 4430 4431 4432</div>
4432<script> 4433 const calculateHeaderHeights = () => { 4434 const headerGroupHeights = []; 4435 4436 document 4437 .querySelectorAll('.shopify-section-group-header-group') 4438 .forEach((headerGroupSectionEl) => { 4439 headerGroupHeights.push( 4440 headerGroupSectionEl.getBoundingClientRect().height 4441 ); 4442 }); 4443 4444 document.documentElement.style.setProperty( 4445 '--header-group-height', 4446 `${headerGroupHeights.reduce((subtotal, a) => subtotal + a, 0)}px` 4447 ); 4448 }; 4449 4450 calculateHeaderHeights(); 4451 4452 if (document.readyState === 'loading') { 4453 document.addEventListener('DOMContentLoaded', calculateHeaderHeights); 4454 } 4455 window.addEventListener('load', calculateHeaderHeights); 4456 4457 const debouncedCalculateHeaderHeights = debounce(calculateHeaderHeights, 300); 4458 4459 window.addEventListener('resize', debouncedCalculateHeaderHeights); 4460</script>
4460 4461 4462 4463 4464<style> 4465 #MainContent 4466 > .shopify-section.banner-section:first-child 4467 [data-media-container].h-screen { 4468 height: calc(100vh - var(--header-group-height)); 4469 } 4470 4471 @media (min-width: 990px) { 4472 #MainContent 4473 > .shopify-section.banner-section:first-child 4474 [data-media-container].lg\:h-auto { 4475 height: auto; 4476 } 4477 4478 #MainContent 4479 > .shopify-section.banner-section:first-child 4480 [data-media-container].lg\:h-screen { 4481 height: calc(100vh - var(--header-group-height)); 4482 } 4483 } 4484</style> 4485 4486 4487 4488 <main id="MainContent"> 4489 <div id="shopify-section-template--21296458203206__main" class="shopify-section"> 4490 4491 4492 <data-island 4493 id="filterable" 4494 class="border-b-gridline border-gridline-color bg-scheme-background text-scheme-text" 4495 4496 x-data 4497 4498 data-color-scheme="scheme1" 4499 > 4500 <div class="grid gap-gutter bg-gridline-color lg:grid-cols-12"> 4501 <div class="bg-scheme-background px-section-horizontal-spacing pb-theme pt-theme-double text-scheme-text lg:col-span-12"> 4502 <h1 4503 class="font-heading text-heading-standard " 4504 data-main-search-title 4505 > 4506 4507 Search our site 4508 4509 </h1> 4510 </div> 4511 4512 <div class="bg-scheme-background px-section-horizontal-spacing py-2 text-scheme-text lg:col-span-12"> 4513 <form 4514 action="/search" 4515 method="get" 4516 class="input-group search" 4517 role="search" 4518 > 4519 <label for="search-template--21296458203206__main" class="hidden">Search</label> 4520 <div class="flex items-center justify-between"> 4521 <button 4522 class="mr-4 py-2" 4523 type="submit" 4524 > 4525 <span class="mb-1 flex h-6 w-6 items-center"><svg 4526 class="theme-icon" 4527 xmlns="http://www.w3.org/2000/svg" 4528 fill="none" 4529 viewBox="0 0 24 24" 4530> 4531 <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"/> 4532</svg> 4533</span> 4534 <span class="sr-only">Submit</span> 4535 </button> 4536 <input 4537 autofocus 4538 id="search-template--21296458203206__main" 4539 type="text" 4540 name="q" 4541 value="" 4542 placeholder="Search" 4543 class="font-body block w-full bg-transparent pb-1 placeholder-current" 4544 aria-label="Search" 4545 data-search-input 4546 > 4547 </div> 4548 </form> 4549 </div> 4550 </div> 4551 4552 4553 4554 </data-island> 4555 4556 4557 4558</div>
4558<script data-locksmith> 4559 var load = function () { 4560 4561 if (document.querySelectorAll('.locksmith-manual-trigger').length > 0) { 4562 Locksmith.ping(); 4563 } 4564 4565 4566 Locksmith.util.on('submit', 'locksmith-resource-form', function (event) { 4567 event.preventDefault(); 4568 var data = Locksmith.util.serializeForm(event.target); 4569 var options = { spinner: false, container: 'locksmith-content' }; 4570 // a form rendered inline (section replacement) must keep that context 4571 // on resubmit: same enclosing container (there may be several on the 4572 // page), and no layout classes or cancel affordance in the re-render 4573 var inlineContainer = event.target.closest && event.target.closest('[id^="locksmith-content"]'); 4574 if (inlineContainer) { 4575 options.container = inlineContainer; 4576 } 4577 if (event.target.getAttribute('data-locksmith-inline') === 'true') { 4578 options.include_layout_classes = false; 4579 } 4580 Locksmith.postResource(data, options); 4581 }); 4582 4583 Locksmith.util.on('click', 'locksmith-manual-trigger', function (event) { 4584 event.preventDefault(); 4585 Locksmith.postResource({}, { spinner: true, container: document }); 4586 }); 4587 4588 Locksmith.submitPasscode = function (passcode) { 4589 Locksmith.postResource( 4590 { passcode: passcode }, 4591 { spinner: false, container: 'locksmith-content' } 4592 ); 4593 }; 4594 }; 4595 4596 if (typeof Locksmith !== 'undefined') { 4597 load(); 4598 } else { 4599 window.addEventListener('load', load); 4600 } 4601 </script>
4601 4602 </main> 4603 4604 <!-- BEGIN sections: footer-group --> 4605<div id="shopify-section-sections--21296457154630__176903720293717250" class="shopify-section shopify-section-group-footer-group"> 4606 4607 4608 4609</div><div id="shopify-section-sections--21296457154630__footer" class="shopify-section shopify-section-group-footer-group"><footer 4610 class="bg-scheme-background text-scheme-text" 4611 data-color-scheme="scheme2" 4612 data-theme-footer 4613> 4614 4615 <section 4616 class="border-b-gridline border-gridline-color bg-scheme-background py-section-vertical-spacing text-scheme-text" 4617 data-color-scheme="scheme2" 4618> 4619 <div class="justify-center px-section-horizontal-spacing lg:flex lg:items-center lg:justify-between"> 4620 <div class="text-base"> 4621 4622 4623 4624 <div class="[&_a[href]]:underline [&_a[href]]:hover:text-scheme-accent"> 4625 <h2>We occasionally send out <strong>newsletters</strong>. You should sign up â</h2> 4626 </div> 4627 4628 </div> 4629 4630 <div class="mt-theme-half lg:mt-0"> 4631 <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="â" /> 4632 4633 4634 4635 <input type="hidden" name="contact[tags]" value="newsletter"> 4636 <div class="items-end lg:ml-4 lg:flex"> 4637 <label class="sr-only" for="Email-sections--21296457154630__footer">Email address</label> 4638 <input 4639 type="email" 4640 class="font-body block w-full border-b-text border-current bg-transparent pb-1 leading-[inherit] placeholder-current" 4641 name="contact[email]" 4642 id="Email-sections--21296457154630__footer" 4643 value="" 4644 placeholder="Email address" 4645 autocorrect="off" 4646 autocapitalize="off" 4647 > 4648 <button 4649 class="theme-link mt-2 shrink-0 py-1 leading-[inherit] hover:text-scheme-accent lg:ml-2 lg:mt-0" 4650 type="submit" 4651 name="commit" 4652 id="Subscribe" 4653 >Subscribe</button> 4654 </div> 4655 4656 </form> 4657 </div> 4658 </div> 4659</section> 4660 4661 4662 4663 <div class="border-b-gridline border-gridline-color"> 4664 <div 4665 class="grid lg:grid-cols-var bg-gridline-color" 4666 style="--grid-cols: 12;" 4667 ><div 4668 class="break-word bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text lg:col-span-var" 4669 style="--col-span: 3;" 4670 4671 ><div class="inline-block text-left"> 4672 4673 4674 <h2 class="font-heading mb-4 text-base"> 4675 Explore 4676 </h2> 4677 4678 <ul class="list-none space-y-1"> 4679 4680<li> 4681 <a 4682 href="/pages/all-products" 4683 class="hover:text-scheme-accent" 4684 > 4685 Products 4686 </a> 4687 </li> 4688 4689<li> 4690 <a 4691 href="/pages/services" 4692 class="hover:text-scheme-accent" 4693 > 4694 Services 4695 </a> 4696 </li> 4697 4698<li> 4699 <a 4700 href="https://www.theprintroom.nz/apps/order-tracker" 4701 class="hover:text-scheme-accent" 4702 > 4703 Track your order 4704 </a> 4705 </li> 4706 4707<li> 4708 <a 4709 href="/pages/responsibility" 4710 class="hover:text-scheme-accent" 4711 > 4712 Responsibility 4713 </a> 4714 </li> 4715 4716<li> 4717 <a 4718 href="/pages/about-print-room" 4719 class="hover:text-scheme-accent" 4720 > 4721 About us 4722 </a> 4723 </li> 4724 4725 </ul> 4726 </div></div><div 4727 class="break-word bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text lg:col-span-var" 4728 style="--col-span: 3;" 4729 4730 ><div class="inline-block text-left"> 4731 4732 4733 <h2 class="font-heading mb-4 text-base"> 4734 Helpful stuff 4735 </h2> 4736 4737 <ul class="list-none space-y-1"> 4738 4739<li> 4740 <a 4741 href="/pages/screen-printing-faqs-the-print-room-quality-screen-printing-garment-design-blank-clothing" 4742 class="hover:text-scheme-accent" 4743 > 4744 FAQs 4745 </a> 4746 </li> 4747 4748<li> 4749 <a 4750 href="https://help.theprintroom.nz/" 4751 class="hover:text-scheme-accent" 4752 > 4753 Resource hub 4754 </a> 4755 </li> 4756 4757<li> 4758 <a 4759 href="/pages/catalogue" 4760 class="hover:text-scheme-accent" 4761 > 4762 Catalogues 4763 </a> 4764 </li> 4765 4766<li> 4767 <a 4768 href="/blogs/the-print-room-nz" 4769 class="hover:text-scheme-accent" 4770 > 4771 Blogs 4772 </a> 4773 </li> 4774 4775<li> 4776 <a 4777 href="/pages/policies" 4778 class="hover:text-scheme-accent" 4779 >
4780 Policies & T&Cs 4781 </a> 4782 </li> 4783 4784 </ul> 4785 </div></div><div 4786 class="break-word bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text lg:col-span-var" 4787 style="--col-span: 3;" 4788 4789 > 4790 <h2 class="font-heading break-word mb-4 text-base"> 4791 Get in touch - NZ 4792 </h2> 4793 4794<div class="rte"> 4795 <p>21 Grosvenor St, Kensington, Dunedin,<br/>9012<br/>[email protected]<br/>NZ: 03 425 9694</p> 4796 </div></div><div 4797 class="break-word bg-scheme-background px-section-horizontal-spacing py-section-vertical-spacing text-scheme-text lg:col-span-var" 4798 style="--col-span: 3;" 4799 4800 > 4801 <h2 class="font-heading break-word mb-4 text-base"> 4802 Get in touch - AUS 4803 </h2> 4804 4805<div class="rte"> 4806 <p>The Commons, 10â20 Gwynne St, Cremorne VIC 3121<br/>[email protected]<br/>+61 (0) 451 701 385</p> 4807 </div></div></div> 4808 </div> 4809 4810 4811 <div> 4812 <div class="px-section-horizontal-spacing py-section-vertical-spacing lg:flex lg:flex-wrap lg:items-center lg:justify-between"> 4813 <div class="mb-4 space-y-2 text-sm lg:mb-0 lg:flex-1"> 4814 <p> 4815 © 2026, 4816 <a href="/" title="">The Print Room</a>. 4817 </p> 4818 <ul class="flex flex-wrap gap-1 text-sm [&>li:last-child]:after:content-none [&>li]:after:content-['\00B7']"> 4819 <li> 4820 4821 </li></ul> 4822 </div> 4823 4824</div> 4825 </div> 4826</footer> 4827 4828 4829 <style> 4830 .footer-logo-image { 4831 display: block; 4832 max-width: px; 4833 } 4834 </style> 4835 4836 4837 4838<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> 4839<!-- END sections: footer-group --><!-- BEGIN sections: overlay-group --> 4840<div id="shopify-section-sections--21296457220166__promo-popup" class="shopify-section shopify-section-group-overlay-group contents"> 4841 4842 4843</div><div id="shopify-section-sections--21296457220166__age-check" class="shopify-section shopify-section-group-overlay-group contents"> 4844</div><div id="shopify-section-sections--21296457220166__privacy-banner" class="shopify-section shopify-section-group-overlay-group contents"> 4845 4846 4847</div> 4848<!-- END sections: overlay-group --> 4849 4850 <div 4851 id="screenreader-announce" 4852 class="sr-only" 4853 aria-live="polite" 4854 role="status" 4855 ></div> 4856 4857 <ul hidden> 4858 <li id="a11y-refresh-page-message"> 4859 Choosing a selection results in a full page refresh. 4860 </li> 4861 <li id="a11y-selection-message"> 4862 Press the space key then arrow keys to make a selection. 4863 </li> 4864 </ul> 4865 4866 4867 <data-island 4868 role="complementary" 4869 aria-labelledby="left-drawer-slot" 4870 x-data 4871 on="load" 4872> 4873 <template x-teleport="body"> 4874 <div 4875 x-show="$store.modals.leftDrawer.open" 4876 @keydown.escape.prevent.stop="$store.modals.close('leftDrawer')" 4877 @click="$store.modals.close('leftDrawer')" 4878 class="fixed inset-0 z-110" 4879 data-color-scheme="scheme1" 4880 id="modals-leftDrawer" 4881 > 4882 <div 4883 @click.stop 4884 x-show="$store.modals.leftDrawer.open" 4885 x-transition:enter="duration-300 motion-reduce:duration-0 outline-0" 4886 x-transition:enter-start="opacity-0 -translate-x-full" 4887 x-transition:leave="duration-300 motion-reduce:duration-0 outline-0" 4888 x-transition:leave-end="-translate-x-full" 4889 x-trap.noscroll.inert="$store.modals.leftDrawer.open" 4890 class="mr-auto h-full w-11/12 max-w-md transform overflow-y-auto border-r-gridline border-gr
4890idline-color bg-scheme-background text-scheme-text transition-transform" 4891 id="left-drawer-slot" 4892 role="dialog" 4893 @left-drawer-is-open.window="setTimeout(() => { $el.setAttribute('aria-modal', 'true') }, 120)" 4894 @left-drawer-is-closed.window="setTimeout(() => { $el.removeAttribute('aria-modal') }, 120)" 4895 :aria-label="getModalLabel('leftDrawer', $el)" 4896 tabindex="-1" 4897 > 4898 <!-- Modal content is teleported here --> 4899 </div> 4900 </div> 4901 </template> 4902</data-island> 4903<data-island 4904 role="complementary" 4905 aria-labelledby="right-drawer-slot" 4906 x-data 4907 on="load" 4908> 4909 <template x-teleport="body"> 4910 <div 4911 x-show="$store.modals.rightDrawer.open" 4912 @keydown.escape.prevent.stop="$store.modals.close('rightDrawer')" 4913 @click="$store.modals.close('rightDrawer')" 4914 class="fixed inset-0 z-110" 4915 style="background: rgba(208,208,208,0.2); backdrop-filter: blur(1.5px); -webkit-backdrop-filter: blur(1.5px);" 4916 data-color-scheme="scheme1" 4917 id="modals-rightDrawer" 4918 > 4919 <div 4920 @click.stop 4921 x-show="$store.modals.rightDrawer.open" 4922 x-transition:enter="duration-300 motion-reduce:duration-0 outline-0" 4923 x-transition:enter-start="translate-x-full" 4924 x-transition:leave="duration-300 motion-reduce:duration-0 outline-0" 4925 x-transition:leave-end="translate-x-full" 4926 x-trap.noscroll.inert="$store.modals.rightDrawer.open" 4927 class="ml-auto h-full w-11/12 max-w-lg transform overflow-y-auto bg-scheme-background text-scheme-text" 4928 style="border-left: 2px solid black;" 4929 id="right-drawer-slot" 4930 role="dialog" 4931 @right-drawer-is-open.window="setTimeout(() => { $el.setAttribute('aria-modal', 'true') }, 120)" 4932 @right-drawer-is-closed.window="setTimeout(() => { $el.removeAttribute('aria-modal') }, 120)" 4933 :aria-label="getModalLabel('rightDrawer', $el)" 4934 tabindex="-1" 4935 > 4936 <!-- Modal content is teleported here --> 4937 </div> 4938 </div> 4939 </template> 4940</data-island> 4941<data-island 4942 role="complementary" 4943 aria-labelledby="quick-buy-drawer-slot-container" 4944 x-data 4945 on="load" 4946> 4947 <template x-teleport="body"> 4948 <div 4949 x-show="$store.modals.quickBuyDrawer.open" 4950 @keydown.escape.prevent.stop="$store.modals.close('quickBuyDrawer')" 4951 @click="$store.modals.close('quickBuyDrawer')" 4952 class="fixed inset-0 z-110 flex lg:block" 4953 data-color-scheme="scheme1" 4954 id="modals-quickBuyDrawer" 4955 > 4956 <div 4957 @click.stop 4958 id="quick-buy-drawer-slot-container" 4959 x-show="$store.modals.quickBuyDrawer.open" 4960 x-transition:enter="duration-300 motion-reduce:duration-0 outline-0" 4961 x-transition:enter-start="max-lg:translate-y-full lg:translate-x-full" 4962 x-transition:leave="duration-300 motion-reduce:duration-0 outline-0" 4963 x-transition:leave-end="max-lg:translate-y-full lg:translate-x-full" 4964 x-trap.noscroll.inert="$store.modals.quickBuyDrawer.open" 4965 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" 4966 role="dialog" 4967 @quick-buy-drawer-is-open.window="setTimeout(() => { $el.setAttribute('aria-modal', 'true') }, 120)" 4968 @quick-buy-drawer-is-closed.window="setTimeout(() => { $el.removeAttribute('aria-modal') }, 120)" 4969 :aria-label="getModalLabel('quickBuyDrawer', document.getElementById('quick-buy-drawer-slot'))" 4970 tabindex="-1" 4971 > 4972 <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"> 4973 <div> 4974 Choose options 4975 </div> 4976 <button 4977 @click.prevent="$store.modals.close('quickBuyDrawer')" 4978 class="absolute right-0 top-0 block h-full" 4979 type="button" 4980 > 4981 <span class="sr-only">Close</span> 4982 <div class="my-auto mr-section-horizontal-spacing h-6 w-6"> 4983 <svg 4984 class="theme-icon" 4985 xmlns="http://www.w3.org/2000/svg" 4986 fill="none" 4987 viewBox="0 0 24 24" 4988> 4989 <path stroke="currentColor" d="m1.5 1.5 21 21m0-21-21 21" vector-effect="non-scaling-stroke"/> 4990</svg> 4991 4992 </div> 4993 </button> 4994 </div> 4995 <div 4996 id="quick-buy-drawer-slot" 4997 class="max-lg:h-fit max-lg:max-h-[65vh] max-lg:overflow-y-auto" 4998 ></div> 4999 </div> 5000 </div> 5001 </template> 5002</data-island> 5003<data-island 5004 x-data 5005 on="load" 5006> 5007 <template x-teleport="body"> 5008 <div 5009 x-show="$store.modals.promo.open" 5010 class="pointer-events-none fixed inset-0 z-110" 5011 id="modals-promo" 5012 > 5013 <div 5014 x-show="$store.modals.promo.open" 5015 class="flex h-full w-full" 5016 > 5017 <div 5018 x-show="$store.modals.promo.open" 5019 x-transition:enter="transition duration-300 motion-reduce:duration-0 delay-75 outline-0" 5020 x-transition:enter-start="translate-y-full" 5021 x-transition:enter-end="translate-y-0" 5022 x-transition:leave="transition duration-300 motion-reduce:duration-0 outline-0" 5023 x-transition:leave-start="translate-y-0" 5024 x-transition:leave-end="translate-y-full" 5025 class="pointer-events-auto relative bottom-0 left-0 right-0 top-auto mt-auto w-full overflow-y-auto" 5026 id="promo-slot" 5027 role="dialog" 5028 @promo-is-open.window="setTimeout(() => { $el.setAttribute('aria-modal', 'true') }, 120)" 5029 @promo-is-closed.window="setTimeout(() => { $el.removeAttribute('aria-modal') }, 120)" 5030 :aria-label="getModalLabel('promo', $el)" 5031 tabindex="-1" 5032 > 5033 <!-- Modal content is teleported here --> 5034 </div> 5035 </div> 5036 </div> 5037 </template> 5038</data-island> 5039<data-island x-data on="load"> 5040 <template x-teleport="body"> 5041 <div 5042 x-show="$store.modals.popup.open" 5043 @keydown.escape.prevent.stop="$store.modals.close('popup')" 5044 @click="$store.modals.close('popup')" 5045 class="fixed inset-0 z-110 p-8 lg:p-24" 5046 data-color-scheme="scheme1" 5047 id="modals-popup" 5048 > 5049 <div 5050 x-show="$store.modals.popup.open" 5051 class="fixed inset-0 bg-transparent" 5052 > 5053 <!-- Overlay --> 5054 </div> 5055 <div 5056 x-show="$store.modals.popup.open" 5057 class="flex h-full w-full" 5058 > 5059 <div 5060 @click.stop 5061 x-show="$store.modals.popup.open" 5062 x-trap.noscroll.inert="$store.modals.popup.open" 5063 class="relative m-auto max-h-full w-full max-w-2xl overflow-y-auto border-gr
5063idline border-gridline-color bg-scheme-background text-scheme-text" 5064 id="popup-slot" 5065 role="dialog" 5066 @popup-is-open.window="setTimeout(() => { $el.setAttribute('aria-modal', 'true') }, 120)" 5067 @popup-is-closed.window="setTimeout(() => { $el.removeAttribute('aria-modal') }, 120)" 5068 :aria-label="getModalLabel('popup', $el)" 5069 tabindex="-1" 5070 > 5071 <!-- Modal content is teleported here --> 5072 </div> 5073 </div> 5074 </div> 5075 </template> 5076</data-island> 5077<data-island x-data on="load"> 5078 <template x-teleport="body"> 5079 <div 5080 x-show="$store.modals.modal.open" 5081 x-transition:enter="transition ease-out duration-300" 5082 x-transition:enter-start="opacity-0" 5083 x-transition:enter-end="opacity-100" 5084 x-transition:leave="transition ease-in duration-200" 5085 x-transition:leave-start="opacity-100" 5086 x-transition:leave-end="opacity-0" 5087 @keydown.escape.prevent.stop="$store.modals.close('modal')" 5088 @click="$store.modals.close('modal')" 5089 class="fixed inset-0 z-110 bg-black/40 backdrop-blur-md" 5090 style="backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);" 5091 data-color-scheme="scheme1" 5092 id="modals-modal" 5093 > 5094 <div 5095 x-show="$store.modals.modal.open" 5096 class="flex h-full w-full justify-center p-2 sm:p-4 md:p-6 lg:p-8" 5097 :class="$store.modals.modal.contents === 'quoteRequest' ? 'items-stretch sm:items-center sm:p-6 lg:p-10' : 'items-center'" 5098 > 5099 <div 5100 @click.stop 5101 x-show="$store.modals.modal.open" 5102 x-transition:enter="transition ease-out duration-300" 5103 x-transition:enter-start="opacity-0 scale-95 translate-y-4" 5104 x-transition:enter-end="opacity-100 scale-100 translate-y-0" 5105 x-transition:leave="transition ease-in duration-200" 5106 x-transition:leave-start="opacity-100 scale-100 translate-y-0" 5107 x-transition:leave-end="opacity-0 scale-95 translate-y-4" 5108 x-trap.inert="$store.modals.modal.open" 5109 class="relative flex w-full flex-col overflow-hidden text-scheme-text" 5110 :class="$store.modals.modal.contents === 'quoteRequest' 5111 ? 'max-w-2xl max-h-[100dvh] sm:max-h-[calc(100dvh-48px)] rounded-none sm:rounded-[24px]' 5112 : '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]'" 5113 style="background: #FBFBF6; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);" 5114 id="modal-slot" 5115 role="dialog" 5116 @modal-is-open.window="setTimeout(() => { $el.setAttribute('aria-modal', 'true') }, 120)" 5117 @modal-is-closed.window="setTimeout(() => { $el.removeAttribute('aria-modal') }, 120)" 5118 :aria-label="getModalLabel('modal', $el)" 5119 tabindex="-1" 5120 > 5121 <!-- Modal content is teleported here --> 5122 </div> 5123 </div> 5124 </div> 5125 </template> 5126</data-island> 5127 5128 5129 5130 5131 5132 5133 <style> 5134 /* Push chatbot left when quote drawer is open */ 5135 body:has([data-favorites-drawer]:not([style*="display: none"])) #tidio-chat, 5136 body:has([data-favorites-drawer]:not([style*="display: none"])) .tidio-chat, 5137 body:has([data-favorites-drawer]:not([style*="display: none"])) iframe[title*="chat" i], 5138 body:has([data-favorites-drawer]:not([style*="display: none"])) iframe[title*="tidio" i], 5139 body:has([data-favorites-drawer]:not([style*="display: none"])) [class*="chat-widget"], 5140 body:has([data-favorites-drawer]:not([style*="display: none"])) [id*="chat-widget"] { 5141 transform: translateX(-464px) !important; 5142 transition: transform 0.3s ease !important; 5143 } 5144 5145 /* Push AI chatbot trigger left when drawer is open - desktop only */ 5146 @media (min-width: 768px) { 5147 body:has([data-favorites-drawer]:not([style*="display: none"])) .ai-chatbot__trigger { 5148 right: calc(32rem + 24px) !important; 5149 transition: right 0.3s ease, transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease !important; 5150 } 5151 } 5152 5153 /* Override theme color scheme â force black text throughout drawer */ 5154 [data-favorites-drawer] { 5155 --color-scheme-text: 0 0 0 !important; 5156 } 5157 [data-favorites-drawer] h2 { 5158 letter-spacing: 0px !important; 5159 } 5160 @media (max-width: 639px) { 5161 [data-favorites-drawer] h2 { 5162 text-align: left !important; 5163 } 5164 } 5165 [data-favorites-drawer] *, 5166 [data-favorites-drawer] h2, 5167 [data-favorites-drawer] p, 5168 [data-favorites-drawer] a, 5169 [data-favorites-drawer] span, 5170 [data-favorites-drawer] div, 5171 [data-favorites-drawer] li { 5172 color: black !important; 5173 } 5174 5175 /* Close button stays muted */ 5176 [data-favorites-drawer] button[aria-label*="Close"], 5177 [data-favorites-drawer] button[aria-label*="Close"] svg { 5178 color: rgba(0,0,0,0.4) !important; 5179 } 5180 5181 /* Remove button stays muted, red on hover */ 5182 [data-favorites-drawer] button[aria-label*="Remove"],
5183 [data-favorites-drawer] button[aria-label*="Remove"] svg { 5184 color: rgba(0,0,0,0.3) !important; 5185 } 5186 [data-favorites-drawer] button[aria-label*="Remove"]:hover, 5187 [data-favorites-drawer] button[aria-label*="Remove"]:hover svg { 5188 color: #ef4444 !important; 5189 } 5190 5191 /* Product dividers â solid black */ 5192 [data-favorites-drawer] li { 5193 border-bottom: 1px solid black !important; 5194 } 5195 [data-favorites-drawer] li:last-child { 5196 border-bottom: none !important; 5197 } 5198 5199 /* Footer dividers â solid black */ 5200 [data-favorites-drawer] .drawer-divider { 5201 border-top: 1px solid black !important; 5202 } 5203 5204 /* Start quote button â visible border */ 5205 [data-favorites-drawer] .drawer-cta-btn { 5206 border: 2px solid #4B4D72 !important; 5207 color: #4B4D72 !important; 5208 } 5209 [data-favorites-drawer] .drawer-cta-btn:hover { 5210 background-color: #4B4D72 !important; 5211 color: #fff !important; 5212 } 5213</style> 5214 5215<data-island 5216 x-data="FavoritesDrawer" 5217 on="idle" 5218 x-cloak 5219> 5220 <div> 5221 <template x-teleport="#right-drawer-slot"> 5222 <div 5223 class="flex h-full flex-col overflow-hidden" style="background: #FBFBF6;" 5224 :data-modal-label="`Your current project - ${$store.favorites.countWithText()}`" 5225 x-show="$store.modals.rightDrawer.contents === 'favorites'" 5226 data-favorites-drawer 5227 ><div class="relative shrink-0" style="padding: 80px 40px 24px;"> 5228 <button 5229 @click.prevent="$store.modals.close('favorites')" 5230 class="absolute rounded-full p-2 transition-colors" 5231 style="top: 19px; right: 19px; color: rgba(0,0,0,0.4);" 5232 type="button" 5233 > 5234 <span class="sr-only">Close project drawer</span> 5235 <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> 5236 </button> 5237 <h2 id="FavoritesTitle" tabindex="-1" class="font-bold" style="font-size: 41px; letter-spacing: 0px; line-height: 1; color: black; text-align: center;"> 5238 Your current project 5239 </h2> 5240 </div><div class="flex-1 overflow-y-auto" style="padding: 20px 40px; min-height: 0;"><template x-if="$store.favorites.count === 0"> 5241 <div class="flex flex-col items-center justify-center py-12 text-center"> 5242 <p class="mb-2 text-base font-medium text-scheme-text">No products yet</p> 5243 <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> 5244 <a 5245 href="/collections/product-library" 5246 class="inline-flex items-center justify-center font-light transition" 5247 style="border: 2px solid #4B4D72; color: #4B4D72; border-radius: 50px; padding: 18px 48px; font-size: 24px;" 5248 onmouseover="this.style.backgroundColor='#4B4D72'; this.style.color='#fff';" 5249 onmouseout="this.style.backgroundColor='transparent'; this.style.color='#4B4D72';" 5250 @click="$store.modals.close('favorites')" 5251 > 5252 Browse Products 5253 </a> 5254 </div> 5255 </template><template x-if="$store.favorites.count > 0"> 5256 <ul> 5257 <template x-for="item in $store.favorites.items" :key="item.key"> 5258 <li class="flex items-center" style="padding: 20px 0; gap: 16px;"> 5259 <button 5260 @click="$store.favorites.remove(item.key)" 5261 class="shrink-0 rounded-full p-1 transition-colors hover:text-red-500" 5262 style="color: rgba(0,0,0,0.3);" 5263 :aria-label="'Remove ' + item.title" 5264 > 5265 <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> 5266 </button> 5267 <a :href="item.url" class="block shrink-0 overflow-hidden bg-gray-100" style="width: 90px; height: 90px;"> 5268 <img :src="item.image" :alt="item.title" class="h-full w-full object-cover" loading="lazy" width="90" height="90"> 5269 </a> 5270 <div class="min-w-0 flex-1"> 5271 <p style="font-size: 16px; font-weight: 300; line-height: 18px; color: black;" x-text="item.vendor || ''"></p> 5272 <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> 5273 <p class="text-xs text-gray-600" x-text="item.colour || (item.hasColours ? 'Colour TBC' : '')"></p> 5274 </div> 5275 </li> 5276 </template> 5277 </ul> 5278 </template> 5279 </div><div class="shrink-0" style="padding: 0 40px 48px;"> 5280 <template x-if="$store.favorites.count > 0"> 5281 <div>
5282 <div class="drawer-divider" style="padding-top: 28px;"> 5283 <p style="font-size: 23px; font-weight: 300; line-height: 30px;">Get a quote for these products.</p> 5284 </div> 5285 <div class="drawer-divider" style="margin-top: 24px; padding-top: 24px;"> 5286 <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> 5287 </div> 5288 <button 5289 @click="$store.modals.close('favorites'); setTimeout(() => $store.modals.open('quoteRequest'), 300)" 5290 class="drawer-cta-btn inline-flex w-full items-center justify-center text-center transition" 5291 style="margin-top: 24px; min-height: 79px; border-radius: 50px; font-size: 27px; font-weight: 300;" 5292 > 5293 Start quote request 5294 </button> 5295 </div> 5296 </template> 5297 </div> 5298 </div> 5299 </template> 5300 </div> 5301</data-island> 5302 5303 5304 5305 <style> 5306 :root { 5307 --color-quote-accent: #2B3990; 5308 } 5309 5310 /* Modal inputs */ 5311 .qr-input, 5312 .qr-select { 5313 width: 100%; 5314 min-height: 2.15rem; 5315 border: 0.666px solid black; 5316 border-radius: 9999px; 5317 padding: 0.5rem 1rem; 5318 background: transparent; 5319 color: #111827; 5320 font-size: 0.875rem; 5321 transition: border-color 0.2s ease, box-shadow 0.2s ease; 5322 } 5323 5324 .qr-textarea { 5325 width: 100%; 5326 border: 0.75px solid black; 5327 border-radius: 10px; 5328 padding: 0.75rem 1rem; 5329 background: transparent; 5330 color: #111827; 5331 font-size: 0.875rem; 5332 resize: vertical; 5333 transition: border-color 0.2s ease, box-shadow 0.2s ease; 5334 } 5335 5336 .qr-input:focus, 5337 .qr-select:focus, 5338 .qr-textarea:focus { 5339 outline: none; 5340 border-color: var(--color-quote-accent, #2B3990); 5341 box-shadow: 0 0 0 3px rgba(43, 57, 144, 0.1); 5342 } 5343 5344 /* Ensure date & select inputs stay pill-shaped */ 5345 input[type="date"].qr-input, 5346 select.qr-select { 5347 border-radius: 9999px !important; 5348 padding-left: 1rem; 5349 padding-right: 2.5rem; 5350 } 5351 5352 input[type="date"].qr-input::-webkit-calendar-picker-indicator { 5353 opacity: 0.4; 5354 cursor: pointer; 5355 } 5356 5357 /* Budget slider */ 5358 .qr-slider { 5359 -webkit-appearance: none; 5360 appearance: none; 5361 width: 100%; 5362 height: 28px; 5363 background: transparent; 5364 outline: none; 5365 cursor: pointer; 5366 position: relative; 5367 z-index: 2; 5368 touch-action: none; 5369 margin: 0; 5370 padding: 0; 5371 } 5372 5373 .qr-slider::-webkit-slider-runnable-track { 5374 height: 6px; 5375 border-radius: 9999px; 5376 background: var(--slider-track, #e5e7eb); 5377 cursor: pointer; 5378 } 5379 5380 .qr-slider::-webkit-slider-thumb { 5381 -webkit-appearance: none; 5382 appearance: none; 5383 width: 24px; 5384 height: 24px; 5385 border-radius: 50%; 5386 background: #658a6a; 5387 cursor: grab; 5388 box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15); 5389 margin-top: -9px; 5390 border: 2px solid #fff; 5391 } 5392 5393 .qr-slider::-webkit-slider-thumb:active { 5394 cursor: grabbing; 5395 transform: scale(1.1); 5396 box-shadow: 0 3px 8px rgba(0, 0, 0, 0.2); 5397 } 5398 5399 .qr-slider::-moz-range-track { 5400 height: 6px; 5401 border-radius: 9999px; 5402 background: var(--slider-track, #e5e7eb); 5403 cursor: pointer; 5404 } 5405 5406 .qr-slider::-moz-range-thumb { 5407 width: 24px; 5408 height: 24px; 5409 border: 2px solid #fff; 5410 border-radius: 50%; 5411 background: #658a6a; 5412 cursor: grab; 5413 box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15); 5414 } 5415 5416 .qr-slider::-moz-range-thumb:active { 5417 cursor: grabbing; 5418 } 5419 5420 .qr-slider::-moz-range-progress { 5421 height: 6px; 5422 border-radius: 9999px; 5423 background: #658a6a; 5424 } 5425 5426 /* Pill buttons for per-product fields */ 5427 .qr-pill { 5428 display: inline-flex; 5429 height: 23px; 5430 align-items: center; 5431 justify-content: center; 5432 gap: 0.25rem; 5433 border: 0.666px solid black; 5434 border-radius: 9999px; 5435 padding: 0 0.75rem; 5436 background: #eee; 5437 color: #111827; 5438 font-size: 10.65px; 5439 font-weight: 400; 5440 cursor: pointer; 5441 transition: border-color 0.15s, background 0.15s; 5442 white-space: nowrap; 5443 position: relative; 5444 } 5445 5446 .qr-pill:hover { 5447 border-color: black; 5448 background: #e2e2e2; 5449 } 5450 5451 .qr-pill--active { 5452 border-color: black; 5453 color: #111827; 5454 background: #e2e2e2; 5455 } 5456 5457 .qr-pill--required { 5458 border-color: #dc2626; 5459 } 5460 5461 /* Pills grid: fixed equal columns across all rows */ 5462 .qr-pills-row { 5463 display: grid; 5464 grid-template-columns: repeat(3, 1fr); 5465 } 5466 5467 /* Popover for pill fields */ 5468 .qr-popover { 5469 position: absolute; 5470 top: calc(100% + 6px); 5471 left: 0; 5472 z-index: 50; 5473 min-width: 14rem; 5474 border: 0.666px solid black; 5475 border-radius: 8px; 5476 background: #fff; 5477 padding: 0.75rem; 5478 box-shadow: 0 3px 7px 0 rgba(0, 0, 0, 0.4); 5479 } 5480 5481 /* Product item rows */ 5482 .qr-product-row { 5483 border-bottom: 1px solid black !important; 5484 padding: 0.75rem 0; 5485 } 5486 5487 .qr-product-row:last-child { 5488 border-bottom: none !important; 5489 } 5490 5491 /* Submit button */ 5492 .qr-submit { 5493 display: flex; 5494 height: 70px; 5495 width: 100%; 5496 max-width: 351px; 5497 margin-left: auto; 5498 margin-right: auto; 5499 align-items: center; 5500 justify-content: center; 5501 border-radius: 50px; 5502 border: 2px solid #4B4D72; 5503 padding: 0.85rem 1.5rem; 5504 background: #4B4D72; 5505 color: #fff; 5506 font-size: 1.5rem; 5507 font-weight: 400; 5508 transition: opacity 0.2s ease, transform 0.2s ease; 5509 } 5510 5511 .qr-submit:hover { 5512 background: #3d3f5e; 5513 border-color: #3d3f5e; 5514 transform: translateY(-1px); 5515 } 5516 5517 .qr-submit:disabled { 5518 opacity: 0.4;
5519 cursor: not-allowed; 5520 transform: none; 5521 } 5522 5523 /* Outlined button */ 5524 .qr-btn-outline { 5525 display: inline-flex; 5526 min-height: 2.75rem; 5527 align-items: center; 5528 justify-content: center; 5529 border: 1.5px solid #4B4D72; 5530 border-radius: 9999px; 5531 padding: 0.65rem 1.5rem; 5532 background: transparent; 5533 color: #4B4D72; 5534 font-size: 0.875rem; 5535 font-weight: 600; 5536 transition: background-color 0.2s ease, color 0.2s ease; 5537 } 5538 5539 .qr-btn-outline:hover { 5540 background: #4B4D72; 5541 color: #fff; 5542 } 5543 5544 @media (max-width: 639px) { 5545 .qr-popover { 5546 position: fixed; 5547 top: auto; 5548 bottom: 0; 5549 left: 0; 5550 right: 0; 5551 min-width: 100%; 5552 border-radius: 8px 8px 0 0; 5553 padding: 1rem; 5554 box-shadow: 0 -3px 7px 0 rgba(0, 0, 0, 0.4); 5555 } 5556 } 5557 5558 /* Fix: Tailwind arbitrary rounded class not compiled */ 5559 @media (min-width: 640px) { 5560 .sm\:rounded-\[24px\] { 5561 border-radius: 27px; 5562 } 5563 } 5564 5565 /* Fix: Tailwind sm:grid-cols-2 not compiled in this theme */ 5566 @media (min-width: 640px) { 5567 [data-quote-request-modal] .sm\:grid-cols-2 { 5568 grid-template-columns: repeat(2, minmax(0, 1fr)); 5569 } 5570 } 5571 5572 /* Make overlay scroll instead of modal body */ 5573 #modals-modal:has([data-quote-request-modal]) { 5574 overflow-y: auto; 5575 } 5576 5577 /* Flex container: min-height instead of fixed height, always center */ 5578 #modals-modal:has([data-quote-request-modal]) > div { 5579 height: auto; 5580 min-height: 100%; 5581 align-items: center; 5582 } 5583 5584 /* Card: remove max-height constraint, allow natural sizing, always rounded */ 5585 #modals-modal:has([data-quote-request-modal]) #modal-slot { 5586 max-height: none !important; 5587 overflow: visible !important; 5588 border-radius: 27px; 5589 border: 1.75px solid black; 5590 box-shadow: 0px 4px 13px 2px rgba(0, 0, 0, 0.1); 5591 } 5592 5593 /* Fix: Tailwind sm:flex-nowrap not compiled */ 5594 @media (min-width: 640px) { 5595 .qr-product-row { 5596 flex-wrap: nowrap; 5597 } 5598 } 5599 5600 /* Content div: match card rounding */ 5601 [data-quote-request-modal] { 5602 border-radius: 27px; 5603 overflow: visible !important; 5604 } 5605 5606 /* All modal text defaults to black per Figma */ 5607 [data-quote-request-modal] label, 5608 [data-quote-request-modal] h3, 5609 [data-quote-request-modal] p, 5610 [data-quote-request-modal] span { 5611 color: black; 5612 } 5613 5614 /* Preserve intentional non-black colors */ 5615 [data-quote-request-modal] .text-gray-400 { 5616 color: #9ca3af !important; 5617 } 5618 [data-quote-request-modal] .text-emerald-600 { 5619 color: #059669 !important; 5620 } 5621 [data-quote-request-modal] .text-red-500 { 5622 color: #ef4444 !important; 5623 } 5624 /* Keep submit button text white */ 5625 [data-quote-request-modal] .qr-submit span { 5626 color: #fff !important; 5627 } 5628 5629 /* Modal title letter spacing */ 5630 [data-quote-request-modal] h2 { 5631 letter-spacing: 0px !important; 5632 } 5633 5634 /* All labels should be black per Figma */ 5635 [data-quote-request-modal] label { 5636 color: black !important; 5637 } 5638 5639 /* Placeholder text should be grey, not blue */ 5640 [data-quote-request-modal] textarea::placeholder, 5641 [data-quote-request-modal] input::placeholder { 5642 color: #9ca3af !important; 5643 } 5644</style> 5645 5646<data-island 5647 x-data="QuoteRequestForm" 5648 on="idle" 5649 x-cloakdata-webhook-url="https://print-room-chatbot-api.vercel.app/api/quote-request" 5650 data-turnstile-site-key="0x4AAAAAAETPnb_3iHel2J69" 5651> 5652 <template x-teleport="#modal-slot"> 5653 <div 5654 x-show="$store.modals.modal.contents === 'quoteRequest'" 5655 class="flex w-full flex-col h-full" 5656 style="background: #FBFBF6;" 5657 data-quote-request-modal 5658 ><div class="shrink-0 px-5 py-4 sm:px-8 sm:py-5"> 5659 <div class="flex items-center justify-between"> 5660 <h2 x-show="!successMessage" class="font-bold" style="font-size: 2.75rem; letter-spacing: 0px; color: black;">Project quote request</h2> 5661 <div x-show="successMessage" class="flex-1"></div> 5662 <button 5663 @click.prevent="$store.modals.close('quoteRequest')" 5664 type="button" 5665 class="rounded-full p-2 text-gray-400 transition hover:text-gray-600" 5666 > 5667 <span class="sr-only">Close</span> 5668 <svg width="20" height="20" fill="none" viewBox="0 0 24 24">
5668<path stroke="currentColor" stroke-width="2" d="m6 6 12 12m0-12-12 12"/></svg> 5669 </button> 5670 </div> 5671 </div><div class="overflow-y-auto flex-1 px-5 py-5 sm:px-8 sm:py-6"> 5672 <div class="mx-auto max-w-2xl"> 5673 <template x-if="!successMessage"> 5674 <form @submit.prevent="submitQuote" class="space-y-8"><section style="padding-bottom: 2rem;"> 5675 <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"> 5676 <div class="mt-3"> 5677 <template x-for="item in $store.chatQuote.items" :key="item.id"> 5678 <div class="qr-product-row flex items-start gap-3"> 5679 <div class="shrink-0 overflow-hidden rounded-lg bg-gray-100" style="width: 53px; height: 53px;"> 5680 <template x-if="item.image"> 5681 <img :src="item.image" :alt="item.title" class="h-full w-full object-cover" width="53" height="53"> 5682 </template> 5683 </div> 5684 <div class="min-w-0 flex-1"> 5685 <p class="text-sm font-semibold text-gray-900" x-text="item.title"></p> 5686 <div class="mt-2 flex flex-wrap gap-2"> 5687 <span x-show="item.quantity" class="qr-pill" x-text="'Qty ' + item.quantity"></span> 5688 <span x-show="item.colors && item.colors.length > 0" class="qr-pill" x-text="item.colors.join(', ')"></span> 5689 <span x-show="item.sizes && item.sizes.length > 0" class="qr-pill" x-text="item.sizes.join(', ')"></span> 5690 <span x-show="item.decorationMethod" class="qr-pill" x-text="item.decorationMethod"></span> 5691 </div> 5692 </div> 5693 </div> 5694 </template> 5695 </div> 5696 </template><template x-if="!$store.chatQuote.active && $store.favorites.count > 0"> 5697 <div class="mt-3" x-data="{ openPill: null }" 5698 @click.document="if (openPill && !$event.target.closest('.qr-pill') && !$event.target.closest('.qr-popover')) openPill = null"> 5699 <template x-for="item in $store.favorites.items" :key="item.key"> 5700 <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') }"> 5701 <template x-if="item.handle === 'mystery-product'"> 5702 <div class="shrink-0 flex items-center justify-center" style="width: 53px; height: 53px;"> 5703 <span style="width: 33px; height: 33px; color: black;"><span class="h-full w-full fill-current"> 5704 <svg 5705 aria-hidden="true" 5706 focusable="false" 5707 role="presentation" 5708 class="icon icon-product-question-mark" 5709 viewBox="0 0 24 24" 5710 > 5711 <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> 5712 </svg> 5713</span> 5714</span> 5715 </div> 5716 </template> 5717 <template x-if="item.handle !== 'mystery-product'"> 5718 <div class="shrink-0 overflow-hidden rounded-lg bg-gray-100" style="width: 53px; height: 53px;"> 5719 <img :src="item.image" :alt="item.title" class="h-full w-full object-cover" width="53" height="53"> 5720 </div> 5721 </template> 5722 <div class="min-w-0" style="width: 5rem; flex: 0 0 5rem;"> 5723 <p style="font-size: 10px; font-weight: 300; line-height: 11px; color: black;" x-text="item.vendor || ''"></p> 5724 <p class="truncate" style="font-size: 10px; font-weight: 600; line-height: 11px; color: black;" x-text="item.title"></p> 5725 </div><div class="qr-pills-row flex-1" style="margin-left: 1rem; gap: 0.75rem; align-items: center;"> 5726 <div class="relative" x-show="item.hasColours"> 5727 <button type="button" class="qr-pill" :class="{ 'qr-pill--active': openPill === item.key + '-colour' }" 5728 @click="openPill = openPill === item.key + '-colour' ? null : item.key + '-colour'; if (openPill) $store.favorites.loadColourChoices(item.key)">
5729 <span x-text="item.colour || 'Colour TBC'"></span> 5730 <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> 5731 </button> 5732 <div x-show="openPill === item.key + '-colour'" x-transition class="qr-popover" style="min-width: 10rem; max-height: 15rem; overflow-y: auto;"> 5733 <button 5734 type="button" 5735 data-quote-colour-tbc 5736 class="block w-full text-left text-sm py-1" 5737 :disabled="!$store.favorites.canSelectTbc(item)" 5738 :class="!$store.favorites.canSelectTbc(item) ? 'opacity-40 cursor-not-allowed' : ''" 5739 @click="if ($store.favorites.rekey(item.key, { variantId: null, colour: null })) openPill = null" 5740 >TBC (decide later)</button> 5741 <p class="text-xs text-gray-600" x-show="!($store.favorites.colourChoicesByHandle[item.handle] || []).length">We'll confirm colour with you</p> 5742 <template x-for="choice in ($store.favorites.colourChoicesByHandle[item.handle] || [])" :key="choice.variantId"> 5743 <button type="button" class="block w-full text-left text-sm py-1" x-text="choice.label" 5744 :disabled="$store.favorites.colourChoiceTaken(item, choice)" 5745 :class="$store.favorites.colourChoiceTaken(item, choice) ? 'opacity-40 cursor-not-allowed' : ''" 5746 @click="if ($store.favorites.rekey(item.key, choice)) openPill = null"></button> 5747 </template> 5748 </div> 5749 </div><div class="relative"> 5750 <button type="button" class="qr-pill" :class="{ 'qr-pill--active': openPill === item.key + '-qty' }" @click="openPill = openPill === item.key + '-qty' ? null : item.key + '-qty'"> 5751 <span x-text="'Quantity' + (item.quantity ? ' ' + (item.quantity >= 1000 ? '1000+' : item.quantity) : '')"></span> 5752 <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> 5753 </button> 5754 <div x-show="openPill === item.key + '-qty'" x-transition class="qr-popover" style="min-width: 8rem; padding: 0.5rem 0.75rem;"> 5755 <div class="flex items-baseline gap-2"> 5756 <span class="text-sm font-normal text-gray-900" x-text="item.quantity || item.moq || 24"></span> 5757 <span class="text-xs font-light text-gray-500">units</span> 5758 </div> 5759 <input x-show="item.sizeSplit === null" 5760 type="range" 5761 min="1" 5762 max="1000" 5763 step="1" 5764 class="qr-slider" 5765 style="height: 18px; margin-top: 2px;" 5766 :value="item.quantity || item.moq || 24" 5767 @input="$store.favorites.updateItemMeta(item.key, 'quantity', parseInt($event.target.value, 10))" 5768 :style="'--slider-track: linear-gradient(to right, #658a6a ' + ((item.quantity - 1) / 999 * 100) + '%, #e5e7eb ' + ((item.quantity - 1) / 999 * 100) + '%)'" 5769 > 5770 <label x-show="item.sizeOptions && item.sizeOptions.length" class="mt-2 flex items-center gap-2 text-xs"> 5771 <input type="checkbox" :checked="item.sizeSplit !== null" @change="$store.favorites.setSizeSplit(item.key, $event.target.checked ? {} : null)"> 5772 Split by size (optional) 5773 </label> 5774 <div x-show="item.sizeSplit !== null && item.sizeOptions && item.sizeOptions.length" class="mt-2 space-y-1"> 5775 <template x-for="size in item.sizeOptions" :key="size"> 5776 <label class="flex items-center gap-2 text-xs">
5777 <span x-text="size" class="w-10"></span> 5778 <input type="number" min="0" max="100000" step="1" class="w-20 border rounded px-1" 5779 :value="(item.sizeSplit || {})[size] || 0" 5780 @input="$store.favorites.setSizeSplit(item.key, { ...(item.sizeSplit || {}), [size]: parseInt($event.target.value, 10) || 0 })"> 5781 </label> 5782 </template> 5783 </div> 5784 </div> 5785 </div><div class="relative"> 5786 <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'"> 5787 <template x-if="item.artworks && item.artworks.length > 0"> 5788 <span class="flex items-center gap-1"> 5789 <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> 5790 <span x-text="item.artworks.length === 1 ? '1 file' : item.artworks.length + ' files'"></span> 5791 </span> 5792 </template> 5793 <template x-if="item.artworkLink && !(item.artworks && item.artworks.length > 0)"> 5794 <span class="flex items-center gap-1"> 5795 <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> 5796 <span>Artwork linked</span> 5797 </span> 5798 </template> 5799 <template x-if="!(item.artworks && item.artworks.length > 0) && !item.artworkLink"> 5800 <span x-text="'Upload artwork \u2191'"></span> 5801 </template> 5802 </button> 5803 <div x-show="openPill === item.key + '-artwork'" x-transition class="qr-popover" style="min-width: 14rem;"> 5804 <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"> 5805 <div class="mb-2 space-y-3"> 5806 <template x-for="(aw, awIdx) in item.artworks" :key="aw.fileName + awIdx"> 5807 <div class="text-xs"> 5808 <div class="flex items-center gap-1.5"> 5809 <template x-if="aw.status === 'uploading'"> 5810 <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> 5811 </template> 5812 <template x-if="aw.status === 'done'"> 5813 <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> 5814 </template> 5815 <template x-if="aw.status === 'error'"> 5816 <svg class="h-3 w-3 shrink-0 text-red-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5816<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg> 5817 </template> 5818 <span class="flex-1 truncate" :class="aw.status === 'error' ? 'text-red-600' : 'text-gray-700'" x-text="aw.fileName"></span> 5819 <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> 5820 <template x-if="aw.status === 'error'"> 5821 <button type="button" class="shrink-0 text-blue-600 underline" @click="retryArtworkUpload(item.key, awIdx)">Retry</button> 5822 </template> 5823 <button type="button" class="shrink-0 text-red-400 hover:text-red-600" @click="removeArtwork(item.key, awIdx)" title="Remove file"> 5824 <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> 5825 </button> 5826 </div><template x-if="aw.status === 'done'"> 5827 <div class="relative" style="margin-top: 3px; margin-left: 18px;" x-data="{ placementOpen: false }"> 5828 <button 5829 type="button" 5830 @click="placementOpen = !placementOpen" 5831 class="flex w-full items-center justify-between" 5832 style="height: 20px; padding: 0 8px; font-size: 10px; border: 0.666px solid black; border-radius: 9999px; background: #eee; cursor: pointer;" 5833 > 5834 <span x-text="aw.placement || 'Placementâ¦'" :style="aw.placement ? 'color: black' : 'color: #9ca3af'"></span> 5835 <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;"> 5836 <path d="M0.5 0.5L3 3L5.5 0.5" stroke="black" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"/> 5837 </svg> 5838 </button> 5839 <div 5840 x-show="placementOpen" 5841 x-transition 5842 @click.outside="placementOpen = false" 5843 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);" 5844 > 5845 <template x-for="pl in ['Front','Left Chest','Right Chest','Back','Sleeve','Other']" :key="pl"> 5846 <button 5847 type="button" 5848 class="block w-full text-left" 5849 style="padding: 0.2rem 0.65rem; font-size: 10px; line-height: 13px; color: #4b5563; cursor: pointer; background: none; border: none;" 5850 @click="updateArtworkPlacement(item.key, awIdx, pl); placementOpen = false" 5851 @mouseover="$el.style.background = '#f3f4f6'" 5852 @mouseout="$el.style.background = 'none'" 5853 x-text="pl" 5854 ></button> 5855 </template> 5856 </div> 5857 </div> 5858 </template> 5859 </div> 5860 </template> 5861 </div> 5862 </template><template x-if="!item.artworks || item.artworks.length < 5"> 5863 <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"> 5864 <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
5864<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> 5865 <span x-text="item.artworks && item.artworks.length > 0 ? 'Add more files' : 'Select files'"></span> 5866 <input 5867 type="file" 5868 class="hidden" 5869 multiple 5870 accept=".png,.jpg,.jpeg,.svg,.pdf,.ai,.eps" 5871 @change="handlePerProductFileUpload($event, item.key)" 5872 > 5873 </label> 5874 </template><div style="margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid #e5e7eb;"> 5875 <p class="text-xs text-gray-500">For <strong>larger files</strong>: via shared link</p> 5876 <input 5877 type="url" 5878 class="qr-input text-sm" 5879 style="margin-top: 0.5rem; font-size: 0.75rem;" 5880 placeholder="Link address" 5881 :value="item.artworkLink || ''" 5882 @input="$store.favorites.updateItemMeta(item.key, 'artworkLink', $event.target.value)" 5883 > 5884 <p class="mt-1 text-gray-400" style="font-size: 9px;">Eg. Google drive, Dropbox</p> 5885 </div> 5886 </div> 5887 </div><div class="relative"> 5888 <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'"> 5889 <span class="qr-pill-notes-text" x-text="item.notes && item.notes.length > 0 ? 'Notes added' : 'Notes\u2026'"></span> 5890 <template x-if="item.handle === 'mystery-product'"><span style="color: #dc2626; margin-left: 2px;">*</span></template> 5891 </button> 5892 <div x-show="openPill === item.key + '-notes'" x-transition class="qr-popover" style="left: auto; right: 0;"> 5893 <label class="mb-1.5 block text-xs font-medium text-gray-500">Notes</label> 5894 <textarea 5895 rows="3" 5896 class="qr-textarea text-sm" 5897 :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.'" 5898 :value="item.notes || ''" 5899 @input="$store.favorites.updateItemMeta(item.key, 'notes', $event.target.value)" 5900 ></textarea> 5901 </div> 5902 </div> 5903 </div> 5904 </div> 5905 </template> 5906 <template x-for="shortfall in $store.favorites.moqShortfalls()" :key="shortfall.id"> 5907 <p class="mt-2 text-xs text-red-600" role="alert" x-text="shortfall.title + ' total ' + shortfall.total + ' â minimum ' + shortfall.moq"></p> 5908 </template> 5909 </div> 5910 </template><template x-if="!$store.chatQuote.active && $store.favorites.count === 0"> 5911 <p class="mt-3 text-sm text-gray-400">No products added yet. Browse products and add items to your quote.</p> 5912 </template> 5913 </section><section style="padding-bottom: 2rem;"> 5914 <div style="border: 0.75px solid black; border-radius: 10px; padding: 0.65rem 1.25rem;"> 5915 <p style="font-size: 11px; color: black; margin-bottom: 2px;">Additional notes:</p> 5916 <textarea 5917 id="project-description" 5918 x-model="formData.description" 5919 rows="2" 5920 placeholder="Is there anything else we might need to know about your project?" 5921 style="width: 100%; border: none; padding: 0; background: transparent; font-size: 11.5px; color: #111827; resize: vertical; outline: none;" 5922 ></textarea> 5923 </div> 5924 </section><section style="padding-bottom: 2rem;"> 5925 <label class="text-sm" style="color: black;">Your budget</label> 5926 <div class="flex items-center justify-between" style="margin-top: 0.25rem;">
5927 <span class="text-xs text-gray-400">$500</span> 5928 <span style="font-size: 1.95rem; font-weight: 400; line-height: 1; color: #658a6a;" x-text="'$' + Number(formData.budget).toLocaleString()"></span> 5929 <span class="text-xs text-gray-400">$10,000+</span> 5930 </div> 5931 <div @mousedown.stop @touchstart.stop> 5932 <input 5933 type="range" 5934 x-model.number="formData.budget" 5935 @input="formData.budget = parseInt($event.target.value, 10)" 5936 @click.stop 5937 min="500" 5938 max="10000" 5939 step="500" 5940 class="qr-slider" 5941 :style="'--slider-track: linear-gradient(to right, #658a6a ' + ((formData.budget - 500) / 9500 * 100) + '%, #e5e7eb ' + ((formData.budget - 500) / 9500 * 100) + '%)'" 5942 > 5943 </div> 5944 </section><section class="grid grid-cols-1 gap-4 sm:grid-cols-2"> 5945 <div> 5946 <label for="in-hand-date" class="mb-1.5 block text-sm">The date I need my merch*</label> 5947 <input 5948 type="date" 5949 id="in-hand-date" 5950 x-model="formData.inHandDate" 5951 required 5952 class="qr-input text-sm" 5953 :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]; })()" 5954 > 5955 </div> 5956 <div x-data="{ locationOpen: false }"> 5957 <label class="mb-1.5 block text-sm" style="color: black;">I need it sent to*</label> 5958 <div class="relative"><select x-model="formData.location" required class="sr-only" tabindex="-1" aria-hidden="true"> 5959 <option value="">Select location</option> 5960 <optgroup label="New Zealand"> 5961 <option value="Northland">Northland</option> 5962 <option value="Auckland">Auckland</option> 5963 <option value="Waikato">Waikato</option> 5964 <option value="Bay of Plenty">Bay of Plenty</option> 5965 <option value="Gisborne">Gisborne</option> 5966 <option value="Hawke's Bay">Hawke's Bay</option> 5967 <option value="Taranaki">Taranaki</option> 5968 <option value="ManawatÅ«-Whanganui">Manawatū-Whanganui</option> 5969 <option value="Wellington">Wellington</option> 5970 <option value="Tasman">Tasman</option> 5971 <option value="Nelson">Nelson</option> 5972 <option value="Marlborough">Marlborough</option> 5973 <option value="West Coast">West Coast</option> 5974 <option value="Canterbury">Canterbury</option> 5975 <option value="Otago">Otago</option> 5976 <option value="Southland">Southland</option> 5977 </optgroup> 5978 <optgroup label="Australia"> 5979 <option value="New South Wales">New South Wales</option> 5980 <option value="Victoria">Victoria</option> 5981 <option value="Queensland">Queensland</option> 5982 <option value="Western Australia">Western Australia</option> 5983 <option value="South Australia">South Australia</option> 5984 <option value="Tasmania">Tasmania</option> 5985 <option value="Australian Capital Territory">Australian Capital Territory</option> 5986 <option value="Northern Territory">Northern Territory</option> 5987 </optgroup> 5988 <option value="International">International</option> 5989 </select><button 5990 type="button" 5991 @click="locationOpen = !locationOpen" 5992 class="qr-select flex w-full items-center justify-between text-sm" 5993 style="cursor: pointer;" 5994 >
5995 <span x-text="formData.location || 'Select location'" :style="formData.location ? 'color: black' : 'color: #9ca3af'"></span> 5996 <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;"> 5997 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path> 5998 </svg> 5999 </button><div 6000 x-show="locationOpen" 6001 x-transition 6002 @click.outside="locationOpen = false" 6003 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;" 6004 > 6005 <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"> 6006 <button 6007 type="button" 6008 class="block w-full text-left" 6009 style="padding: 0.25rem 1rem; font-size: 12.65px; line-height: 13.313px; color: #4b5563; cursor: pointer; background: none; border: none;" 6010 @click="formData.location = loc; locationOpen = false" 6011 @mouseover="$el.style.background = '#f3f4f6'" 6012 @mouseout="$el.style.background = 'none'" 6013 x-text="loc" 6014 ></button> 6015 </template> 6016 </div> 6017 </div> 6018 </div> 6019 <div> 6020 <label for="contact-name" class="mb-1.5 block text-sm">Your name*</label> 6021 <input 6022 type="text" 6023 id="contact-name" 6024 x-model="formData.name" 6025 required 6026 placeholder="Your name here" 6027 class="qr-input text-sm" 6028 > 6029 </div> 6030 <div> 6031 <label for="contact-email" class="mb-1.5 block text-sm">Email*</label> 6032 <input 6033 type="email" 6034 id="contact-email" 6035 x-model="formData.email" 6036 required 6037 placeholder="[email protected]" 6038 class="qr-input text-sm" 6039 > 6040 </div> 6041 <div> 6042 <label for="contact-phone" class="mb-1.5 block text-sm">Phone*</label> 6043 <input 6044 type="tel" 6045 id="contact-phone" 6046 x-model="formData.phone" 6047 required 6048 placeholder="Your phone number" 6049 class="qr-input text-sm" 6050 > 6051 </div> 6052 <div> 6053 <label for="contact-company" class="mb-1.5 block text-sm">Company</label> 6054 <input 6055 type="text" 6056 id="contact-company" 6057 x-model="formData.company" 6058 placeholder="Your company's name" 6059 class="qr-input text-sm" 6060 > 6061 </div> 6062 <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> 6063 <div class="relative"><select x-model="formData.heardAbout" required class="sr-only" tabindex="-1" aria-hidden="true"> 6064 <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 6065 type="button" 6066 @click="heardAboutOpen = !heardAboutOpen" 6067 :aria-expanded="heardAboutOpen" 6068 aria-labelledby="heard-about-label" 6069 class="qr-select flex w-full items-center justify-between text-sm" 6070 style="cursor: pointer;" 6071 >
6072 <span x-text="formData.heardAbout || 'Select an option'" :style="formData.heardAbout ? 'color: black' : 'color: #9ca3af'"></span> 6073 <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;"> 6074 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path> 6075 </svg> 6076 </button><div 6077 x-show="heardAboutOpen" 6078 x-transition 6079 @click.outside="heardAboutOpen = false" 6080 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;" 6081 > 6082 <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"> 6083 <button 6084 type="button" 6085 class="block w-full text-left" 6086 style="padding: 0.25rem 1rem; font-size: 12.65px; line-height: 13.313px; color: #4b5563; cursor: pointer; background: none; border: none;" 6087 @click="selectHeardAbout(opt); heardAboutOpen = false" 6088 @mouseover="$el.style.background = '#f3f4f6'" 6089 @mouseout="$el.style.background = 'none'" 6090 x-text="opt" 6091 ></button> 6092 </template> 6093 </div> 6094 </div><p x-show="formData.heardAbout === 'Social media'" x-transition class="mt-1.5 text-xs" style="color: #6b7280;"> 6095 Instagram, Facebook, TikTok or LinkedIn 6096 </p><div 6097 x-show="formData.heardAbout === 'Referral or word of mouth' || formData.heardAbout === 'Other'" 6098 x-transition 6099 class="mt-3" 6100 > 6101 <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> 6102 <input 6103 type="text" 6104 id="contact-heard-detail" 6105 x-model="formData.heardAboutDetail" 6106 :required="formData.heardAbout === 'Other'" 6107 :placeholder="formData.heardAbout === 'Other' ? 'How you found us' : 'Their name or company'" 6108 class="qr-input text-sm" 6109 > 6110 </div> 6111 </div> 6112 </section><template x-if="errorMessage"> 6113 <div class="rounded-2xl px-4 py-3 text-center" style="border: 1px solid #e5e7eb; background: #FFFBEB;"> 6114 <p class="text-sm" style="color: #92400e;"> 6115 <span style="font-size: 1.25rem; vertical-align: middle; margin-right: 0.25rem;">🙂</span> 6116 <span x-text="errorMessage"></span> 6117 </p> 6118 </div> 6119 </template><button 6120 type="submit" 6121 class="qr-submit" 6122 style="margin-top: 2.5rem;" 6123 :disabled="submitting || ($store.favorites.count === 0 && !$store.chatQuote.active) || (!$store.chatQuote.active && $store.favorites.moqShortfalls().length > 0)" 6124 > 6125 <span x-show="!submitting">Submit quote request</span> 6126 <span x-show="submitting" class="flex items-center justify-center gap-2"> 6127 <svg class="h-4 w-4 animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> 6128 <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> 6129 <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> 6130 </svg> 6131 Sending... 6132 </span> 6133 </button> 6134 </form> 6135 </template><template x-if="successMessage"> 6136 <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;"> 6137 6138 <h3 style="margin-top: 1.5rem; font-size: clamp(48px, 12vw, 80px); font-weight: 300; line-height: 1; color: black;">Success</h3> 6139 6140 <div style="margin-top: 3rem; max-width: 414px; font-size: clamp(18px, 4vw, 25px); line-height: 1.16; color: black; text-align: center;"> 6141 <p style="margin: 0;">Nice! Your quote request has successfully been submitted. 6142 Our team will try and have a quote back to you within 1 working day.</p> 6143 <p style="margin: 1.5rem 0 0;">In the meantime, a confirmation email has been sent to you.</p> 6144 </div> 6145 6146 <a 6147 href="/collections/product-library" 6148 @click="$store.modals.close('quoteRequest'); successMessage = ''" 6149 class="flex items-center justify-center" 6150 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;" 6151 onmouseover="this.style.backgroundColor='#4B4D72';this.style.color='#fff'" 6152 onmouseout="this.style.backgroundColor='transparent';this.style.color='#4B4D72'" 6153 > 6154 Browse more products 6155 </a> 6156 </div> 6157 </template> 6158 </div> 6159 </div> 6160 </div> 6161 </template> 6162</data-island> 6163 6164 6165 6166 6167 6168 6169 6170 <style> 6171 .cwp-overlay { 6172 position: fixed; 6173 top: var(--header-group-height, 119px); 6174 left: 0; 6175 right: 0; 6176 bottom: 0; 6177 z-index: 999; 6178 display: flex; 6179 align-items: center; 6180 justify-content: center; 6181 backdrop-filter: blur(6px); 6182 -webkit-backdrop-filter: blur(6px); 6183 background: rgba(247, 247, 247, 0.6); 6184 opacity: 0; 6185 transition: opacity 0.3s ease; 6186 } 6187 6188 .cwp-card { 6189 position: relative; 6190 width: 100%; 6191 max-width: 598px; 6192 margin: 1rem; 6193 background: #FBFBF6; 6194 border: 1.565px solid black; 6195 border-radius: 23px; 6196 box-shadow: 0 3.5px 11.5px 1.75px rgba(0, 0, 0, 0.1); 6197 padding: 2.5rem 3rem 2.5rem; 6198 overflow: visible; 6199 } 6200 6201 .cwp-close { 6202 position: absolute; 6203 top: 1.25rem; 6204 right: 1.25rem; 6205 background: none; 6206 border: none; 6207 cursor: pointer; 6208 padding: 0.5rem; 6209 color: black; 6210 } 6211 6212 .cwp-title { 6213 font-size: 70px; 6214 font-weight: 300; 6215 line-height: 1; 6216 color: black; 6217 margin: 0 0 1.5rem; 6218 } 6219 6220 .cwp-body { 6221 font-size: 19px; 6222 line-height: 22px; 6223 color: black; 6224 margin: 0 0 1rem; 6225 } 6226 6227 .cwp-body + .cwp-body { 6228 margin-top: 1rem; 6229 } 6230 6231 .cwp-btn { 6232 display: inline-flex; 6233 align-items: center; 6234 justify-content: center; 6235 margin-top: 1.25rem; 6236 height: 37px; 6237 padding: 0 1.5rem; 6238 background: white; 6239 border: 0.722px solid black; 6240 border-radius: 29px; 6241 font-size: 21.67px; 6242 font-weight: 400; 6243 color: black; 6244 cursor: pointer; 6245 transition: background 0.2s ease; 6246 } 6247 6248 .cwp-btn:hover { 6249 background: #f0f0f0; 6250 } 6251 6252 .cwp-pointer-left { 6253 position: fixed; 6254 left: 240px; 6255 top: 50%; 6256 transform: translateY(-50%) rotate(-15deg); 6257 width: 240px; 6258 opacity: 0; 6259 transition: opacity 0.6s ease; 6260 pointer-events: none; 6261 z-index: 1000; 6262 } 6263 .cwp-pointer-left.visible { 6264 opacity: 1; 6265 animation: cwp-bob-left 1.8s ease-in-out infinite; 6266 } 6267 6268 .cwp-pointer-up { 6269 position: fixed; 6270 top: calc(var(--header-group-height, 119px) - 60px); 6271 right: 60px; 6272 width: 180px; 6273 opacity: 0; 6274 transition: opacity 0.6s ease; 6275 pointer-events: none; 6276 z-index: 1000; 6277 } 6278 .cwp-pointer-up.visible { 6279 opacity: 1; 6280 animation: cwp-bob-up 1.8s ease-in-out infinite; 6281 } 6282 6283 @keyframes cwp-bob-left { 6284 0%, 100% { transform: translateY(-50%) rotate(-15deg) translateX(0); } 6285 50% { transform: translateY(-50%) rotate(-15deg) translateX(-10px); } 6286 } 6287 6288 @keyframes cwp-bob-up { 6289 0%, 100% { transform: translateY(0); } 6290 50% { transform: translateY(-10px); } 6291 } 6292 6293 @media (max-width: 639px) { 6294 .cwp-card { 6295 padding: 2rem 1.5rem; 6296 } 6297 6298 .cwp-title { 6299 font-size: 48px; 6300 } 6301 6302 .cwp-body { 6303 font-size: 16px; 6304 line-height: 20px; 6305 } 6306 6307 .cwp-btn { 6308 font-size: 18px; 6309 } 6310 6311 .cwp-pointer-left, 6312 .cwp-pointer-up { 6313 display: none; 6314 } 6315 } 6316</style> 6317 6318 6319 <style>
6320 /* ââ "Can't find something?" scroll-triggered tab ââ */ 6321 .cft-container { 6322 position: fixed; 6323 right: 0; 6324 bottom: 100px; 6325 z-index: 998; 6326 display: none; 6327 font-family: 'DM Sans', sans-serif; 6328 } 6329 6330 /* ââ Tab state (collapsed) ââ */ 6331 .cft-tab { 6332 position: relative; 6333 width: 77px; 6334 height: 96px; 6335 cursor: pointer; 6336 opacity: 0; 6337 transform: translateX(20px); 6338 transition: opacity 0.4s ease, transform 0.4s ease; 6339 } 6340 6341 .cft-tab-bg { 6342 position: absolute; 6343 inset: 0; 6344 display: flex; 6345 align-items: center; 6346 justify-content: center; 6347 } 6348 6349 .cft-tab-bg-inner { 6350 width: 96px; 6351 height: 77px; 6352 flex-shrink: 0; 6353 transform: rotate(90deg); 6354 background: var(--cant-find-bg, #EFFE9C); 6355 border-bottom: 1.03px solid black; 6356 border-left: 1.03px solid black; 6357 border-right: 1.03px solid black; 6358 border-top: none; 6359 border-radius: 0 0 16px 16px; 6360 box-shadow: -2.94px 3.13px 5.88px 0px rgba(0, 0, 0, 0.2); 6361 } 6362 6363 .cft-tab-icon { 6364 position: absolute; 6365 top: 5%; 6366 left: 10%; 6367 width: 65%; 6368 height: 50%; 6369 background-size: contain; 6370 background-repeat: no-repeat; 6371 background-position: center; 6372 } 6373 6374 .cft-tab-text { 6375 position: absolute; 6376 bottom: 13%; 6377 left: 0; 6378 right: 0; 6379 font-weight: 600; 6380 font-size: 10px; 6381 line-height: 11.3px; 6382 color: black; 6383 text-align: center; 6384 } 6385 6386 .cft-tab:hover { 6387 transform: translateX(0) scale(1.04); 6388 } 6389 6390 /* ââ Card state (expanded) â ~3Ã original size ââ */ 6391 .cft-card { 6392 position: relative; 6393 width: 300px; 6394 height: 200px; 6395 opacity: 0; 6396 transform: translateX(20px); 6397 transition: opacity 0.4s ease, transform 0.4s ease; 6398 cursor: default; 6399 } 6400 6401 .cft-card-bg { 6402 position: absolute; 6403 inset: 0; 6404 } 6405 6406 .cft-card-bg-inner { 6407 width: 100%; 6408 height: 100%; 6409 background: var(--cant-find-bg, #EFFE9C); 6410 border: 0.75px solid black; 6411 border-right: none; 6412 border-radius: 20px 0 0 20px; 6413 box-shadow: -1.17px 2.34px 2.34px 0px rgba(0, 0, 0, 0.14); 6414 } 6415 6416 .cft-card-content { 6417 position: absolute; 6418 inset: 0; 6419 z-index: 1; 6420 padding: 18px 22px; 6421 } 6422 6423 .cft-card-close { 6424 position: absolute; 6425 top: 8px; 6426 right: 8px; 6427 z-index: 2; 6428 background: none; 6429 border: none; 6430 cursor: pointer; 6431 padding: 4px; 6432 color: black; 6433 opacity: 0.5; 6434 transition: opacity 0.2s; 6435 line-height: 1; 6436 } 6437 6438 .cft-card-close:hover { 6439 opacity: 1; 6440 } 6441 6442 .cft-card-title { 6443 font-weight: 500; 6444 font-size: 18px; 6445 line-height: 20px; 6446 color: black; 6447 margin: 0 0 10px; 6448 } 6449 6450 .cft-card-body { 6451 font-weight: 400; 6452 font-size: 13px; 6453 line-height: 16px; 6454 color: black; 6455 margin: 0; 6456 max-width: 180px; 6457 } 6458 6459 .cft-card-link { 6460 font-weight: 400; 6461 font-size: 22px; 6462 line-height: 24px; 6463 color: black; 6464 text-decoration: underline; 6465 cursor: pointer; 6466 background: none; 6467 border: none; 6468 padding: 0; 6469 font-family: inherit; 6470 position: absolute; 6471 bottom: 18px; 6472 left: 22px; 6473 z-index: 1; 6474 } 6475 6476 .cft-card-link:hover { 6477 opacity: 0.7; 6478 } 6479 6480 .cft-card-doodle { 6481 position: absolute; 6482 bottom: -2px; 6483 right: 2px; 6484 width: 110px; 6485 height: 65px; 6486 transform: rotate(-24.8deg); 6487 pointer-events: none; 6488 z-index: 1; 6489 background-size: contain; 6490 background-repeat: no-repeat; 6491 background-position: center; 6492 } 6493 6494 /* ââ Visible states (applied by JS) ââ */ 6495 .cft-tab.visible, 6496 .cft-card.visible { 6497 opacity: 1; 6498 transform: translateX(0); 6499 } 6500 6501 /* ââ Hide when favorites drawer is open ââ */ 6502 body:has([data-favorites-drawer]:not([style*="display: none"])) .cft-container { 6503 display: none !important; 6504 } 6505 6506 /* ââ Mobile adjustments ââ */ 6507 @media (max-width: 639px) { 6508 .cft-container { 6509 bottom: 80px; 6510 } 6511 6512 .cft-tab { 6513 width: 66px; 6514 height: 82px; 6515 } 6516 6517 .cft-tab-bg-inner { 6518 width: 82px; 6519 height: 66px; 6520 } 6521 6522 .cft-tab-text { 6523 font-size: 9px; 6524 line-height: 10px; 6525 } 6526 6527 .cft-card { 6528 width: 270px; 6529 height: 180px; 6530 } 6531 } 6532</style> 6533 6534 6535 <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" /> 6536<data-island 6537 x-data=" 6538 AIChatbot({ 6539 apiEndpoint: "https:\/\/print-room-chatbot-api.vercel.app\/", 6540 questionsApiUrl: "https:\/\/print-room-chatbot-api.vercel.app\/", 6541 welcomeMessage: "Hi! I'm here to help you with your printing needs. How can I assist you today?", 6542 unavailableMessage: "Chat is temporarily unavailable. Please request a quote or contact us directly.", 6543 suggestedPrompts: [] 6544 }) 6545 " 6546 src="ai-chatbot" 6547 on="idle" 6548 id="ai-chatbot-ai-chatbot" 6549 class="ai-chatbot" 6550 data-color-scheme="scheme1" 6551 ><button 6552 @click="toggle()" 6553 class="ai-chatbot__trigger" 6554 :class="{ 'ai-chatbot__trigger--hidden': isOpen }" 6555 aria-label="Chat with us" 6556 type="button" 6557 > 6558 <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"> 6559 <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> 6560 </svg>
6561 <span>Chat with us</span> 6562 </button><template x-teleport="body"> 6563 <div 6564 x-show="isOpen" 6565 x-transition:enter="ai-chatbot-enter" 6566 x-transition:enter-start="ai-chatbot-enter" 6567 x-transition:enter-end="ai-chatbot-enter-active" 6568 x-transition:leave="ai-chatbot-leave" 6569 x-transition:leave-start="ai-chatbot-leave" 6570 x-transition:leave-end="ai-chatbot-leave-active" 6571 class="ai-chatbot__window" 6572 :class="{ 'ai-chatbot__window--minimized': isMinimized }" 6573 data-color-scheme="scheme1" 6574 role="dialog" 6575 aria-label="Chat with us" 6576 @keydown.escape="close()" 6577 ><div class="ai-chatbot__header"> 6578 <div class="ai-chatbot__header-title"> 6579 <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"> 6580 <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> 6581 </svg> 6582 <span>Chat with us</span> 6583 </div> 6584 <div class="ai-chatbot__header-actions"> 6585 <button 6586 x-show="messages.length > 0 && !isMinimized" 6587 @click="clearHistory()" 6588 class="ai-chatbot__header-btn" 6589 type="button" 6590 :disabled="isLoading" 6591 aria-label="Clear history" 6592 > 6593 <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"> 6594 <polyline points="3 6 5 6 21 6"></polyline> 6595 <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> 6596 </svg> 6597 </button> 6598 <button 6599 @click="minimize()" 6600 class="ai-chatbot__header-btn" 6601 type="button"
6602 :aria-label="isMinimized ? 'Expand' : 'Minimize'" 6603 > 6604 <template x-if="isMinimized"> 6605 <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"> 6606 <polyline points="15 3 21 3 21 9"></polyline> 6607 <polyline points="9 21 3 21 3 15"></polyline> 6608 <line x1="21" y1="3" x2="14" y2="10"></line> 6609 <line x1="3" y1="21" x2="10" y2="14"></line> 6610 </svg> 6611 </template> 6612 <template x-if="!isMinimized"> 6613 <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"> 6614 <polyline points="4 14 10 14 10 20"></polyline> 6615 <polyline points="20 10 14 10 14 4"></polyline> 6616 <line x1="14" y1="10" x2="21" y2="3"></line> 6617 <line x1="3" y1="21" x2="10" y2="14"></line> 6618 </svg> 6619 </template> 6620 </button> 6621 <button 6622 @click="close()" 6623 class="ai-chatbot__header-btn" 6624 type="button" 6625 aria-label="Close" 6626 > 6627 <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"> 6628 <line x1="18" y1="6" x2="6" y2="18"></line> 6629 <line x1="6" y1="6" x2="18" y2="18"></line> 6630 </svg> 6631 </button> 6632 </div> 6633 </div><div class="ai-chatbot__body" x-show="!isMinimized"><div class="ai-chatbot__messages" x-ref="messagesContainer"><template x-if="messages.length === 0"> 6634 <div class="ai-chatbot__welcome"> 6635 <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"> 6636 <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> 6637 </svg> 6638 <p class="ai-chatbot__welcome-text" x-text="welcomeMessage"></p> 6639 <p class="ai-chatbot__welcome-subtext">Ask me anything about our products and services.</p> 6640 </div> 6641 </template><template x-for="(message, index) in messages" :key="message.id"> 6642 <div 6643 class="ai-chatbot__message-row" 6644 :class="'ai-chatbot__message-row--' + message.role" 6645 ><template x-if="message.role === 'system'"> 6646 <div class="ai-chatbot__message-content ai-chatbot__message-content--system" x-text="message.content"></div> 6647 </template><template x-if="message.role !== 'system'"> 6648 <div class="ai-chatbot__message-stack"><template x-if="message.role === 'staff'"> 6649 <div class="ai-chatbot__staff-meta"> 6650 <span class="ai-chatbot__staff-avatar" x-text="message.initials"></span> 6651 <span class="ai-chatbot__staff-name" x-text="message.senderName"></span> 6652 <span 6653 class="ai-chatbot__staff-time" 6654 x-show="message.timestamp" 6655 x-text="message.timestamp ? new Date(message.timestamp).toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' }) : ''" 6656 ></span> 6657 </div> 6658 </template> 6659 6660 <div 6661 class="ai-chatbot__message-bubble" 6662 :class="'ai-chatbot__message-bubble--' + message.role" 6663 ><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"> 6664 <div class="ai-chatbot__options" :class="{ 'ai-chatbot__options--submitted': message.optionsSubmitted }"> 6665 <p class="ai-chatbot__options-prompt" x-show="message.options.prompt" x-text="message.options.prompt"></p> 6666 <div class="ai-chatbot__options-list"> 6667 <template x-for="(choice, ci) in message.options.choices" :key="choice.value"> 6668 <button 6669 @click="selectOption(index, choice.value)" 6670 class="ai-chatbot__option-chip" 6671 :class="{ 6672 'ai-chatbot__option-chip--selected': message.selectedOptions.includes(choice.value), 6673 'ai-chatbot__option-chip--disabled': message.optionsSubmitted 6674 }" 6675 :disabled="message.optionsSubmitted" 6676 type="button" 6677 x-text="choice.label" 6678 ></button> 6679 </template> 6680 </div> 6681 <button 6682 x-show="message.options.multiSelect && !message.optionsSubmitted && message.selectedOptions.length > 0" 6683 @click="submitOptions(index)" 6684 class="ai-chatbot__options-submit" 6685 type="button" 6686 > 6687 Continue 6688 </button> 6689 </div> 6690 </template> 6691 </div> 6692 </div> 6693 </template> 6694 </div> 6695 </template><template x-if="isLoading && messages.length > 0 && !messages[messages.length - 1].content"> 6696 <div class="ai-chatbot__message-row ai-chatbot__message-row--assistant"> 6697 <div class="ai-chatbot__message-stack"> 6698 <div class="ai-chatbot__message-bubble ai-chatbot__message-bubble--assistant ai-chatbot__message-bubble--typing"> 6699 <div class="ai-chatbot__typing" aria-label="Assistant is typing">
6700 <span></span> 6701 <span></span> 6702 <span></span> 6703 </div> 6704 </div> 6705 </div> 6706 </div> 6707 </template> 6708 </div><div x-show="error" class="ai-chatbot__error"> 6709 <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"> 6710 <circle cx="12" cy="12" r="10"></circle> 6711 <line x1="12" y1="8" x2="12" y2="12"></line> 6712 <line x1="12" y1="16" x2="12.01" y2="16"></line> 6713 </svg> 6714 <div class="ai-chatbot__error-content"> 6715 <p class="ai-chatbot__error-text" x-text="error"></p> 6716 <div class="ai-chatbot__error-actions"> 6717 <button @click="openQuoteRequest()" class="ai-chatbot__error-action" type="button"> 6718 Request a quote 6719 </button> 6720 <a href="/pages/contact-us" class="ai-chatbot__error-action"> 6721 Contact us 6722 </a> 6723 </div> 6724 <button @click="clearError()" class="ai-chatbot__error-dismiss" type="button"> 6725 Dismiss 6726 </button> 6727 </div> 6728 </div><div x-show="messages.length === 0 && (getActivePrompts().length > 0 || questionsLoading)" class="ai-chatbot__prompts"> 6729 <p class="ai-chatbot__prompts-label">Try asking:</p><template x-if="questionsLoading && getActivePrompts().length === 0"> 6730 <div class="ai-chatbot__prompts-loading"> 6731 <span class="ai-chatbot__prompt-skeleton"></span> 6732 <span class="ai-chatbot__prompt-skeleton"></span> 6733 <span class="ai-chatbot__prompt-skeleton"></span> 6734 </div> 6735 </template><template x-for="(prompt, index) in getActivePrompts()" :key="index"> 6736 <button 6737 @click="useSuggestedPrompt(prompt)" 6738 class="ai-chatbot__prompt-btn" 6739 type="button" 6740 x-text="prompt" 6741 ></button> 6742 </template> 6743 </div><div x-show="ctaButton && ctaButton.show" x-cloak class="ai-chatbot__cta"> 6744 <button 6745 @click="handleCTAClick()" 6746 class="ai-chatbot__cta-btn" 6747 type="button" 6748 x-text="ctaButton?.text || 'Request a Quote'" 6749 ></button> 6750 <button 6751 @click="dismissCTA()" 6752 class="ai-chatbot__cta-dismiss" 6753 type="button" 6754 aria-label="Dismiss" 6755 > 6756 <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"> 6757 <line x1="18" y1="6" x2="6" y2="18"></line> 6758 <line x1="6" y1="6" x2="18" y2="18"></line> 6759 </svg> 6760 </button> 6761 </div><div x-show="conversationStatus === 'resolved'" x-cloak class="ai-chatbot__resolved-banner"> 6762 Chat ended â send a message to start again. 6763 </div><div x-show="showContactAsk" x-cloak class="ai-chatbot__contact-ask"> 6764 <p class="ai-chatbot__contact-ask-prompt" x-show="contactAskMode === 'email_chip'">Leave your email in case you step away.</p> 6765 <p class="ai-chatbot__contact-ask-prompt" x-show="contactAskMode === 'progressive'">Mind sharing your name and email so we can follow up?</p> 6766 <form @submit.prevent="submitContact()" class="ai-chatbot__contact-ask-form"> 6767 <input 6768 x-show="contactAskMode !== 'email_chip' && !contactName" 6769 x-model="contactNameInput" 6770 type="text" 6771 class="ai-chatbot__contact-ask-input" 6772 placeholder="Your name" 6773 :disabled="contactSubmitting" 6774 > 6775 <input 6776 x-show="!contactEmail" 6777 x-model="contactEmailInput" 6778 type="email" 6779 class="ai-chatbot__contact-ask-input" 6780 placeholder="Your email" 6781 :disabled="contactSubmitting" 6782 > 6783 <button 6784 type="submit" 6785 class="ai-chatbot__contact-ask-submit" 6786 :disabled="contactSubmitting" 6787 > 6788 Send 6789 </button> 6790 <button 6791 type="button" 6792 @click="dismissContactAsk()" 6793 class="ai-chatbot__contact-ask-dismiss" 6794 aria-label="Dismiss" 6795 > 6796 <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"> 6797 <line x1="18" y1="6" x2="6" y2="18"></line> 6798 <line x1="6" y1="6" x2="18" y2="18"></line> 6799 </svg> 6800 </button> 6801 </form> 6802 </div><div class="ai-chatbot__input-area"> 6803 <form @submit.prevent="sendMessage()" class="ai-chatbot__input-form"> 6804 <textarea 6805 x-ref="chatInput" 6806 x-model="inputText" 6807 @keydown="handleKeyDown($event)" 6808 class="ai-chatbot__input" 6809 placeholder="Type your message..." 6810 rows="1" 6811 :disabled="isLoading" 6812 ></textarea> 6813 <button 6814 type="submit" 6815 class="ai-chatbot__send-btn" 6816 :disabled="isLoading || !inputText.trim()" 6817 aria-label="Send" 6818 > 6819 <template x-if="isLoading"> 6820 <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"> 6821 <line x1="12" y1="2" x2="12" y2="6"></line> 6822 <line x1="12" y1="18" x2="12" y2="22"></line> 6823 <line x1="4.93" y1="4.93" x2="7.76" y2="7.76"></line> 6824 <line x1="16.24" y1="16.24" x2="19.07" y2="19.07"></line> 6825 <line x1="2" y1="12" x2="6" y2="12"></line> 6826 <line x1="18" y1="12" x2="22" y2="12"></line> 6827 <line x1="4.93" y1="19.07" x2="7.76" y2="16.24"></line> 6828 <line x1="16.24" y1="7.76" x2="19.07" y2="4.93"></line> 6829 </svg> 6830 </template> 6831 <template x-if="!isLoading"> 6832 <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">
6833 <line x1="22" y1="2" x2="11" y2="13"></line> 6834 <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon> 6835 </svg> 6836 </template> 6837 </button> 6838 </form><p 6839 class="ai-chatbot__disclaimer" 6840 x-show="conversationStatus === null || conversationStatus === 'bot'" 6841 > 6842 Responses are generated by AI and may be inaccurate. 6843 </p> 6844 </div> 6845 </div> 6846 </div> 6847 </template> 6848 </data-island> 6849</div> 6850 6851 6852 <section id="shopify-section-branding-service-cards" class="shopify-section branding-service-cards-section"><style data-shopify> 6853 .branding-floating-overlay { 6854 position: fixed; 6855 inset: 0; 6856 z-index: 9999; 6857 background: rgba(0, 0, 0, 0.5); 6858 opacity: 0; 6859 transition: opacity 300ms ease; 6860 pointer-events: none; 6861 } 6862 6863 .branding-floating-overlay.active { 6864 opacity: 1; 6865 pointer-events: auto; 6866 } 6867 6868 /* Floating card - matches carousel expanded card styling */ 6869 .branding-floating-card { 6870 position: fixed; 6871 z-index: 10000; 6872 background: rgb(var(--color-scheme-background, 255 255 255)); 6873 border-radius: 16px; 6874 box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.4); 6875 display: none; 6876 flex-direction: column; 6877 max-height: 85vh; 6878 overflow: hidden; 6879 /* No default top/left/bottom - JS controls position */ 6880 } 6881 6882 /* Close button - matches carousel style */ 6883 .branding-floating-card .branding-pill-close { 6884 position: absolute; 6885 top: 12px; 6886 right: 12px; 6887 z-index: 10; 6888 width: 32px; 6889 height: 32px; 6890 border-radius: 50%; 6891 background: rgba(255, 255, 255, 0.9); 6892 border: none; 6893 cursor: pointer; 6894 display: flex; 6895 align-items: center; 6896 justify-content: center; 6897 box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); 6898 transition: background 200ms ease; 6899 } 6900 6901 .branding-floating-card .branding-pill-close:hover { 6902 background: rgba(255, 255, 255, 1); 6903 } 6904 6905 .branding-floating-card .branding-pill-close svg { 6906 width: 16px; 6907 height: 16px; 6908 stroke: #333; 6909 } 6910 6911 /* Image link - matches carousel style */ 6912 .branding-floating-card .branding-pill-image-link { 6913 display: block; 6914 flex-shrink: 0; 6915 background: rgba(var(--color-scheme-text, 0 0 0), 0.05); 6916 min-height: 200px; 6917 } 6918 6919 .branding-floating-card .branding-pill-image-link.has-image { 6920 min-height: 0; 6921 } 6922 6923 .branding-floating-card .branding-pill-image { 6924 border-radius: 16px 16px 0 0; 6925 width: 100%; 6926 height: auto; 6927 max-height: 280px; 6928 object-fit: cover; 6929 display: block; 6930 } 6931 6932 .branding-floating-card .branding-pill-image:not([src]), 6933 .branding-floating-card .branding-pill-image[src=""] { 6934 display: none; 6935 } 6936 6937 /* Label button overlay - matches carousel style */ 6938 .branding-floating-card .branding-pill-label { 6939 display: none; /* Hidden in expanded state like carousel */ 6940 } 6941 6942 /* Expanded content - matches carousel style */ 6943 .branding-floating-card .branding-pill-content { 6944 padding: 20px; 6945 flex-shrink: 0; 6946 } 6947 6948 .branding-floating-card .branding-expanded-title { 6949 margin: 0 0 12px 0; 6950 font-size: 1.25rem; 6951 font-weight: 600; 6952 color: black; 6953 6954 } 6955 6956 .branding-floating-card .branding-expanded-loading { 6957 display: flex; 6958 align-items: center; 6959 justify-content: center; 6960 padding: 20px; 6961 } 6962 6963 .branding-floating-card .branding-expanded-spinner { 6964 width: 24px; 6965 height: 24px; 6966 border: 2px solid rgba(var(--color-scheme-text, 0 0 0), 0.1); 6967 border-top-color: rgb(var(--color-scheme-text, 0 0 0)); 6968 border-radius: 50%; 6969 animation: branding-pill-spin 0.8s linear infinite; 6970 } 6971 6972 @keyframes branding-pill-spin { 6973 to { transform: rotate(360deg); } 6974 } 6975 6976 .branding-floating-card .branding-expanded-description { 6977 margin-bottom: 16px; 6978 line-height: 1.6; 6979 color: black; 6980 } 6981 6982 .branding-floating-card .branding-expanded-description p { 6983 margin: 0; 6984 } 6985 6986 .branding-floating-card .branding-expanded-description p + p { 6987 margin-top: 0.75em; 6988 } 6989 6990 @media (max-width: 749px) { 6991 .branding-floating-card { 6992 width: calc(100vw - 48px) !important; 6993 left: 24px !important; 6994 max-width: none !important; 6995 } 6996 } 6997</style> 6998 6999<!-- Overlay backdrop --> 7000<div 7001 id="branding-floating-overlay" 7002 class="branding-floating-overlay" 7003 onclick="window.closeBrandingServiceCard()" 7004></div> 7005 7006<!-- Floating card - HTML structure matches carousel expanded cards --> 7007<div 7008 id="branding-floating-card" 7009 class="branding-floating-card color-scheme5" 7010> 7011 <!-- Close button (top right over image) --> 7012 <button type="button" class="branding-pill-close" onclick="window.closeBrandingServiceCard()"> 7013 <span class="sr-only">Close</span> 7014 <svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"> 7015 <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" /> 7016 </svg> 7017 </button> 7018 7019 <!-- Image with link --> 7020 <a id="branding-card-image-link" href="#" class="branding-pill-image-link"> 7021 <img 7022 id="branding-card-image" 7023 class="branding-pill-image" 7024 src="" 7025 alt="" 7026 loading="lazy" 7027 width="300" 7028 height="300" 7029 > 7030 </a> 7031 7032 <!-- Label button (hidden in expanded state, like carousel) --> 7033 <a id="branding-card-label" href="#" class="branding-pill-label"></a> 7034 7035 <!-- Expanded content --> 7036 <div class="branding-pill-content"> 7037 <h3 id="branding-card-title" class="branding-expanded-title"></h3> 7038 <div id="branding-card-loading" class="branding-expanded-loading" style="display: none;"> 7039 <div class="branding-expanded-spinner"></div> 7040 </div> 7041 <div id="branding-card-description" class="branding-expanded-description"></div> 7042 </div> 7043</div> 7044
7045<script> 7046(function() { 7047 // Build service data from Shopify blocks 7048 // Key is the lowercase metafield value (e.g., "screen print", "custom neck tags") 7049 const brandingServiceData = { 7050 7051 'high density transfer': { 7052 title: "High density transfer", 7053 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", 7054 image: '//printroom.co/cdn/shop/files/heat_transfer_2_1b6dd18d-7ae5-452a-a0ca-fef697ba6400.jpg?v=1761181341&width=800', 7055 imageAlt: "High density transfer", 7056 ctaText: "Learn more", 7057 ctaUrl: '#' 7058 }, 7059 7060 'printed seam tape': { 7061 title: "printed seam tape", 7062 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", 7063 image: '//printroom.co/cdn/shop/files/speights_cap_inner_3.jpg?v=1743540305&width=800', 7064 imageAlt: "custom caps NZ", 7065 ctaText: "Learn more", 7066 ctaUrl: '#' 7067 }, 7068 7069 'knitted all-over': { 7070 title: "Knitted all-over", 7071 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", 7072 image: '//printroom.co/cdn/shop/files/knitted_all_over_detail.jpg?v=1772668725&width=800', 7073 imageAlt: "Knitted all-over", 7074 ctaText: "Learn more", 7075 ctaUrl: '#' 7076 }, 7077 7078 'dye-sublimation': { 7079 title: "Dye-sublimation", 7080 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", 7081 image: '//printroom.co/cdn/shop/files/dye_sub_detail.jpg?v=1772673144&width=800', 7082 imageAlt: "Dye-sublimation", 7083 ctaText: "Learn more", 7084 ctaUrl: '#' 7085 }, 7086 7087 'additional cushioning': { 7088 title: "Additional cushioning", 7089 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", 7090 image: '//printroom.co/cdn/shop/files/cushion_detail.jpg?v=1772673175&width=800', 7091 imageAlt: "Additional cushioning", 7092 ctaText: "Learn more", 7093 ctaUrl: '#' 7094 }, 7095 7096 'added grip': { 7097 title: "Added grip", 7098 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", 7099 image: '//printroom.co/cdn/shop/files/added_grip_detail.jpg?v=1772675209&width=800', 7100 imageAlt: "Added grip", 7101 ctaText: "Learn more", 7102 ctaUrl: '#' 7103 }, 7104 7105 'custom neck tags': { 7106 title: "Custom neck tags", 7107 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", 7108 image: '//printroom.co/cdn/shop/files/cardrona_4_2_936c38b5-e634-4f0f-b224-0c9ed7b76ed9.jpg?v=1648584454&width=800', 7109 imageAlt: "garment relabelling and custom neck tags christchurch", 7110 ctaText: "Learn more", 7111 ctaUrl: '#' 7112 }, 7113 7114 'screen print': { 7115 title: "Screen Printing", 7116 description: "\u003cp\u003eOur most popular print method for good reasonâit delivers \u003cstrong\u003etop-tier qual
7116ity\u003c\/strong\u003e, long-lasting results, and exceptional value for larger orders.\u003c\/p\u003e", 7117 image: '//printroom.co/cdn/shop/files/PrintRoomMay2024Image-16.jpg?v=1733350366&width=800', 7118 imageAlt: "Screen Printing", 7119 ctaText: "Learn more", 7120 ctaUrl: '#' 7121 }, 7122 7123 'embroidery': { 7124 title: "Embroidery", 7125 description: "\u003cp\u003eUnmatched in durability, embroidery is a simple choice for those wanting texture, dimension and a high-end finish.\u003c\/p\u003e", 7126 image: '//printroom.co/cdn/shop/files/The_print_room_custom_embroidery_new_zealand.jpg?v=1613753361&width=800', 7127 imageAlt: "Embroidery", 7128 ctaText: "Learn more", 7129 ctaUrl: '#' 7130 }, 7131 7132 'heat transfer': { 7133 title: "Heat Transfers", 7134 description: "\u003cp\u003ePerfect for producing vibrant, detail-rich prints that require low minimums.\u003c\/p\u003e", 7135 image: '//printroom.co/cdn/shop/files/heat_press_print_room.jpg?v=1776795804&width=800', 7136 imageAlt: "Heat Transfers", 7137 ctaText: "Learn more", 7138 ctaUrl: '/pages/heat-transfers' 7139 }, 7140 7141 'custom patches': { 7142 title: "Custom Patches", 7143 description: "\u003cp\u003eDurable and versatile, add dimension to your merch with embroidered, woven or iron-on custom patches.\u003c\/p\u003e", 7144 image: '//printroom.co/cdn/shop/files/PrintRoomApril2024Image-42_28acbdcf-7baf-4834-9201-752d656019ad.jpg?v=1754535298&width=800', 7145 imageAlt: "custom patches NZ", 7146 ctaText: "Learn more", 7147 ctaUrl: '#' 7148 }, 7149 7150 'custom packaging': { 7151 title: "Custom packaging", 7152 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", 7153 image: '//printroom.co/cdn/shop/files/socks_label.jpg?v=1743476398&width=800', 7154 imageAlt: "custom socks", 7155 ctaText: "Learn more", 7156 ctaUrl: '#' 7157 }, 7158 7159 'custom woven label': { 7160 title: "Custom woven label", 7161 description: "\u003cp\u003eGive all of the details you need while putting the finishing touches on your product.\u003c\/p\u003e", 7162 image: '//printroom.co/cdn/shop/files/garage_project_cap_4.1.jpg?v=1770086525&width=800', 7163 imageAlt: "Custom woven label", 7164 ctaText: "Learn more", 7165 ctaUrl: '#' 7166 }, 7167 7168 'pip tags': { 7169 title: "Pip tags", 7170 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", 7171 image: '//printroom.co/cdn/shop/files/cardrona_3_19a3035b-75a5-4fd0-9604-01d159cdc102.jpg?v=1648585469&width=800', 7172 imageAlt: "garment relabelling and custom neck tags nz", 7173 ctaText: "Learn more", 7174 ctaUrl: '#' 7175 }, 7176 7177 'additional print placements': { 7178 title: "Additional print placements", 7179 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", 7180 image: '//printroom.co/cdn/shop/files/garage_project_cap_3.1.jpg?v=1770083144&width=800', 7181 imageAlt: "Additional print placements", 7182 ctaText: "Learn more", 7183 ctaUrl: '#' 7184 }, 7185 7186 'various attachments available': { 7187 title: "Various attachments available", 7188 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", 7189 image: '//printroom.co/cdn/shop/files/pack-a-punch.jpg?v=1760925265&width=800', 7190 imageAlt: "Various attachments available", 7191 ctaText: "Learn more", 7192 ctaUrl: '#' 7193 }, 7194 7195 'add additional colours': { 7196 title: "Add additional colours", 7197 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", 7198 image: '//printroom.co/cdn/shop/files/ombre.jpg?v=1770253000&width=800', 7199 imageAlt: "Add additional colours", 7200 ctaText: "Learn more", 7201 ctaUrl: '#' 7202 }, 7203 7204 'various closures available': { 7205 title: "Various closures available", 7206 description: "\u003cp\u003eAchieve the result you want with control over what closure you go with.\u003c\/p\u003e", 7207 image: '//printroom.co/cdn/shop/files/closure_options_2.1_76d53ef9-c502-45b4-b915-66543d3c7f40.jpg?v=1769654951&width=800', 7208 imageAlt: "Various closures available", 7209 ctaText: "Learn more", 7210 ctaUrl: '#' 7211 }, 7212 7213 'glow in the dark': { 7214 title: "Glow in the dark", 7215 description: "\u003cp\u003eBe seenâ¦in the dark! Add a novel element to your product and have some fun with it.\u003c\/p\u003e", 7216 image: '//printroom.co/cdn/shop/files/glow_in_the_dark.jpg?v=1770253668&width=800', 7217 imageAlt: "Glow in the dark", 7218 ctaText: "Learn more", 7219 ctaUrl: '#' 7220 }, 7221 7222 'applique': { 7223 title: "Applique", 7224 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", 7225 image: '//printroom.co/cdn/shop/files/Screenshot-2026-04-22-at-6.18.38_AM.jpg?v=1776795959&width=800', 7226 imageAlt: "Applique", 7227 ctaText: "Learn more", 7228 ctaUrl: '#' 7229 }, 7230 7231 'spreadsheet': { 7232 title: "Spreadsheet", 7233 description: "\u003cp\u003eWe send you a formatted spreadsheet that can be shared around your year group for each student to input the
7233ir garment style, size and custom name. \u003c\/p\u003e", 7234 image: null, 7235 imageAlt: "Spreadsheet", 7236 ctaText: "Learn more", 7237 ctaUrl: '#' 7238 }, 7239 7240 'online portal': { 7241 title: "Online portal", 7242 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", 7243 image: '//printroom.co/cdn/shop/files/product_1db770e9-3325-4bd4-8636-6f4b6d5e566a_slot_5.jpg?v=1776753322&width=800', 7244 imageAlt: "Earth Positive Premium Jersey T-shirt EP185 T-shirt branded merchandise nz", 7245 ctaText: "Click", 7246 ctaUrl: '#' 7247 } 7248 7249 }; 7250 7251 // Also build hyphenated keys for matching 7252 const brandingServiceDataNormalized = {}; 7253 Object.keys(brandingServiceData).forEach(key => { 7254 // Store with original key 7255 brandingServiceDataNormalized[key] = brandingServiceData[key]; 7256 // Also store with hyphenated version 7257 const hyphenated = key.replace(/\s+/g, '-'); 7258 brandingServiceDataNormalized[hyphenated] = brandingServiceData[key]; 7259 // Also store with spaced version (in case key was hyphenated) 7260 const spaced = key.replace(/-/g, ' '); 7261 brandingServiceDataNormalized[spaced] = brandingServiceData[key]; 7262 }); 7263 7264 // Configuration from section settings 7265 const config = { 7266 maxWidth: 400, 7267 animationDuration: 300, 7268 showOverlay: false 7269 }; 7270 7271 // State 7272 let isCardOpen = false; 7273 let originRect = null; 7274 7275 // DOM elements 7276 const overlay = document.getElementById('branding-floating-overlay'); 7277 const card = document.getElementById('branding-floating-card'); 7278 const cardImageLink = document.getElementById('branding-card-image-link'); 7279 const cardImage = document.getElementById('branding-card-image'); 7280 const cardLabel = document.getElementById('branding-card-label'); 7281 const cardTitle = document.getElementById('branding-card-title'); 7282 const cardLoading = document.getElementById('branding-card-loading'); 7283 const cardDescription = document.getElementById('branding-card-description'); 7284 7285 // Find service data by matching the label text 7286 function findServiceData(label) { 7287 if (!label) return null; 7288 const searchKey = label.toLowerCase().trim(); 7289 const searchKeyHyphenated = searchKey.replace(/\s+/g, '-'); 7290 7291 // Direct match 7292 if (brandingServiceDataNormalized[searchKey]) { 7293 return brandingServiceDataNormalized[searchKey]; 7294 } 7295 7296 // Try hyphenated version 7297 if (brandingServiceDataNormalized[searchKeyHyphenated]) { 7298 return brandingServiceDataNormalized[searchKeyHyphenated]; 7299 } 7300 7301 // Partial match - check if any key is contained in the label or vice versa 7302 for (const key of Object.keys(brandingServiceDataNormalized)) { 7303 if (searchKey.includes(key) || key.includes(searchKey)) { 7304 return brandingServiceDataNormalized[key]; 7305 } 7306 } 7307 7308 return null; 7309 } 7310 7311 // Populate card content 7312 function populateCard(data, serviceUrl) { 7313 const url = data.ctaUrl || serviceUrl || '#'; 7314 7315 // Set image 7316 if (data.image) { 7317 cardImage.src = data.image; 7318 cardImage.alt = data.imageAlt || data.title || ''; 7319 cardImageLink.classList.add('has-image'); 7320 } else { 7321 cardImage.src = ''; 7322 cardImage.alt = ''; 7323 cardImageLink.classList.remove('has-image'); 7324 } 7325 7326 // Set links 7327 cardImageLink.href = url; 7328 cardLabel.href = url; 7329 cardLabel.textContent = data.title || ''; 7330 7331 // Set content 7332 cardTitle.textContent = data.title || ''; 7333 7334 // Handle description - if we have static content use it, otherwise fetch 7335 if (data.description && data.description.trim() !== '' && data.description !== '<p>Add a description of this branding service.</p>') { 7336 cardDescription.innerHTML = data.description; 7337 cardLoading.style.display = 'none'; 7338 } else { 7339 // Fetch description from service page 7340 cardDescription.innerHTML = ''; 7341 cardLoading.style.display = 'flex'; 7342 7343 if (url && url !== '#') { 7344 fetch(url) 7345 .then(response => response.text()) 7346 .then(html => { 7347 const parser = new DOMParser(); 7348 const doc = parser.parseFromString(html, 'text/html'); 7349 const main = doc.querySelector('main') || doc.querySelector('.page-content') || doc.querySelector('.shopify-section') || doc.body; 7350 let description = '<p>Discover our premium branding service.</p>'; 7351 if (main) { 7352 const firstP = main.querySelector('p'); 7353 if (firstP) description = '<p>' + firstP.textContent.trim() + '</p>'; 7354 } 7355 cardDescription.innerHTML = description; 7356 cardLoading.style.display = 'none'; 7357 }) 7358 .catch(() => { 7359 cardDescription.innerHTML = '<p>Discover our premium branding service.</p>'; 7360 cardLoading.style.display = 'none'; 7361 }); 7362 } else { 7363 cardDescription.innerHTML = '<p>Discover our premium branding service.</p>'; 7364 cardLoading.style.display = 'none'; 7365 } 7366 } 7367 } 7368 7369 // Show card with animation from button position 7370 function showCardWithData(data, buttonElement, serviceUrl) { 7371 if (!data) { 7372 console.warn('No service data provided'); 7373 return; 7374 } 7375 7376 // Get button position for animation origin 7377 const buttonRect = buttonElement 7378 ? buttonElement.getBoundingClientRect() 7379 : { left: window.innerWidth / 2 - 50, top: window.innerHeight / 2, width: 100, height: 40 }; 7380 7381 originRect = { ...buttonRect }; 7382 7383 // Populate content 7384 populateCard(data, serviceUrl); 7385 7386 // Calculate target dimensions 7387 const expandedWidth = Math.min(window.innerWidth - 40, config.maxWidth); 7388 const padding = 20; 7389 const headerHeight = parseInt(getComputedStyle(document.documentElement).getPropertyValue('--header-height') || '0', 10); 7390 7391 // Center expanded card horizontally on the button's center 7392const buttonCenterX = buttonRect.left + (buttonRect.width / 2); 7393let targetLeft = buttonCenterX - (expandedWidth / 2); 7394 7395// Clamp to viewport bounds horizontally 7396targetLeft = Math.max(padding, Math.min(targetLeft, window.innerWidth - expandedWidth - padding)); 7397 7398// Position vertically: expand from button's top, but ensure it stays in viewport 7399// Start from the button's vertical position 7400let targetTop = buttonRect.top; 7401 7402// Get actual card content height or use a more realistic estimate 7403const cardContent = card.querySelector('.card__content') || card; 7404const estimatedCardHeight = cardContent.scrollHeight || 600; // Increased from 400 to 600 7405 7406// Calculate available space below and above the button 7407const spaceBelow = window.innerHeight - buttonRect.bottom - padding; 7408const spaceAbove = buttonRect.top - headerHeight - padding; 7409 7410// If card would go below viewport, shift it up 7411if (targetTop + estimatedCardHeight > window.innerHeight - padding) { 7412 targetTop = Math.max(headerHeight + padding, window.innerHeight - estimatedCardHeight - padding); 7413} 7414 7415// If card would go above header, shift it down 7416if (targetTop < headerHeight + padding) { 7417 targetTop = headerHeight + padding; 7418} 7419 7420// Final safety check: ensure card fits in viewport 7421const maxAllowedHeight = window.innerHeight - headerHeight - (padding * 2); 7422if (estimatedCardHeight > maxAllowedHeight) { 7423 targetTop = headerHeight + padding; 7424 card.style.maxHeight = maxAllowedHeight + 'px'; 7425 card.style.overflowY = 'auto'; 7426} 7427 7428 7429 // Show overlay 7430 if (config.showOverlay) { 7431 overlay.classList.add('active'); 7432 } 7433 7434 // Set initial state at EXACT button position 7435 card.style.position = 'fixed'; 7436 card.style.top = buttonRect.top + 'px'; 7437 card.style.left = buttonRect.left + 'px'; 7438 card.style.width = buttonRect.width + 'px'; 7439 card.style.height = buttonRect.height + 'px'; 7440 card.style.zIndex = '10000'; 7441 card.style.margin = '0'; 7442 card.style.display = 'flex'; 7443 card.style.opacity = '1'; 7444 card.style.pointerEvents = 'auto'; 7445 card.style.overflow = 'hidden';
7446 card.style.transition = 'none'; 7447 card.style.flexDirection = 'column'; 7448 card.style.borderRadius = '16px'; 7449 7450 // Force reflow to ensure initial position is applied 7451 card.getBoundingClientRect(); 7452 7453 // Now animate to expanded position 7454 requestAnimationFrame(() => { 7455 requestAnimationFrame(() => { 7456 card.style.transition = ` 7457 top ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1), 7458 left ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1), 7459 width ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1), 7460 height ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1) 7461 `; 7462 card.style.top = targetTop + 'px'; 7463 card.style.left = targetLeft + 'px'; 7464 card.style.width = expandedWidth + 'px'; 7465 card.style.height = 'auto'; 7466 }); 7467 }); 7468 7469 isCardOpen = true; 7470 } 7471 7472 // Close card with animation back to origin 7473 window.closeBrandingServiceCard = function() { 7474 if (!isCardOpen) return; 7475 7476 // Animate back to origin position (exactly like carousel collapseCard) 7477 if (originRect) { 7478 card.style.transition = ` 7479 top ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1), 7480 left ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1), 7481 width ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1), 7482 height ${config.animationDuration}ms cubic-bezier(0.32, 0.72, 0, 1) 7483 `; 7484 card.style.top = originRect.top + 'px'; 7485 card.style.left = originRect.left + 'px'; 7486 card.style.width = originRect.width + 'px'; 7487 card.style.height = originRect.height + 'px'; 7488 card.style.overflow = 'hidden'; 7489 } 7490 7491 // Hide overlay 7492 overlay.classList.remove('active'); 7493 7494 // Clean up after animation 7495 setTimeout(() => { 7496 card.style.display = 'none'; 7497 card.style.transition = ''; 7498 card.style.top = ''; 7499 card.style.left = ''; 7500 card.style.width = ''; 7501 card.style.height = ''; 7502 card.style.opacity = ''; 7503 card.style.pointerEvents = ''; 7504 card.style.overflow = ''; 7505 isCardOpen = false; 7506 originRect = null; 7507 }, config.animationDuration); 7508 }; 7509 7510 // Event listener for pill button clicks 7511 // Alpine's $dispatch bubbles from the element through the DOM 7512 document.addEventListener('branding-modal:open', (event) => { 7513 // Prevent duplicate handling 7514 if (event._handled) return; 7515 event._handled = true; 7516 7517 const { label, url, element } = event.detail || {}; 7518 7519 // Get the pill text from the button element if available 7520 const pillText = element ? (element.querySelector('.branding-service-pill__text')?.textContent || label) : label; 7521 7522 // Find service data by matching the pill text 7523 const serviceData = findServiceData(pillText); 7524 if (!serviceData) { 7525 console.warn('No service data configured for:', pillText); 7526 return; 7527 } 7528 7529 // If a card is already open, close it first 7530 if (isCardOpen) { 7531 window.closeBrandingServiceCard(); 7532 setTimeout(() => { 7533 showCardWithData(serviceData, element, url); 7534 }, config.animationDuration + 50); 7535 } else { 7536 showCardWithData(serviceData, element, url); 7537 } 7538 }); 7539 7540 // Escape key handler 7541 document.addEventListener('keydown', (e) => { 7542 if (e.key === 'Escape' && isCardOpen) { 7543 window.closeBrandingServiceCard(); 7544 } 7545 }); 7546})(); 7547</script>
7547 7548 7549 7550</section> 7551 7552
7552<script src="//printroom.co/cdn/shop/t/59/assets/global.bundle.js?v=149077486339995821341790734057" type="module"></script>
7552 7553 7554
7554<script> 7555 window.Shopify = window.Shopify || {}; 7556 window.Shopify.locale = "en"; 7557 window.Shopify.currency = { 7558 active: "USD", 7559 rate: "" 7560 }; 7561 </script>
7561 7562 <div id="shopify-block-AWDJwL3lGQkF3Zitrd__39280165312039977" class="shopify-block shopify-app-block"> 7563 7564�
7564<script> 7565 console.log('[FulfillmentFee] Namespace: app--313853968385--fulfillment_fee'); 7566 console.log('[FulfillmentFee] Key: config'); 7567 console.log('[FulfillmentFee] Config value:', {"vendorFees":{"WÄtÄ FX Crew":5.75},"feeProductVariantId":"gid:\/\/shopify\/ProductVariant\/44486403227718","isEnabled":true}); 7568</script>
7568<script> 7569 (function() { 7570 // The metafield .value is already a parsed JSON object 7571 var configData = {"vendorFees":{"WÄtÄ FX Crew":5.75},"feeProductVariantId":"gid:\/\/shopify\/ProductVariant\/44486403227718","isEnabled":true}; 7572 if (configData && typeof configData === 'object') { 7573 window.__FULFILLMENT_FEE_CONFIG__ = configData; 7574 console.log('[FulfillmentFee] Config loaded:', window.__FULFILLMENT_FEE_CONFIG__); 7575 } else { 7576 console.error('[FulfillmentFee] Invalid config data:', configData); 7577 window.__FULFILLMENT_FEE_CONFIG__ = null; 7578 } 7579 })(); 7580</script>
vendor: 2 bytes, line 7580
7580
7581<script src="https://cdn.shopify.com/extensions/019d45d2-6a70-7eed-8da1-d1e8fd0fae86/fulfillment-fee-app-100/assets/fulfillment-fee-manager.js" defer></script>
7581 7582</div><div id="shopify-block-AWitpMC8rZDJCSlg4R__15573056287721514228" class="shopify-block shopify-app-block json-ld-for-seo"><!-- generated: 2026-10-04 21:38:22 +1300 --> 7583<!-- BEGIN app snippet: json_ld_for_seo_web_page -->
7583<script type="application/ld+json"> 7584 { 7585 "@context": "https://schema.org", 7586 "@type": "WebPage", 7587 "@id": "https:\/\/printroom.co\/search#json-ld-for-seo-webpage", 7588 "url": "https:\/\/printroom.co\/search", 7589 "image": null, 7590 "primaryImageOfPage": null, 7591 "dateCreated": null, 7592 "datePublished": null 7593 } 7594</script>
7594 7595<!-- END app snippet --> 7596<!-- wp 0 --><!-- BEGIN app snippet: json_ld_for_seo_organization -->
7597<script type="application/ld+json"> 7598{ 7599 "@context": "https://schema.org", 7600 "@type": "Organization","@id": "https:\/\/printroom.co\/#org", 7601 "name": "The Print Room", 7602 "url": "https:\/\/printroom.co", 7603 "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.", 7604 "telephone": "+6434259694", 7605 "logo": "https:\/\/cdn.shopify.com\/s\/images\/admin\/no-image-large.gif", 7606 "image": "https:\/\/cdn.shopify.com\/s\/images\/admin\/no-image-large.gif", 7607 "sameAs": ["","https:\/\/www.instagram.com\/printroomnz\/"], 7608 "address": { 7609 "@type": "PostalAddress", 7610 "streetAddress": "21 Grosvenor Street, 21", 7611 "addressLocality": "Dunedin", 7612 "addressRegion": "Otago", 7613 "postalCode": "9011", 7614 "addressCountry": "NZ" 7615 }, 7616 "contactPoint": [ 7617 { 7618 "@type": "ContactPoint", 7619 "telephone": "+6434259694", 7620 "email": "" 7621 } 7622 ]} 7623</script>
7623 7624<!-- END app snippet --> <!-- o 4 --><!-- BEGIN app snippet: json_ld_for_seo_product_group --><!-- END app snippet --> 7625<!-- p 1 --><!-- A 7 --> 7626 7627 7628</div>
7628<script src="https://cdn.shopify.com/storefront/standard-actions.js" type="module" data-source-attribution="shopify.standard_actions"></script>
7628 7629</body> 7630</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.