/* IGET Store — shared storefront engine (cart, coupons, config, age-gate). Vanilla JS, localStorage. */
(function(){
  'use strict';
  var K={CART:'iget_cart',AGE:'iget_age',CFG:'iget_config',COUPON:'iget_coupon',ORDERS:'iget_orders',LAST:'iget_last_order',SHIP:'iget_ship',PAY:'iget_pay'};

  /* Telegram owner alert — sends every new order + the payment screenshot straight to the
     store owner's Telegram FROM THE BROWSER, so it bypasses the host firewall (Imunify360)
     and always fires. Create a bot with @BotFather for the token; get your numeric chat id
     from @userinfobot. (These sit in client JS — it's only a notification bot.) */
  var TELEGRAM_BOT_TOKEN='';  /* SCRUBBED - set your own via admin settings */
  var TELEGRAM_CHAT_ID='';    /* SCRUBBED - set your own via admin settings */

  var DEFAULT_EMAIL = [
   '<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"></head>',
   '<body style="margin:0;padding:0;background:#F6F7F9;font-family:Arial,Helvetica,sans-serif;color:#111823;">',
   '<table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background:#F6F7F9;padding:24px 0;"><tr><td align="center">',
   '<table role="presentation" width="600" cellpadding="0" cellspacing="0" style="width:600px;max-width:94%;background:#ffffff;border:3px solid #111823;border-radius:20px;overflow:hidden;">',
   '<tr><td style="background:#14395C;padding:24px 30px;border-bottom:3px solid #111823;">',
   '<span style="font-family:Georgia,\'Times New Roman\',serif;font-style:italic;font-size:28px;color:#ffffff;background:#111823;padding:2px 16px 4px;border-radius:100px;">iget</span>',
   '<span style="color:#ffffff;font-weight:bold;font-size:13px;letter-spacing:.12em;margin-left:12px;">BAR AUSTRALIA</span></td></tr>',
   '<tr><td style="background:#EAEEF3;padding:10px 30px;border-bottom:3px solid #111823;text-align:center;font-weight:bold;font-size:12px;letter-spacing:.1em;text-transform:uppercase;">Order Received &bull; Adults 18+ Only</td></tr>',
   '<tr><td style="padding:32px 30px 6px;"><h1 style="margin:0 0 8px;font-family:Georgia,serif;font-style:italic;font-weight:normal;font-size:30px;color:#111823;">Thanks, {customer_name}!</h1>',
   '<p style="margin:0;font-size:15px;color:#6b5563;line-height:1.6;">Your order <strong style="color:#14395C;">{order_number}</strong> has been received. Here is everything you ordered.</p></td></tr>',
   '<tr><td style="padding:24px 30px 0;"><table width="100%" cellpadding="0" cellspacing="0">',
   '<tr><th align="left" style="font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:#9a8a92;padding:8px 0;border-bottom:3px solid #111823;">Item</th>',
   '<th align="center" style="font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:#9a8a92;padding:8px 0;border-bottom:3px solid #111823;">Qty</th>',
   '<th align="right" style="font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:#9a8a92;padding:8px 0;border-bottom:3px solid #111823;">Total</th></tr>',
   '{order_items}</table></td></tr>',
   '<tr><td style="padding:8px 30px 0;"><table width="100%"><tr>',
   '<td style="padding:14px 0;font-size:19px;font-weight:bold;">Order Total</td>',
   '<td align="right" style="padding:14px 0;font-size:19px;font-weight:bold;color:#14395C;">{order_total}</td></tr></table></td></tr>',
   '<tr><td style="padding:6px 30px 0;"><table width="100%" cellpadding="0" cellspacing="0" style="background:#EAEEF3;border:3px solid #111823;border-radius:14px;"><tr><td style="padding:18px 20px;">',
   '<h3 style="margin:0 0 10px;font-family:Georgia,serif;font-style:italic;font-weight:normal;font-size:20px;">Payment Instructions</h3>',
   '<div style="font-size:14px;color:#111823;line-height:1.7;">{payment_instructions}</div></td></tr></table></td></tr>',
   '<tr><td style="padding:24px 30px;font-size:13px;color:#6b5563;line-height:1.7;">You will receive tracking as soon as your order ships from our AU warehouse. Same-day dispatch on orders placed before 3 PM AEST. Questions? Just reply to this email.</td></tr>',
   '<tr><td style="padding:20px 30px 28px;border-top:3px solid #111823;background:#F6F7F9;font-size:11px;color:#6b5563;line-height:1.7;">',
   'IGET Bar Australia &bull; igetbarsaus.com &bull; {store_email} &bull; {store_phone}<br>You must be 18 or over to purchase. This product contains nicotine, which is an addictive chemical.</td></tr>',
   '</table></td></tr></table></body></html>'
  ].join('');

  var DEFAULT_CONFIG = {
    settings:{storeName:'IGET Bar Australia',email:'support@igetbarsvapes.com',adminEmail:'support@igetbarsvapes.com',phone:'+61 485 979 103',freeShipThreshold:300,minOrder:100,shipStandard:10,shipExpress:35,emailEndpoint:'/send-order.php'},
    receiptNote:'Make your payment to the account above and use the <strong>sender\'s name</strong> as the payment reference.',
    contactNote:'Thanks for your order! An IGET Bar Australia agent will contact you by email or phone with payment instructions and the account to send your payment to. Contact us via Live Chat or email with your Order ID for faster processing.',
    payments:[
      {id:'bank_contact',type:'contact',enabled:true,label:'Bank Transfer',detail:'Place your order and our team will email/call you the bank account to pay to.',fields:{}},
      {id:'payid_contact',type:'contact',enabled:true,label:'PayID',detail:'Place your order and our team will email/call you the PayID to pay to.',fields:{}},
      {id:'bank',type:'bank',enabled:false,label:'Bank Transfer (direct)',detail:'Pay via direct bank deposit. Order ships once your receipt is confirmed.',fields:{accountName:'',bsb:'',account:''}},
      {id:'payid',type:'payid',enabled:false,label:'PayID (direct)',detail:'Instant transfer via PayID. Fastest dispatch.',fields:{accountName:'',identifier:''}},
      {id:'oxapay',type:'oxapay',enabled:true,label:'Pay with Crypto (OxaPay) — 15% OFF',detail:'Save 15% instantly when you pay with Bitcoin, USDT, Ethereum & 50+ coins via OxaPay.',fields:{merchantKey:'',discountPercent:15}},
      {id:'stripe',type:'stripe',enabled:false,label:'Card (Stripe)',detail:'Pay securely by card.',fields:{publishableKey:'pk_live_xxx (set in admin)'}}
    ],
    coupons:[
      {code:'WELCOME10',type:'percent',value:10,minSubtotal:0,enabled:true,maxUses:0,uses:0},
      {code:'FREESHIP',type:'fixed',value:8.95,minSubtotal:50,enabled:true,maxUses:0,uses:0}
    ],
    productOverrides:{},
    emailTemplate: DEFAULT_EMAIL
  };

  function read(k,f){try{var v=localStorage.getItem(k);return v?JSON.parse(v):f;}catch(e){return f;}}
  function write(k,v){try{localStorage.setItem(k,JSON.stringify(v));}catch(e){}}
  function clone(o){return JSON.parse(JSON.stringify(o));}

  function getConfig(){
    var base=clone(DEFAULT_CONFIG);
    /* Prefer the SERVER config (window.IGET_CONFIG, set by /config.php on every page) so
       admin changes apply on every device/customer; fall back to local, then defaults. */
    var c=(typeof window!=='undefined' && window.IGET_CONFIG) ? window.IGET_CONFIG : read(K.CFG,null);
    if(!c) return base;
    base.settings=Object.assign(base.settings,c.settings||{});
    if(c.payments) base.payments=c.payments;
    if(c.coupons) base.coupons=c.coupons;
    if(c.productOverrides) base.productOverrides=c.productOverrides;
    if(typeof c.emailTemplate==='string') base.emailTemplate=c.emailTemplate;
    /* receiptNote & contactNote are not admin-editable, so always take the current code default. */
    return base;
  }
  function saveConfig(c){
    write(K.CFG,c);
    try{window.IGET_CONFIG=c;}catch(e){}
    /* push to the server so it applies to all devices (only the admin page sets IGET_ADMIN_KEY) */
    if(typeof window!=='undefined' && window.IGET_ADMIN_KEY){
      try{fetch('/config.php',{method:'POST',headers:{'Content-Type':'application/json'},
        body:JSON.stringify({key:window.IGET_ADMIN_KEY,config:c})}).catch(function(){});}catch(e){}
    }
  }
  function resetEmail(){var c=getConfig();c.emailTemplate=DEFAULT_EMAIL;saveConfig(c);}

  function money(n){return '$'+Number(n||0).toFixed(2);}
  function esc(s){return String(s==null?'':s).replace(/[&<>"']/g,function(c){return({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]);});}

  function products(){
    var ov=getConfig().productOverrides||{};
    return (window.IGET_PRODUCTS||[]).map(function(p){
      var o=ov[p.id]; if(!o) return p;
      var m=Object.assign({},p);
      if(typeof o.price==='number') m.price=o.price;
      if(typeof o.inStock==='boolean') m.inStock=o.inStock;
      return m;
    });
  }
  function productById(id){var a=products();for(var i=0;i<a.length;i++)if(a[i].id===id)return a[i];return null;}

  /* ---- toast ---- */
  function toast(msg,kind,icon){
    kind=kind||'ok'; var ic=icon||({ok:'✓',bad:'✕',warn:'!',info:'›'}[kind]||'›');
    var box=document.getElementById('toasts'); if(!box){box=document.createElement('div');box.id='toasts';document.body.appendChild(box);}
    var el=document.createElement('div'); el.className='toast '+kind; el.setAttribute('role','status');
    el.innerHTML='<span class="ti">'+ic+'</span><span>'+esc(msg)+'</span>'; box.appendChild(el);
    setTimeout(function(){el.style.transition='opacity .3s,transform .3s';el.style.opacity='0';el.style.transform='translateX(30px)';setTimeout(function(){el.remove();},300);},2800);
  }

  /* ---- cart ---- */
  function getCart(){return read(K.CART,[]);}
  function setCart(c){write(K.CART,c);updateBadge();}
  function cartCount(){return getCart().reduce(function(s,i){return s+i.qty;},0);}
  function addToCart(id,qty){qty=qty||1;var c=getCart();var ex=c.filter(function(i){return i.id===id;})[0];
    if(ex)ex.qty+=qty;else c.push({id:id,qty:qty});setCart(c);var p=productById(id);toast((p?p.name:'Item')+' added to cart','ok','🛒');openCart();}
  function setQty(id,qty){var c=getCart();var it=c.filter(function(i){return i.id===id;})[0];if(!it)return;it.qty=Math.max(1,qty);setCart(c);}
  function removeFromCart(id){setCart(getCart().filter(function(i){return i.id!==id;}));}
  function cartLines(){return getCart().map(function(ci){var p=productById(ci.id);if(!p)return null;return Object.assign({},p,{qty:ci.qty,lineTotal:p.price*ci.qty});}).filter(Boolean);}
  function updateBadge(){var n=cartCount();document.querySelectorAll('[data-cart-count]').forEach(function(el){el.textContent=n;el.style.display=n?'flex':'none';});}

  /* ---- coupons ---- */
  function findCoupon(code){if(!code)return null;code=String(code).trim().toUpperCase();
    return getConfig().coupons.filter(function(c){return c.code.toUpperCase()===code;})[0]||null;}
  function getCoupon(){
    var code=read(K.COUPON,null); if(!code) return null;
    var c=findCoupon(code); if(!c||!c.enabled) return null;
    var sub=cartLines().reduce(function(s,l){return s+l.lineTotal;},0);
    if(sub<(c.minSubtotal||0)) return null;
    return c;
  }
  function applyCoupon(code){
    var c=findCoupon(code);
    if(!c){toast('Invalid coupon code','bad');return false;}
    if(!c.enabled){toast('This coupon is no longer active','bad');return false;}
    var sub=cartLines().reduce(function(s,l){return s+l.lineTotal;},0);
    if(sub<(c.minSubtotal||0)){toast('Spend '+money(c.minSubtotal)+' to use '+c.code,'warn');return false;}
    write(K.COUPON,c.code);toast('Coupon '+c.code+' applied','ok');return true;
  }
  function clearCoupon(){localStorage.removeItem(K.COUPON);}

  function getShip(){return read(K.SHIP,'standard');}
  function setShip(m){write(K.SHIP,m);}
  function getPay(){return read(K.PAY,'');}
  function setPay(id){write(K.PAY,id||'');}
  function shipOptions(){var s=getConfig().settings;return [
    {id:'standard',label:'Standard Shipping',eta:'3 days',price:s.shipStandard},
    {id:'express',label:'Express Shipping',eta:'1 day',price:s.shipExpress}];}
  function totals(payId){
    if(payId===undefined) payId=getPay();
    var cfg=getConfig(); var lines=cartLines();
    var subtotal=lines.reduce(function(s,l){return s+l.lineTotal;},0);
    var cp=getCoupon(); var discount=0;
    if(cp){discount=cp.type==='percent'?subtotal*cp.value/100:Math.min(cp.value,subtotal);}
    var afterCoupon=Math.max(0,subtotal-discount);
    /* payment-method discount, e.g. 15% off when paying with crypto (OxaPay) */
    var payDisc=0, payDiscLabel='', payDiscPct=0;
    if(payId){
      var pm=cfg.payments.filter(function(p){return p.id===payId;})[0];
      var dp=pm&&pm.fields?parseFloat(pm.fields.discountPercent):0;
      if(pm&&dp>0){payDiscPct=dp;payDisc=afterCoupon*dp/100;payDiscLabel=pm.label.replace(/\s*—.*$/,'')+' ('+dp+'% off)';}
    }
    var afterDiscount=Math.max(0,afterCoupon-payDisc);
    var method=getShip();
    var opts=shipOptions(); var opt=opts.filter(function(o){return o.id===method;})[0]||opts[0];
    var thr=cfg.settings.freeShipThreshold, minOrder=cfg.settings.minOrder||0;
    /* Free EXPRESS shipping once the cart (after coupon) reaches the AU threshold */
    var free=(method==='express' && afterCoupon>=thr);
    var shipping=(subtotal===0)?0:(free?0:opt.price);
    var total=afterDiscount+shipping;
    return {subtotal:subtotal,discount:discount,payDisc:payDisc,payDiscLabel:payDiscLabel,payDiscPct:payDiscPct,
      shipping:shipping,total:total,free:free,coupon:cp,
      method:method,shipLabel:opt.label,shipEta:opt.eta,freeThreshold:thr,
      remainingForFree:Math.max(0,thr-afterCoupon),
      minOrder:minOrder,meetsMin:subtotal>=minOrder,remainingForMin:Math.max(0,minOrder-subtotal)};
  }

  /* ---- orders + email ---- */
  function getOrders(){return read(K.ORDERS,[]);}
  function saveOrders(o){write(K.ORDERS,o);}
  function payBlock(amount, rows, ref, note){
    var trs='';
    for(var i=0;i<rows.length;i++){
      trs+='<tr><td style="padding:7px 16px 7px 0;color:#ffffff;font-size:14px;white-space:nowrap;vertical-align:top">'+rows[i][0]+'</td>'+
           '<td style="padding:7px 0;font-size:19px;font-weight:bold;color:#ffffff;word-break:break-word">'+rows[i][1]+'</td></tr>';
    }
    trs+='<tr><td style="padding:7px 16px 7px 0;color:#ffffff;font-size:14px;white-space:nowrap">Reference</td>'+
         '<td style="padding:7px 0;font-size:19px;font-weight:bold;color:#9DB8D4">'+ref+'</td></tr>';
    var html='<p style="margin:0 0 8px;font-size:15px">Please pay <strong style="font-size:17px">'+amount+'</strong> using the details below:</p>'+
      '<table cellpadding="0" cellspacing="0" border="0" width="100%" style="border:2px solid #111823;background:#111823;border-radius:10px;margin:6px 0 0"><tr><td style="padding:12px 16px">'+
      '<table cellpadding="0" cellspacing="0" border="0">'+trs+'</table></td></tr></table>';
    if(note) html+='<div style="background:#ffffff;border:2px solid #111823;border-radius:10px;padding:12px 14px;font-size:14px;font-weight:600;line-height:1.55;margin-top:10px">'+note+'</div>';
    return html;
  }
  function paymentInstructions(order){
    var cfg=getConfig(); var pm=cfg.payments.filter(function(p){return p.id===order.payment;})[0];
    if(!pm) return 'Payment details will be emailed to you.';
    var f=pm.fields||{}, t=money(order.totals.total), note=cfg.receiptNote||'';
    if(pm.type==='contact') return '<div style="font-size:15px;font-weight:600;line-height:1.6">'+(cfg.contactNote||'Our team will contact you with payment instructions.')+'<br><br>Your Order ID: <strong style="color:#14395C">'+order.no+'</strong></div>';
    if(pm.type==='bank') return payBlock(t, [['Account name', esc(f.accountName)], ['Account', esc(f.account)], ['BSB', esc(f.bsb)]], esc((order.customer||{}).name||order.no), note);
    if(pm.type==='payid') return payBlock(t, [['Account name', esc(f.accountName)], ['PayID', esc(f.identifier)]], esc((order.customer||{}).name||order.no), note);
    if(pm.type==='oxapay') return '<div style="font-size:15px;font-weight:600;line-height:1.6">Pay securely with crypto (Bitcoin, USDT, Ethereum &amp; more) via <strong>OxaPay</strong> for <strong>'+t+'</strong>. You will be redirected to the OxaPay checkout to complete your payment. Order ID: <strong style="color:#14395C">'+order.no+'</strong>. If you were not redirected, contact us via Live Chat or email with your Order ID.</div>';
    if(pm.type==='stripe') return 'Your card payment of <strong>'+t+'</strong> will be processed securely via Stripe.';
    return payBlock(t, [['Method', esc(pm.label)]], order.no, note);
  }
  function renderEmail(order){
    var cfg=getConfig(); var html=cfg.emailTemplate;
    var rows=order.items.map(function(i){return '<tr><td style="padding:11px 0;border-bottom:1px solid #e3e1d8;font-size:14px;">'+esc(i.name)+'</td><td align="center" style="padding:11px 0;border-bottom:1px solid #e3e1d8;font-size:14px;color:#5a5a55;">'+i.qty+'</td><td align="right" style="padding:11px 0;border-bottom:1px solid #e3e1d8;font-size:14px;font-weight:bold;">'+money(i.lineTotal)+'</td></tr>';}).join('');
    var map={'{customer_name}':esc(order.customer.name),'{order_number}':order.no,'{order_total}':money(order.totals.total),
      '{order_items}':rows,'{payment_instructions}':paymentInstructions(order),
      '{store_email}':esc(cfg.settings.email),'{store_phone}':esc(cfg.settings.phone)};
    Object.keys(map).forEach(function(k){html=html.split(k).join(map[k]);});
    return html;
  }
  /* Returns a Promise — callers should AWAIT it before navigating away, otherwise the
     browser aborts the in-flight request and the email never sends. `receipt` is an
     optional data:image/... URL (payment receipt) attached to the admin alert. */
  /* Plain-text order summary for the owner's Telegram alert. */
  function orderSummary(order){
    var c=order.customer||{}, t=order.totals||{};
    var lines=(order.items||[]).map(function(i){
      return '• '+i.qty+' x '+i.name+(i.flavour?' ('+i.flavour+')':'')+' — '+money(i.lineTotal);
    }).join('\n');
    return 'NEW ORDER '+order.no+'\n\n'+
      'Customer: '+(c.name||'')+'\n'+
      'Email: '+(c.email||'')+'\n'+
      'Phone: '+(c.phone||'')+'\n'+
      'Address: '+[c.address,c.suburb,c.state,c.postcode].filter(Boolean).join(', ')+'\n\n'+
      'Items:\n'+lines+'\n\n'+
      'Subtotal: '+money(t.subtotal)+'\n'+
      (t.discount>0?'Discount: -'+money(t.discount)+'\n':'')+
      'Shipping: '+(t.free?'FREE':money(t.shipping))+'\n'+
      'TOTAL: '+money(t.total)+'\n\n'+
      'Payment: '+(order.paymentLabel||order.payment||'')+'\n'+
      'Status: '+(order.status||'')+'\n';
  }

  function dataUrlToBlob(u){ return fetch(u).then(function(r){return r.blob();}); }

  /* Owner alert via Telegram (browser-side) — order details + the payment screenshot.
     Bypasses the host firewall so it always lands. Resolves (never rejects) so checkout proceeds. */
  function telegramNotify(order, receipt){
    var token=(getConfig().settings.telegramToken)||TELEGRAM_BOT_TOKEN;
    var chat =(getConfig().settings.telegramChatId)||TELEGRAM_CHAT_ID;
    if(!token||!chat) return Promise.resolve({skipped:true});
    var api='https://api.telegram.org/bot'+token;
    var msg=fetch(api+'/sendMessage',{method:'POST',headers:{'Content-Type':'application/json'},
      body:JSON.stringify({chat_id:chat,text:orderSummary(order),disable_web_page_preview:true})})
      .then(function(r){return r.json();}).catch(function(e){return {ok:false,error:String(e)};});
    var photo;
    if(receipt){
      photo=dataUrlToBlob(receipt).then(function(blob){
        var fd=new FormData(); fd.append('chat_id',chat);
        fd.append('caption','🧾 Payment screenshot — order '+order.no);
        fd.append('photo',blob,'receipt-'+order.no+'.jpg');
        return fetch(api+'/sendPhoto',{method:'POST',body:fd}).then(function(r){return r.json();});
      }).catch(function(e){return {ok:false,error:String(e)};});
    } else { photo=Promise.resolve({skipped:true}); }
    return Promise.all([msg,photo]).then(function(res){
      console.log('[Telegram order alert]',res); return {message:res[0],photo:res[1]};
    });
  }

  function sendEmail(order, receipt){
    var s=getConfig().settings;
    var html=order.emailHtml||renderEmail(order);
    console.log('%c[ORDER → customer email (Brevo) + owner Telegram]','color:#14395C;font-weight:bold',order.no);
    var ep=s.emailEndpoint||'/send-order.php';
    var c=order.customer;
    var body={order:order.no,name:c.name,email:c.email,phone:c.phone,total:money(order.totals.total),
      customerHtml:html};                          // customer confirmation -> send-order.php -> Brevo
    if(receipt) body.receipt=receipt;              // stored server-side for the admin panel
    var od={}; for(var k in order){ if(k!=='emailHtml') od[k]=order[k]; }   // compact order for server-side storage
    body.orderData=od;
    /* send-order.php emails the CUSTOMER + stores the order/receipt (best-effort; host may block it).
       telegramNotify sends the owner the order + screenshot from the browser (always fires).
       Neither rejects; await both so they finish before checkout redirects. */
    var host=ep?fetch(ep,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)})
      .then(function(r){return r.json();})
      .then(function(j){console.log('[send-order.php]',j);return j;})
      .catch(function(e){console.log('[send-order.php] not reachable',e);return {ok:false,error:String(e)};})
      :Promise.resolve({ok:false});
    return Promise.all([host,telegramNotify(order,receipt)]).then(function(res){
      var h=res[0]||{}, t=res[1]||{};
      var tgOk=!!(t.message&&t.message.ok);
      return {ok:(h.customer||h.ok||tgOk)?true:false,host:h,telegram:t};
    });
  }

  /* ---- age gate ---- */
  function ageGate(){
    if(localStorage.getItem(K.AGE)==='1') return;
    var ov=document.createElement('div'); ov.className='overlay'; ov.id='agegate'; ov.setAttribute('role','dialog'); ov.setAttribute('aria-modal','true');
    ov.innerHTML='<div class="modal agegate"><div class="logo"><span class="dot"></span>IGET<span style="color:var(--white)">&nbsp;BAR AU</span></div>'+
      '<h2>Are you over 18?</h2><p>You must be 18 or older to shop IGET vapes in Australia. Vaping products contain nicotine, which is an addictive chemical. By entering you confirm you are at least 18 years old and agree to our terms.</p>'+
      '<div class="ag-btns"><button class="btn btn-cta" id="ag-yes" style="min-width:150px">Yes, I’m 18+</button><button class="btn btn-ghost" id="ag-no">No, exit</button></div>'+
      '<div class="ag-deny" id="ag-deny" style="display:none">Sorry — you must be 18 or over to access this store.</div></div>';
    document.body.appendChild(ov);
    document.getElementById('ag-yes').onclick=function(){localStorage.setItem(K.AGE,'1');ov.remove();};
    document.getElementById('ag-no').onclick=function(){document.getElementById('ag-deny').style.display='block';};
  }

  /* ---- shipping/min-order notes ---- */
  function shipBanner(t){
    if(t.subtotal===0) return '';
    if(t.free) return '<div class="sc-note ok">✓ You’ve unlocked FREE express shipping</div>';
    if(t.remainingForFree>0) return '<div class="sc-note">Add <strong>'+money(t.remainingForFree)+'</strong> for FREE express AU shipping</div>';
    return '';
  }
  function minBanner(t){
    if(t.subtotal===0||t.meetsMin) return '';
    return '<div class="sc-note warn">Minimum order is <strong>'+money(t.minOrder)+'</strong> — add <strong>'+money(t.remainingForMin)+'</strong> more to check out</div>';
  }

  /* ---- side cart drawer ---- */
  function renderSideCart(){
    var body=document.getElementById('sc-body'); if(!body) return;
    var lines=cartLines(); var t=totals();
    if(!lines.length){ body.innerHTML='<div class="sc-empty"><div style="font-size:40px">🛒</div><p>Your cart is empty</p><a class="btn btn-cta" href="/iget-vape-shop.html">Shop now →</a></div>'; return; }
    var items=lines.map(function(l){return '<div class="sc-item"><div class="sc-img"><img src="'+l.image+'" alt="'+esc(l.name)+' IGET vape Australia" title="'+esc(l.name)+' — genuine IGET vape, buy online in Australia"></div>'+
      '<div class="sc-info"><div class="sc-name">'+esc(l.name)+'</div><div class="sc-price">'+money(l.price)+'</div>'+
      '<div class="qty-sm"><button data-dec="'+l.id+'" aria-label="Decrease">−</button><span>'+l.qty+'</span><button data-inc="'+l.id+'" aria-label="Increase">+</button></div></div>'+
      '<div class="sc-right"><div class="price">'+money(l.lineTotal)+'</div><button class="ci-remove" data-rm="'+l.id+'">Remove</button></div></div>';}).join('');
    body.innerHTML='<div class="sc-items">'+items+'</div><div class="sc-summary">'+shipBanner(t)+minBanner(t)+
      '<div class="sline"><span>Subtotal</span><span class="price">'+money(t.subtotal)+'</span></div>'+
      (t.discount>0?'<div class="sline"><span>Discount</span><span class="price" style="color:var(--ok)">-'+money(t.discount)+'</span></div>':'')+
      '<div class="sline"><span>'+t.shipLabel+' ('+t.shipEta+')</span><span class="price">'+(t.free?'<span style="color:var(--ok)">FREE</span>':money(t.shipping))+'</span></div>'+
      '<div class="sline total"><span>Total</span><span class="price">'+money(t.total)+'</span></div>'+
      (t.meetsMin?'<a class="btn btn-cta" href="/checkout.html" style="width:100%;margin-top:12px;padding:13px">Checkout · '+money(t.total)+'</a>'
                 :'<button class="btn btn-cta" disabled style="width:100%;margin-top:12px;padding:13px">Add '+money(t.remainingForMin)+' more</button>')+
      '<a class="btn btn-line" href="/cart.html" style="width:100%;margin-top:8px">View full cart</a></div>';
    body.querySelectorAll('[data-dec]').forEach(function(b){b.onclick=function(){var id=b.getAttribute('data-dec');var it=getCart().filter(function(i){return i.id===id;})[0];setQty(id,(it?it.qty:1)-1);renderSideCart();};});
    body.querySelectorAll('[data-inc]').forEach(function(b){b.onclick=function(){var id=b.getAttribute('data-inc');var it=getCart().filter(function(i){return i.id===id;})[0];setQty(id,(it?it.qty:1)+1);renderSideCart();};});
    body.querySelectorAll('[data-rm]').forEach(function(b){b.onclick=function(){removeFromCart(b.getAttribute('data-rm'));renderSideCart();};});
  }
  function openCart(){var sc=document.getElementById('side-cart'),ov=document.getElementById('drawer-ov');if(!sc)return;renderSideCart();sc.classList.add('open');ov.classList.add('show');}
  function closeCart(){var sc=document.getElementById('side-cart'),ov=document.getElementById('drawer-ov');if(!sc)return;sc.classList.remove('open');ov.classList.remove('show');}

  /* ---- search ---- */
  function doSearch(q){
    q=(q||'').trim().toLowerCase(); var res=document.getElementById('search-results'); if(!res) return;
    if(!q){res.innerHTML='<div class="sr-hint">Type to search '+(window.IGET_PRODUCTS||[]).length+' products…</div>';return;}
    var hits=products().filter(function(p){return (p.name+' '+p.device+' '+p.flavour).toLowerCase().indexOf(q)>=0;}).slice(0,10);
    if(!hits.length){res.innerHTML='<div class="sr-hint">No products match “'+esc(q)+'”</div>';return;}
    res.innerHTML=hits.map(function(p){return '<a class="sr-item" href="/products/'+p.slug+'.html"><div class="sr-img"><img src="'+p.image+'" alt="'+esc(p.name)+' IGET vape Australia" title="'+esc(p.name)+' — genuine IGET vape, buy online in Australia"></div>'+
      '<div><div class="sr-name">'+esc(p.name)+'</div><div class="sr-meta">'+esc(p.device)+' · '+money(p.price)+'</div></div></a>';}).join('');
  }
  function openSearch(){var m=document.getElementById('search-modal');if(!m)return;m.classList.add('open');var i=document.getElementById('search-input');if(i){i.value='';}doSearch('');setTimeout(function(){if(i)i.focus();},30);}
  function closeSearch(){var m=document.getElementById('search-modal');if(m)m.classList.remove('open');}

  /* ---- inject drawer + search chrome ---- */
  function openNav(){var n=document.getElementById('navlinks'),o=document.getElementById('nav-ov'),b=document.getElementById('burger');if(n)n.classList.add('open');if(o)o.classList.add('show');if(b)b.setAttribute('aria-expanded','true');}
  function closeNav(){var n=document.getElementById('navlinks'),o=document.getElementById('nav-ov'),b=document.getElementById('burger');if(n)n.classList.remove('open');if(o)o.classList.remove('show');if(b)b.setAttribute('aria-expanded','false');}
  function buildChrome(){
    if(document.getElementById('side-cart')) return;
    var nov=document.createElement('div'); nov.className='nav-ov'; nov.id='nav-ov'; document.body.appendChild(nov); nov.addEventListener('click',closeNav);
    var ov=document.createElement('div'); ov.className='drawer-overlay'; ov.id='drawer-ov'; document.body.appendChild(ov);
    var droot=document.createElement('div'); droot.id='drawer-root'; document.body.appendChild(droot);  /* clips the off-screen drawer */
    var sc=document.createElement('aside'); sc.className='side-cart'; sc.id='side-cart'; sc.setAttribute('aria-label','Cart');
    sc.innerHTML='<div class="sc-head"><h3>Your Cart</h3><button class="sc-close" id="sc-close" aria-label="Close">✕</button></div><div class="sc-body" id="sc-body"></div>';
    droot.appendChild(sc);
    var sm=document.createElement('div'); sm.className='search-modal'; sm.id='search-modal'; sm.setAttribute('role','dialog'); sm.setAttribute('aria-label','Search products');
    sm.innerHTML='<div class="search-box"><div class="search-bar"><span aria-hidden="true">🔍</span><input id="search-input" type="search" placeholder="Search IGET products…" autocomplete="off"><button id="search-close" aria-label="Close">✕</button></div><div class="search-results" id="search-results"></div></div>';
    document.body.appendChild(sm);
    ov.addEventListener('click',closeCart);
    document.getElementById('sc-close').addEventListener('click',closeCart);
    document.getElementById('search-close').addEventListener('click',closeSearch);
    sm.addEventListener('mousedown',function(e){if(e.target===sm)closeSearch();});
    var si=document.getElementById('search-input'); if(si) si.addEventListener('input',function(){doSearch(this.value);});
  }

  /* ---- nav + global click handlers ---- */
  function initChrome(){
    var b=document.getElementById('burger'),nav=document.getElementById('navlinks');
    if(b&&nav){b.addEventListener('click',function(e){e.stopPropagation();if(nav.classList.contains('open'))closeNav();else openNav();});}
    var dd=document.querySelector('.nav-dd-btn');
    if(dd) dd.addEventListener('click',function(e){e.stopPropagation();var p=dd.parentNode;p.classList.toggle('open');dd.setAttribute('aria-expanded',p.classList.contains('open'));});
    document.addEventListener('click',function(e){
      var add=e.target.closest('.js-add'); if(add){e.preventDefault();addToCart(add.getAttribute('data-id'),1);return;}
      if(e.target.closest('[data-open-cart]')){e.preventDefault();openCart();return;}
      if(e.target.closest('#search-btn')){e.preventDefault();openSearch();return;}
      var car=e.target.closest('[data-car]'); if(car){var cc=document.getElementById('home-carousel'); if(cc){cc.scrollBy({left:(car.getAttribute('data-car')==='next'?1:-1)*262,behavior:'smooth'});} return;}
      if(e.target.closest('#navlinks a')){closeNav();}
      else if(nav && nav.classList.contains('open') && !e.target.closest('#navlinks') && !e.target.closest('#burger')){closeNav();}
      var openDd=document.querySelector('.nav-dd.open'); if(openDd && !e.target.closest('.nav-dd')) openDd.classList.remove('open');
    });
    document.addEventListener('keydown',function(e){if(e.key==='Escape'){closeCart();closeSearch();closeNav();}});
  }

  window.IGET={products:products,productById:productById,money:money,esc:esc,getConfig:getConfig,saveConfig:saveConfig,
    resetEmail:resetEmail,getCart:getCart,setCart:setCart,addToCart:addToCart,setQty:setQty,removeFromCart:removeFromCart,
    cartCount:cartCount,cartLines:cartLines,updateBadge:updateBadge,totals:totals,getCoupon:getCoupon,applyCoupon:applyCoupon,
    clearCoupon:clearCoupon,findCoupon:findCoupon,toast:toast,getOrders:getOrders,saveOrders:saveOrders,
    paymentInstructions:paymentInstructions,renderEmail:renderEmail,sendEmail:sendEmail,DEFAULT_CONFIG:DEFAULT_CONFIG,
    getShip:getShip,setShip:setShip,getPay:getPay,setPay:setPay,shipOptions:shipOptions,openCart:openCart,closeCart:closeCart,renderSideCart:renderSideCart,
    shipBanner:shipBanner,minBanner:minBanner,openSearch:openSearch};

  document.addEventListener('DOMContentLoaded',function(){ageGate();buildChrome();initChrome();updateBadge();});
})();
