diff --git a/site/admin.html b/site/admin.html
index 2359f1a..03edd57 100644
--- a/site/admin.html
+++ b/site/admin.html
@@ -204,6 +204,7 @@ function invEdit(sku){
In stock
${fld('Notes','eNotes',r.notes)}
+
`);
}
@@ -240,6 +241,65 @@ async function invDoAdd(){
await fetch('/admin/inventory/add',{method:'POST',headers:hdr(),body:JSON.stringify(body)});
invModalClose(); loadInv();
}
+
+// ---------- Label print + RFID (drives the local rfid-daemon :7790, Chafon H102) ----------
+const RFID_DAEMON = 'http://127.0.0.1:7790'; // localhost is a secure context β HTTPS page may call it
+function invLabel(sku){
+ const r = invItems[sku] || { sku };
+ const qr = 'https://api.qrserver.com/v1/create-qr-code/?size=120x120&margin=0&data=' + encodeURIComponent(r.sku);
+ invModalBox(`π· Label β ${escapeH(r.title||sku)}
+
+
+
${escapeH(r.artist||'')}
+
${escapeH(r.title||'')}
+
${money(r.price)}
+
${escapeH(r.sku)}${r.condition?' Β· '+escapeH(r.condition):''}
+
+

+
+
+ checking tag readerβ¦
+
+
+ `);
+ daemonPing();
+}
+async function daemonPing(){
+ const el = $('#lblDaemon'); if(!el) return;
+ try { const r = await fetch(RFID_DAEMON+'/status', {signal:AbortSignal.timeout(2500)}).then(x=>x.json());
+ el.innerHTML = 'β tag reader connected'; }
+ catch(e){ el.innerHTML = 'β rfid-daemon not running on :7790 β RFID disabled (label still prints)'; }
+}
+function invDoPrint(r){
+ const qr = 'https://api.qrserver.com/v1/create-qr-code/?size=200x200&margin=0&data=' + encodeURIComponent(r.sku);
+ const html = `
+ ${escapeH(r.artist||'')}
${escapeH(r.title||'')}
+
${money(r.price)}
${escapeH(r.sku)}
+

`;
+ const w = window.open('', '_blank', 'width=420,height=240');
+ if(w){ w.document.open(); w.document.write(html); w.document.close(); }
+ if($('#lblRfid') && $('#lblRfid').checked) rfidWrite(r.sku, r.release_id);
+}
+async function rfidWrite(sku, releaseId){
+ const msg = $('#lblMsg'); if(msg) msg.innerHTML = 'β‘ writing tag (present the chip to the reader)β¦';
+ try {
+ await fetch(RFID_DAEMON+'/clear-mask', {method:'POST', signal:AbortSignal.timeout(3000)}).catch(()=>{});
+ const body = { sku }; if(releaseId) body.releaseId = String(releaseId);
+ const d = await fetch(RFID_DAEMON+'/write-tag', {method:'POST', headers:{'Content-Type':'application/json'},
+ body:JSON.stringify(body), signal:AbortSignal.timeout(120000)}).then(x=>x.json());
+ if(msg) msg.innerHTML = d.ok ? `β RFID tag programmed (${escapeH(sku)})`
+ : `RFID write failed: ${escapeH(d.error||'?')}`;
+ } catch(e){ if(msg) msg.innerHTML = 'RFID daemon unreachable (:7790)'; }
+}
function invImport(){
invModalBox(`Import list (bulk stock-in)
One per line β Release ID / barcode / catalogue no. Resolved against the catalog, each becomes an in-stock item.