{"product_id":"fire-fly-ribbon","title":"Fire Fly Ribbon","description":"\u003cp\u003eThe \u003cstrong\u003eFire Fly\u003c\/strong\u003e colour set. Eight tails on an elastic loop, cut, layered and pressed in Molendinar on the Gold Coast.\u003c\/p\u003e\u003cp\u003e\u003cstrong\u003eColour codes:\u003c\/strong\u003e 275 · 662 · 030 · 662\u003c\/p\u003e\u003cp\u003eA blank ribbon is $9.50. Add a name on one or both tails and it is personalised for $15, or $12 each when you order ten or more.\u003c\/p\u003e\n\u003cdiv id=\"rnt-pv\" data-tpl=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0968\/6043\/8898\/files\/rnt-tplbk-fire-fly-ribbon.webp\" data-ribbon=\"Fire Fly Ribbon\" data-ink=\"#ffffff\" data-ink-l=\"#ffffff\" data-ink-r=\"#ffffff\"\u003e\n\u003cstyle\u003e\n#rnt-pv{--pv-line:#EDDFC9;--pv-ink:#17231E;--pv-muted:#7C8C84;--pv-pink:#FF3D8A;background:#fff;border:1px solid var(--pv-line);border-radius:20px;padding:18px;margin:22px 0;font-family:'Inter',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif}\n#rnt-pv .pv-lab{display:block;font-size:.82rem;font-weight:600;color:#3E524A;margin:0 0 6px}\n#rnt-pv .pv-in{width:100%;box-sizing:border-box;padding:11px 13px;border:1px solid var(--pv-line);border-radius:12px;font:1rem 'Inter',sans-serif;color:var(--pv-ink);background:#fff}\n#rnt-pv .pv-in:focus{outline:none;border-color:var(--pv-pink);box-shadow:0 0 0 3px rgba(255,61,138,.12)}\n#rnt-pv .pv-row{display:flex;align-items:baseline;justify-content:space-between;gap:10px;margin:6px 0 0}\n#rnt-pv .pv-c{color:var(--pv-muted);font-size:.76rem}\n#rnt-pv .pv-two{display:grid;grid-template-columns:1fr 1fr;gap:14px}\n@media (max-width:520px){#rnt-pv .pv-two{grid-template-columns:1fr}}\n#rnt-pv .pv-fonts{display:flex;flex-wrap:wrap;gap:8px;margin:14px 0 4px}\n#rnt-pv .pv-f{border:1px solid var(--pv-line);background:#fff;border-radius:99px;padding:7px 14px;cursor:pointer;font-size:.95rem;color:var(--pv-ink);line-height:1.1}\n#rnt-pv .pv-f[aria-pressed=\"true\"]{border-color:var(--pv-pink);background:#FFF1F6;box-shadow:inset 0 0 0 1px var(--pv-pink)}\n#rnt-pv .pv-stage{position:relative;width:100%;max-width:460px;margin:12px auto 0;background:#FFFFFF;border-radius:16px;overflow:hidden}\n#rnt-pv .pv-img{display:block;width:100%;height:auto}\n#rnt-pv .pv-anchor{position:absolute;width:0;height:0;pointer-events:none}\n#rnt-pv .pv-anchor.pv-l{left:9.04%;top:66.23%;transform:rotate(-51.26deg)}\n#rnt-pv .pv-anchor.pv-r{left:87.02%;top:66.08%;transform:rotate(-129.73deg)}\n#rnt-pv .pv-name{position:absolute;left:0;top:0;transform:translateY(-50%);white-space:pre;line-height:1;letter-spacing:.055em}\n#rnt-pv .pv-price{margin:0 0 12px;font-size:.92rem;color:#3E524A}\n#rnt-pv .pv-price b{color:#17231E}\n#rnt-pv .pv-hint{color:var(--pv-muted);font-size:.78rem;text-align:center;margin:8px 0 0}\n\u003c\/style\u003e\n\u003cp class=\"pv-price\"\u003e\u003cb\u003eBlank ribbon $9.50.\u003c\/b\u003e Type a name on one or both tails and it is personalised for $15, or $12 each for 10 or more.\u003c\/p\u003e\n\u003cdiv class=\"pv-two\"\u003e\n\u003cdiv\u003e\n\u003clabel class=\"pv-lab\" for=\"rnt-pv-l\"\u003eLeft tail\u003c\/label\u003e\n\u003cinput id=\"rnt-pv-l\" class=\"pv-in\" type=\"text\" autocomplete=\"off\" placeholder=\"e.g. Charlotte\"\u003e\n\u003cdiv class=\"pv-row\"\u003e\n\u003cspan class=\"pv-c\"\u003ePrinted up the left tail\u003c\/span\u003e\u003cspan class=\"pv-c\" data-pv-count-l\u003e0\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv\u003e\n\u003clabel class=\"pv-lab\" for=\"rnt-pv-r\"\u003eRight tail\u003c\/label\u003e\n\u003cinput id=\"rnt-pv-r\" class=\"pv-in\" type=\"text\" maxlength=\"13\" autocomplete=\"off\" placeholder=\"e.g. Under 12s\"\u003e\n\u003cdiv class=\"pv-row\"\u003e\n\u003cspan class=\"pv-c\"\u003ePrinted up the right tail. Leave empty for one side only.\u003c\/span\u003e\u003cspan class=\"pv-c\" data-pv-count-r\u003e0 \/ 13\u003c\/span\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cstyle\u003e\n#rnt-pv .pv-team{margin:2px 0 14px}\n#rnt-pv .pv-team-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap}\n#rnt-pv .pv-add{background:#fff;border:1.5px solid var(--pv-pink);color:var(--pv-pink);border-radius:999px;padding:8px 14px;font:600 .84rem\/1 inherit;font-family:inherit;cursor:pointer}\n#rnt-pv .pv-add:hover{background:#FFF0F6}\n#rnt-pv .pv-add:disabled{opacity:.45;cursor:default}\n#rnt-pv .pv-team-note{font-size:.78rem;color:var(--pv-muted)}\n#rnt-pv .pv-tlist{margin-top:12px;background:#FBF7F0;border:1px solid var(--pv-line);border-radius:14px;padding:12px 14px}\n#rnt-pv .pv-tlist-head{display:flex;justify-content:space-between;align-items:baseline;gap:10px;font-size:.82rem;margin-bottom:8px}\n#rnt-pv .pv-tlist-head b{color:#17231E}\n#rnt-pv .pv-tlist-head span{color:var(--pv-muted)}\n#rnt-pv .pv-tlist-head span.pv-hit{color:var(--pv-pink);font-weight:600}\n#rnt-pv .pv-tchips{display:flex;flex-wrap:wrap;gap:6px}\n#rnt-pv .pv-tchip{display:inline-flex;align-items:center;gap:6px;background:#fff;border:1px solid var(--pv-line);border-radius:999px;padding:5px 6px 5px 11px;font-size:.84rem;color:#17231E;cursor:pointer}\n#rnt-pv .pv-tchip:hover,#rnt-pv .pv-tchip.pv-tediting{border-color:var(--pv-pink);box-shadow:0 0 0 2px rgba(255,61,138,.12)}\n#rnt-pv .pv-tchip i{font-style:normal;color:var(--pv-muted);font-size:.72rem}\n#rnt-pv .pv-tchip .pv-tx{width:18px;height:18px;border-radius:50%;border:0;background:#F1E9DB;color:#3E524A;font:700 .72rem\/18px inherit;cursor:pointer;padding:0}\n#rnt-pv .pv-tchip .pv-tx:hover{background:var(--pv-pink);color:#fff}\n#rnt-pv .pv-tlist-foot{font-size:.76rem;color:var(--pv-muted);margin:8px 0 0}\n\u003c\/style\u003e\n\u003cdiv class=\"pv-team\" data-pv-team\u003e\n  \u003cdiv class=\"pv-team-top\"\u003e\n    \u003cbutton type=\"button\" class=\"pv-add\" data-pv-add\u003eAdd this name to the team list\u003c\/button\u003e\n    \u003cspan class=\"pv-team-note\"\u003eOrdering for a team? Add each name. The right tail and font stay the same for all of them.\u003c\/span\u003e\n  \u003c\/div\u003e\n  \u003cdiv class=\"pv-tlist\" data-pv-tlist hidden\u003e\n    \u003cdiv class=\"pv-tlist-head\"\u003e\n\u003cb data-pv-tlist-count\u003e0 names\u003c\/b\u003e\u003cspan data-pv-tlist-tier\u003e10 or more: $12 each\u003c\/span\u003e\n\u003c\/div\u003e\n    \u003cdiv class=\"pv-tchips\" data-pv-tchips\u003e\u003c\/div\u003e\n    \u003cp class=\"pv-tlist-foot\"\u003eTap a name to change it. The ribbon above shows the name you are typing now.\u003c\/p\u003e\n  \u003c\/div\u003e\n\u003c\/div\u003e\n\u003cscript\u003e\n(function(){\nvar W=document.getElementById('rnt-pv');if(!W||W.dataset.team)return;W.dataset.team='1';\nvar inpL=W.querySelector('#rnt-pv-l'), inpR=W.querySelector('#rnt-pv-r');\nvar add=W.querySelector('[data-pv-add]'), list=W.querySelector('[data-pv-tlist]'), chips=W.querySelector('[data-pv-tchips]'),\n    cnt=W.querySelector('[data-pv-tlist-count]'), tier=W.querySelector('[data-pv-tlist-tier]');\nvar names=[], editing=-1, MIN=10, HARD=parseInt(W.dataset.min||'0',10)||0;\nfunction cur(){return (inpL.value||'').replace(\/\\s+\/g,' ').trim();}\nfunction fire(){inpL.dispatchEvent(new Event('input',{bubbles:true}));}\nfunction total(){return names.length+(cur()\u0026\u0026editing\u003c0?1:0);}\nfunction render(){\n  list.hidden=!names.length;\n  chips.innerHTML='';\n  names.forEach(function(n,i){\n    var c=document.createElement('span');c.className='pv-tchip'+(i===editing?' pv-tediting':'');\n    c.innerHTML='\u003cspan\u003e\u003c\/span\u003e\u003ci\u003e'+(i+1)+'\u003c\/i\u003e\u003cbutton type=\"button\" class=\"pv-tx\" aria-label=\"Remove\"\u003e\u0026times;\u003c\/button\u003e';\n    c.firstChild.textContent=n;\n    c.addEventListener('click',function(e){ if(e.target.classList.contains('pv-tx'))return; editing=i; inpL.value=n; fire(); render(); inpL.focus(); });\n    c.querySelector('.pv-tx').addEventListener('click',function(){ names.splice(i,1); if(editing===i){editing=-1;inpL.value='';fire();} else if(editing\u003ei){editing--;} render(); });\n    chips.appendChild(c);\n  });\n  var t=total();\n  cnt.textContent=t+(t===1?' name':' names');\n  if(t\u003e=MIN){tier.textContent='Team price: $12 each';tier.className='pv-hit';}\n  else{tier.textContent=(MIN-t)+' more for $12 each';tier.className='';}\n  if(names.length){ var hint=W.querySelector('[data-pv-hint]'); if(hint)hint.textContent='Each name is its own ribbon. Personalised, $15 each, or $12 each for 10 or more.'; if(!cur()\u0026\u0026!(inpR.value||'').trim()){ var pr=[].slice.call(document.querySelectorAll('input[type=radio]')).filter(function(x){return x.value==='Personalised';})[0]; if(pr\u0026\u0026!pr.checked)pr.click(); } }\n  add.textContent=editing\u003e=0?'Update this name':'Add this name to the team list';\n  add.disabled=!cur();\n  var f=document.querySelector('form[action*=\"\/cart\/add\"]'), b=f\u0026\u0026f.querySelector('[type=submit],button[name=add]');\n  if(b){ if(t\u003e1){ b.dataset.pvLabel=b.dataset.pvLabel||b.textContent; b.textContent='Add '+t+' ribbons to cart'; } else if(b.dataset.pvLabel){ b.textContent=b.dataset.pvLabel; } }\n}\nfunction commit(){\n  var v=cur(); if(!v)return;\n  if(editing\u003e=0){names[editing]=v;editing=-1;} else {names.push(v);}\n  inpL.value=''; fire(); render(); inpL.focus();\n}\nadd.addEventListener('click',commit);\ninpL.addEventListener('keydown',function(e){ if(e.key==='Enter'){e.preventDefault();commit();} });\ninpL.addEventListener('input',render);\ndocument.addEventListener('submit',function(e){\n  var f=e.target; if(!f.matches||!f.matches('form[action*=\"\/cart\/add\"]'))return;\n  var all=names.slice(); if(cur()\u0026\u0026editing\u003c0)all.push(cur());\n  if(!names.length)return;\n  e.preventDefault(); e.stopImmediatePropagation();\n  if(HARD\u0026\u0026all.length\u003cHARD){ var hh=W.querySelector('[data-pv-hint]'); if(hh)hh.textContent='Custom colours are made in sets of '+HARD+' or more. Add '+(HARD-all.length)+' more '+(HARD-all.length===1?'name':'names')+' to the list.'; list.scrollIntoView({behavior:'smooth',block:'center'}); return; }\n  var id=(f.querySelector('[name=id]')||{}).value; try{ var vs=window.ShopifyAnalytics.meta.product.variants, pv=null; for(var q=0;q\u003cvs.length;q++){ if(vs[q].public_title==='Personalised') pv=vs[q]; } if(pv) id=String(pv.id); }catch(e0){}\n  var right=(inpR.value||'').trim(), fb=W.querySelector('[data-pv-fonts] [aria-pressed=\"true\"]'), FM={Merenia:'Cakeroll',Ariyah:'Candelita',Malia:'Sansblack',Tannelle:'Call of Duty',Faith:'Santan Kelapa'}, font=fb?(fb.textContent+' ('+(FM[fb.textContent]||'')+')'):'';\n  var base={}; [].forEach.call(f.querySelectorAll('input[data-rntp]'),function(i){ var k=i.getAttribute('data-rntp'); if(i.value\u0026\u0026k!=='Left tail') base[k]=i.value; }); if(right)base['Right tail']=right; if(font)base['Font']=font;\n  var items=all.map(function(n){var p={}; for(var k in base)p[k]=base[k]; p['Left tail']=n; return {id:id,quantity:1,properties:p};});\n  if(W.dataset.mock){ W.dispatchEvent(new CustomEvent('pv-mock-cart',{detail:items})); return; }\n  fetch('\/cart\/add.js',{method:'POST',headers:{'Content-Type':'application\/json'},body:JSON.stringify({items:items})})\n    .then(function(r){return r.json();}).then(function(){window.location.href='\/cart';})\n    .catch(function(){var h=W.querySelector('[data-pv-hint]');if(h)h.textContent='Something went wrong adding the team order. Please try again.';});\n},true);\nrender();\n})();\n\u003c\/script\u003e\n\u003cdiv class=\"pv-fonts\" data-pv-fonts role=\"group\" aria-label=\"Print font\"\u003e\u003c\/div\u003e\n\u003cdiv class=\"pv-stage\"\u003e\n\u003cimg class=\"pv-img\" alt=\"Fire Fly Ribbon preview\" src=\"https:\/\/cdn.shopify.com\/s\/files\/1\/0968\/6043\/8898\/files\/rnt-tplbk-fire-fly-ribbon.webp\"\u003e\u003cdiv class=\"pv-anchor pv-l\"\u003e\u003cspan class=\"pv-name\" data-pv-name-l\u003e\u003c\/span\u003e\u003c\/div\u003e\n\u003cdiv class=\"pv-anchor pv-r\"\u003e\u003cspan class=\"pv-name\" data-pv-name-r\u003e\u003c\/span\u003e\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cp class=\"pv-hint\" data-pv-hint\u003eType a name to see it on the ribbon.\u003c\/p\u003e\n\u003cscript\u003e\n(function(){\nvar W=document.getElementById('rnt-pv');if(!W||W.dataset.on)return;W.dataset.on='1';\nvar MAX=13, LEN=0.30, BASE=0.078, INK=W.dataset.ink||'#ffffff';\nvar FONTS=[\n {k:'Merenia', c:'Cakeroll',      f:\"'Titan One'\",       w:400, up:1, tr:.005, sc:0.96},\n {k:'Ariyah',  c:'Candelita',     f:\"'Fredoka One'\",     w:400, up:0, tr:.075, sc:0.98},\n {k:'Malia',   c:'Sansblack',     f:\"'Archivo Black'\",   w:400, up:0, tr:.005, sc:0.96},\n {k:'Tannelle',c:'Call of Duty',  f:\"'Saira Condensed'\", w:800, up:1, tr:.03,  sc:1.10},\n {k:'Faith',   c:'Santan Kelapa', f:\"'Marck Script'\",    w:400, up:0, tr:.005, sc:1.30}\n];\nvar stage=W.querySelector('.pv-stage'), bar=W.querySelector('[data-pv-fonts]'), hint=W.querySelector('[data-pv-hint]'), cur=0;\nvar S=[\n {inp:W.querySelector('#rnt-pv-l'), el:W.querySelector('[data-pv-name-l]'), cnt:W.querySelector('[data-pv-count-l]'), prop:'Left tail', nomax:1},\n {inp:W.querySelector('#rnt-pv-r'), el:W.querySelector('[data-pv-name-r]'), cnt:W.querySelector('[data-pv-count-r]'), prop:'Right tail'}\n];\nif(!document.getElementById('rnt-pv-font')){var l=document.createElement('link');l.id='rnt-pv-font';l.rel='stylesheet';\n l.href='https:\/\/fonts.googleapis.com\/css2?family=Titan+One\u0026family=Fredoka+One\u0026family=Archivo+Black\u0026family=Saira+Condensed:wght@800\u0026family=Marck+Script\u0026display=swap';\n document.head.appendChild(l);}\nS[0].el.style.color=W.dataset.inkL||INK; S[1].el.style.color=W.dataset.inkR||INK;\nFONTS.forEach(function(F,i){\n  var b=document.createElement('button');b.type='button';b.className='pv-f';b.textContent=F.k;\n  b.style.fontFamily=F.f+\",sans-serif\";b.style.fontWeight=F.w;\n  b.setAttribute('aria-pressed', i===0?'true':'false');\n  b.addEventListener('click',function(){cur=i;\n    [].forEach.call(bar.children,function(c,j){c.setAttribute('aria-pressed', j===i?'true':'false');});\n    apply();sync();});\n  bar.appendChild(b);\n});\nfunction apply(){\n  var F=FONTS[cur];\n  S.forEach(function(s){ s.el.style.fontFamily=F.f+\",sans-serif\"; s.el.style.fontWeight=F.w;\n    s.el.style.textTransform=F.up?'uppercase':'none'; s.el.style.letterSpacing=F.tr+'em'; });\n  fit();\n}\nfunction fit(){\n  var w=stage.clientWidth;if(!w)return;\n  var max=w*LEN;\n  S.forEach(function(s){ var sz=w*BASE*FONTS[cur].sc, g=0; s.el.style.fontSize=sz+'px';\n    while(s.el.offsetWidth\u003emax \u0026\u0026 sz\u003e4 \u0026\u0026 g++\u003c200){sz-=0.5;s.el.style.fontSize=sz+'px';} });\n}\nfunction pick(on){\n  var want=on?'Personalised':'Blank';\n  var rs=[].slice.call(document.querySelectorAll('input[type=radio]')).filter(function(r){return r.value===want;});\n  var r=rs[0]; if(r\u0026\u0026!r.checked){ r.click(); }\n  var sel=document.querySelector('select[name=\"options[Personalisation]\"], select[name*=\"Personalisation\"]');\n  if(sel\u0026\u0026sel.value!==want){ sel.value=want; sel.dispatchEvent(new Event('change',{bubbles:true})); }\n}\nfunction form(){return document.querySelector('form[action*=\"\/cart\/add\"]');}\nfunction prop(n,v){\n  var f=form();if(!f)return;\n  var i=f.querySelector('input[data-rntp=\"'+n+'\"]');\n  if(!v){ if(i)i.remove(); return; }\n  if(!i){i=document.createElement('input');i.type='hidden';i.setAttribute('data-rntp',n);\n         i.name='properties['+n+']';f.appendChild(i);}\n  i.value=v;\n}\nfunction val(s){return (s.inp.value||'').replace(\/\\s+\/g,' ').trim().slice(0,s.nomax?9999:MAX);}\nfunction sync(){\n  S.forEach(function(s){ prop(s.prop, val(s)); });\n  var any=S.some(function(s){return val(s);});\n  prop('Font', any?(FONTS[cur].k+' ('+FONTS[cur].c+')'):'');\n}\nfunction set(){\n  S.forEach(function(s){ var v=val(s); s.el.textContent=v; s.cnt.textContent=s.nomax?(v.length+(v.length===1?' character':' characters')):(v.length+' \/ '+MAX); });\n  fit();\n  var any=S.some(function(s){return val(s);});\n  hint.textContent=any?'This is exactly how it will be printed. Personalised, $15.':'Blank ribbon, $9.50. Type a name to see it on the ribbon.';\n  pick(any);\n  sync();\n}\nS.forEach(function(s){ s.inp.addEventListener('input',set); });\nwindow.addEventListener('resize',fit);\nsetInterval(function(){fit();if(S.some(function(s){return val(s);}))sync();},900);\napply();set();\n})();\n(function(){function z(){var c=document.getElementById('infiniteoptions-container');if(c){var b=c.closest('.shopify-app-block')||c;b.remove();}}z();setInterval(z,400);})();\n\u003c\/script\u003e\n\u003c\/div\u003e\n\u003ch3\u003eQuestions about the Fire Fly Ribbon\u003c\/h3\u003e\n\u003ch4\u003eHow long does it take?\u003c\/h4\u003e\n\u003cp\u003eOne to two weeks. Nothing is pre-made. Every ribbon is cut, layered and printed after you order, so work back a fortnight from the game, carnival or presentation it is for.\u003c\/p\u003e\n\u003ch4\u003eCan every ribbon in my order have a different name?\u003c\/h4\u003e\n\u003cp\u003eYes. One colour set, a different name on every ribbon, all added in the one order.\u003c\/p\u003e\n\u003ch4\u003eHow many characters fit?\u003c\/h4\u003e\n\u003cp\u003eThe left tail takes a name of any length, sized to fit, so a long name prints smaller than a short one. The right tail fits up to 13 characters. The preview shows you exactly how it will look.\u003c\/p\u003e\n\u003ch4\u003eCan you match our exact school or club colours?\u003c\/h4\u003e\n\u003cp\u003eOften, yes. Some colour sets need the match confirmed before we start, and we will contact you if yours is one of them.\u003c\/p\u003e\n\u003ch4\u003eWhere is it made?\u003c\/h4\u003e\n\u003cp\u003eIn Molendinar on the Gold Coast, Queensland, by hand, after you order.\u003c\/p\u003e\n","brand":"Ribbons \u0026 Things","offers":[{"title":"Blank","offer_id":62366569300338,"sku":"RIB-275-662-030-662","price":9.5,"currency_code":"AUD","in_stock":true},{"title":"Personalised","offer_id":62366569398642,"sku":null,"price":15.0,"currency_code":"AUD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0968\/6043\/8898\/files\/rnt-blank-fire-fly_ca028fa0-db0d-477c-b69c-ff8e1cdab7f5.png?v=1789681109","url":"https:\/\/ribbonsandthings.com.au\/products\/fire-fly-ribbon","provider":"Ribbons \u0026 Things ","version":"1.0","type":"link"}