{"id":2217,"date":"2026-04-09T15:58:36","date_gmt":"2026-04-09T15:58:36","guid":{"rendered":"https:\/\/primetoolhub.com\/?page_id=2217"},"modified":"2026-08-08T12:54:58","modified_gmt":"2026-08-08T12:54:58","slug":"advanced-qr-code-generator-offline","status":"publish","type":"page","link":"https:\/\/schoolict.net\/tools\/advanced-qr-code-generator-offline\/","title":{"rendered":"Free Advanced QR Code Generator &#8211; Custom Logo &amp; Colors"},"content":{"rendered":"<div class=\"pth-hero-section\">\n<div class=\"pth-hero-content\">\n<h2><b data-path-to-node=\"1,0,0\" data-index-in-node=\"0\">Design Standout QR Codes for Free<\/b> \u2014 Add Custom Logos, Colors &amp; Brand Styling Instantly<\/h2>\n<p>Create custom QR codes instantly with our 100% offline Advanced QR Code Generator. Embed logos, change colors, and generate WiFi or vCard QR codes securely.<\/p>\n<div id=\"pth-toc-placeholder\">\u00a0<\/div>\n<\/div>\n<div class=\"pth-hero-image\"><img decoding=\"async\" src=\"https:\/\/schoolict.net\/tools\/wp-content\/uploads\/2026\/04\/Advanced-QR-Code-Generator-1024x572.jpeg\" alt=\"Advanced QR Code Generator\" width=\"450\" height=\"253\" data-no-lazy=\"1\" \/><\/div>\n<\/div>\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>Table of Contents<\/h2><nav><ul><li><a href=\"#\ud83d\udfe2-one-page-for-making-codes-and-reading-them\">\ud83d\udfe2 One Page For Making Codes And Reading Them<\/a><\/li><li><a href=\"#\ud83d\udfe1-making-a-wi-fi-code-start-to-finish\">\ud83d\udfe1 Making A WiFi Code, Start To Finish<\/a><\/li><li><a href=\"#\ud83d\udfe2-choosing-a-barcode-format\">\ud83d\udfe2 Choosing A Barcode Format<\/a><ul><li><a href=\"#a-real-example\">A real example<\/a><\/li><\/ul><\/li><li><a href=\"#\ud83d\udfe1-two-jobs-worth-knowing-about\">\ud83d\udfe1 Two Jobs Worth Knowing About<\/a><ul><li><a href=\"#contact-cards-for-an-event\">Contact cards for an event<\/a><\/li><li><a href=\"#asset-labels-for-a-school-or-office\">Asset labels for a school or office<\/a><\/li><\/ul><\/li><li><a href=\"#\ud83d\udd34-common-mistakes-and-real-limits\">\ud83d\udd34 Common Mistakes and Real Limits<\/a><\/li><\/ul><\/nav><\/div>\n\n\n<link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.css\">\r\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/easyqrcodejs@4.6.1\/dist\/easy.qrcode.min.js\" data-no-optimize=\"1\" data-no-minify=\"1\" data-cfasync=\"false\"><\/script>\r\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/jsbarcode@3.11.6\/dist\/JsBarcode.all.min.js\" data-no-optimize=\"1\" data-no-minify=\"1\" data-cfasync=\"false\"><\/script>\r\n<script src=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.js\" data-no-optimize=\"1\" data-no-minify=\"1\" data-cfasync=\"false\"><\/script>\r\n\r\n<style>\r\n\/* STRICTLY SCOPED CSS - PTH QR & BARCODE STUDIO *\/\r\n#pth-qrcode-wrapper {\r\n  --blu: #2563eb; --grn: #047857; --red: #dc2626; --amb: #b45309; --pur: #6d28d9;\r\n  --bg1: #ffffff; --bg2: #f8fafc; --bg3: #f1f5f9;\r\n  --bd1: #cbd5e1; --bd2: #e2e8f0;\r\n  --tx1: #0f172a; --tx2: #475569;\r\n  font-family: 'Inter', system-ui, sans-serif;\r\n  max-width: 1400px; margin: 0 auto; box-sizing: border-box;\r\n  background: var(--bg3); padding: 20px; border-radius: 16px; color: var(--tx1); opacity: 1;\r\n}\r\n#pth-qrcode-wrapper * { box-sizing: border-box; min-width: 0; }\r\n\r\n#pth-qrcode-wrapper .pth-intro { background: var(--bg1); border: 1px solid var(--bd2); border-radius: 12px; padding: 22px; margin-bottom: 18px; }\r\n#pth-qrcode-wrapper .pth-tool-title { font-size: 27px; font-weight: 800; color: var(--blu); margin: 0 0 10px 0; line-height: 1.25; }\r\n#pth-qrcode-wrapper .pth-intro p { font-size: 14px; color: var(--tx2); margin: 0; line-height: 1.65; }\r\n#pth-qrcode-wrapper .pth-badges { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }\r\n#pth-qrcode-wrapper .pth-badge-top { font-size: 12px; font-weight: 600; padding: 4px 12px; border-radius: 20px; }\r\n#pth-qrcode-wrapper .pth-version-badge { background: #eff6ff; color: #1d4ed8; border: 1px solid #bfdbfe; }\r\n#pth-qrcode-wrapper .pth-status-offline { background: #ecfdf5; color: #065f46; border: 1px solid #a7f3d0; }\r\n#pth-qrcode-wrapper .pth-badge-ora { background: #fff7ed; color: #9a3412; border: 1px solid #fed7aa; }\r\n\r\n#pth-qrcode-wrapper .pth-actions-bar { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }\r\n#pth-qrcode-wrapper .layout { display: grid; grid-template-columns: 1.8fr 1fr; gap: 16px; align-items: start; }\r\n#pth-qrcode-wrapper .layout.fw { grid-template-columns: 1fr; }\r\n\r\n#pth-qrcode-wrapper .card { background: var(--bg1); border: 1px solid var(--bd2); border-radius: 12px; overflow: hidden; }\r\n#pth-qrcode-wrapper .card-pad { padding: 16px; }\r\n#pth-qrcode-wrapper .hdr { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; border-bottom: 1px solid var(--bd2); background: var(--bg2); flex-wrap: wrap; gap: 8px; }\r\n#pth-qrcode-wrapper .hdr-title { font-size: 15px; font-weight: 700; color: var(--tx1); margin: 0; }\r\n#pth-qrcode-wrapper label { font-size: 12px; color: var(--tx2); font-weight: 600; }\r\n\r\n#pth-qrcode-wrapper .btn { padding: 8px 14px; border-radius: 8px; font-size: 13px; font-weight: 600; cursor: pointer; border: 1px solid var(--bd1); transition: background .15s; display: inline-flex; align-items: center; gap: 6px; font-family: inherit; background: var(--bg1); color: var(--tx1); }\r\n#pth-qrcode-wrapper .btn:hover { background: var(--bg2); }\r\n#pth-qrcode-wrapper .btn:disabled { color: #94a3b8; cursor: not-allowed; background: var(--bg3); }\r\n#pth-qrcode-wrapper .btn-primary { background: var(--blu); color: #fff; border-color: var(--blu); }\r\n#pth-qrcode-wrapper .btn-primary:hover { background: #1d4ed8; }\r\n#pth-qrcode-wrapper .btn-grn { background: var(--grn); color: #fff; border-color: var(--grn); }\r\n#pth-qrcode-wrapper .btn-grn:hover { background: #065f46; }\r\n#pth-qrcode-wrapper .btn-red { background: var(--red); color: #fff; border-color: var(--red); }\r\n#pth-qrcode-wrapper .btn-sm { padding: 5px 10px; font-size: 12px; }\r\n\r\n#pth-qrcode-wrapper .tabs { display: flex; gap: 4px; padding: 8px 8px 0; background: var(--bg2); border-bottom: 1px solid var(--bd2); flex-wrap: wrap; }\r\n#pth-qrcode-wrapper .tab { padding: 9px 15px; border-radius: 8px 8px 0 0; border: 1px solid transparent; background: transparent; color: var(--tx2); font-size: 13px; font-weight: 700; cursor: pointer; font-family: inherit; }\r\n#pth-qrcode-wrapper .tab:hover { background: var(--bg3); }\r\n#pth-qrcode-wrapper .tab.on { background: var(--bg1); color: var(--blu); border-color: var(--bd2); border-bottom-color: var(--bg1); margin-bottom: -1px; }\r\n#pth-qrcode-wrapper .panel { display: none; }\r\n#pth-qrcode-wrapper .panel.on { display: block; }\r\n\r\n#pth-qrcode-wrapper .sect { border-top: 1px solid var(--bd2); padding-top: 14px; margin-top: 14px; }\r\n#pth-qrcode-wrapper .sect:first-child { border-top: none; padding-top: 0; margin-top: 0; }\r\n#pth-qrcode-wrapper .sect h4 { font-size: 12px; font-weight: 800; color: var(--tx2); margin: 0 0 10px; text-transform: uppercase; letter-spacing: .5px; }\r\n#pth-qrcode-wrapper .grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }\r\n#pth-qrcode-wrapper .grid3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }\r\n#pth-qrcode-wrapper .fld { margin-bottom: 11px; }\r\n#pth-qrcode-wrapper .fld label { display: block; margin-bottom: 4px; }\r\n#pth-qrcode-wrapper .row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 11px; }\r\n\r\n#pth-qrcode-wrapper input[type=\"text\"], #pth-qrcode-wrapper input[type=\"number\"], #pth-qrcode-wrapper input[type=\"tel\"],\r\n#pth-qrcode-wrapper input[type=\"email\"], #pth-qrcode-wrapper input[type=\"url\"], #pth-qrcode-wrapper input[type=\"date\"],\r\n#pth-qrcode-wrapper input[type=\"time\"], #pth-qrcode-wrapper select, #pth-qrcode-wrapper textarea {\r\n  width: 100%; padding: 8px 10px; border: 1px solid var(--bd1); border-radius: 7px; font-size: 13px; font-family: inherit; color: var(--tx1); background: var(--bg1);\r\n}\r\n#pth-qrcode-wrapper textarea { resize: vertical; min-height: 76px; }\r\n#pth-qrcode-wrapper input[type=\"color\"] { width: 100%; height: 36px; padding: 2px; border: 1px solid var(--bd1); border-radius: 7px; background: var(--bg1); cursor: pointer; }\r\n#pth-qrcode-wrapper input[type=\"range\"] { width: 100%; }\r\n#pth-qrcode-wrapper input[type=\"checkbox\"] { width: auto; }\r\n#pth-qrcode-wrapper .chk { display: flex; align-items: center; gap: 7px; font-size: 13px; color: var(--tx1); font-weight: 600; cursor: pointer; }\r\n\r\n#pth-qrcode-wrapper .types { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 7px; }\r\n#pth-qrcode-wrapper .type { border: 1px solid var(--bd1); background: var(--bg2); border-radius: 8px; padding: 9px 5px; font-size: 11px; font-weight: 700; color: var(--tx1); cursor: pointer; text-align: center; font-family: inherit; }\r\n#pth-qrcode-wrapper .type:hover { background: var(--bg3); }\r\n#pth-qrcode-wrapper .type.on { background: var(--blu); color: #fff; border-color: var(--blu); }\r\n#pth-qrcode-wrapper .type .ic { display: block; font-size: 16px; margin-bottom: 3px; }\r\n\r\n#pth-qrcode-wrapper .presets { display: flex; gap: 7px; flex-wrap: wrap; }\r\n#pth-qrcode-wrapper .preset { width: 30px; height: 30px; border-radius: 7px; border: 2px solid var(--bd1); cursor: pointer; padding: 0; }\r\n#pth-qrcode-wrapper .preset:hover { border-color: var(--tx2); }\r\n\r\n#pth-qrcode-wrapper .stage { background: var(--bg2); border: 1px solid var(--bd2); border-radius: 10px; padding: 18px; text-align: center; min-height: 300px; display: flex; align-items: center; justify-content: center; }\r\n#pth-qrcode-wrapper .stage canvas, #pth-qrcode-wrapper .stage svg { max-width: 100%; height: auto; }\r\n#pth-qrcode-wrapper #pth-qr-out, #pth-qrcode-wrapper #pth-bc-out { display: inline-block; }\r\n#pth-qrcode-wrapper .ph { color: var(--tx2); font-size: 13px; font-weight: 600; }\r\n\r\n#pth-qrcode-wrapper #pth-map { height: 230px; border-radius: 9px; border: 1px solid var(--bd1); margin-bottom: 11px; }\r\n#pth-qrcode-wrapper .note { background: #fffbeb; border: 1px solid #fde68a; border-radius: 8px; padding: 10px 12px; font-size: 12px; color: #78350f; line-height: 1.6; margin-bottom: 12px; }\r\n#pth-qrcode-wrapper .note a { color: #1d4ed8; font-weight: 700; }\r\n#pth-qrcode-wrapper .info { background: #eff6ff; border: 1px solid #bfdbfe; border-radius: 8px; padding: 10px 12px; font-size: 12px; color: #1e3a8a; line-height: 1.6; margin-bottom: 12px; }\r\n#pth-qrcode-wrapper .err { background: #fef2f2; border: 1px solid #fecaca; border-radius: 8px; padding: 10px 12px; font-size: 12px; color: #991b1b; font-weight: 600; margin-bottom: 12px; display: none; }\r\n#pth-qrcode-wrapper .err.on { display: block; }\r\n\r\n#pth-qrcode-wrapper #pth-video { width: 100%; max-width: 460px; border-radius: 10px; background: #0f172a; display: block; margin: 0 auto; }\r\n#pth-qrcode-wrapper .scanbox { text-align: center; }\r\n#pth-qrcode-wrapper .result { background: var(--bg2); border: 1px solid var(--bd2); border-radius: 9px; padding: 13px; margin-top: 12px; text-align: left; }\r\n#pth-qrcode-wrapper .result .rt { font-size: 11px; font-weight: 800; color: var(--pur); text-transform: uppercase; letter-spacing: .5px; margin-bottom: 5px; }\r\n#pth-qrcode-wrapper .result .rv { font-size: 13px; color: var(--tx1); font-weight: 600; word-break: break-all; line-height: 1.6; }\r\n#pth-qrcode-wrapper .hist { max-height: 230px; overflow-y: auto; border: 1px solid var(--bd2); border-radius: 8px; margin-top: 10px; }\r\n#pth-qrcode-wrapper .hitem { padding: 9px 11px; border-bottom: 1px solid var(--bd2); font-size: 12px; }\r\n#pth-qrcode-wrapper .hitem:last-child { border-bottom: none; }\r\n#pth-qrcode-wrapper .hitem b { color: var(--pur); font-size: 10px; text-transform: uppercase; }\r\n#pth-qrcode-wrapper .hitem div { color: var(--tx1); font-weight: 600; word-break: break-all; margin-top: 2px; }\r\n#pth-qrcode-wrapper .empty { font-size: 12px; color: var(--tx2); text-align: center; padding: 20px 10px; }\r\n\r\n#pth-qrcode-wrapper #pth-qr-toast { position: fixed; bottom: 20px; right: 20px; background: #0f172a; color: #fff; padding: 12px 18px; border-radius: 10px; font-size: 13px; font-weight: 600; z-index: 999999; display: none; max-width: 330px; line-height: 1.5; }\r\n#pth-qrcode-wrapper #pth-qr-toast.show { display: block; }\r\n#pth-qrcode-wrapper #pth-qr-toast.err { background: #991b1b; }\r\n#pth-qrcode-wrapper #pth-qr-toast.ok { background: #065f46; }\r\n\r\n@media (max-width: 900px) {\r\n  #pth-qrcode-wrapper { padding: 14px; }\r\n  #pth-qrcode-wrapper .layout { grid-template-columns: 1fr; }\r\n  #pth-qrcode-wrapper .grid3 { grid-template-columns: 1fr 1fr; }\r\n}\r\n<\/style>\r\n\r\n<div id=\"pth-qrcode-wrapper\">\r\n\r\n  <div class=\"pth-intro\">\r\n    <h2 class=\"pth-tool-title\">QR &amp; Barcode Studio - Create and Read Codes Offline<\/h2>\r\n    <div class=\"pth-badges\">\r\n      <span class=\"pth-badge-top pth-version-badge\">v7.1<\/span>\r\n      <span class=\"pth-badge-top pth-status-offline\">100% Offline<\/span>\r\n      <span class=\"pth-badge-top pth-badge-ora\">Zero Server Uploads<\/span>\r\n    <\/div>\r\n    <p>Build a QR code for eleven kinds of data, generate retail and inventory barcodes with automatic check digits, or point your camera at an existing code to read it back. Everything is drawn in your browser, so nothing you encode is ever sent anywhere.<\/p>\r\n  <\/div>\r\n\r\n  <div class=\"pth-actions-bar\">\r\n    <button type=\"button\" class=\"btn\" id=\"pth-qr-sample\">Load Sample<\/button>\r\n    <button type=\"button\" class=\"btn\" id=\"pth-qr-fw\">Full Width<\/button>\r\n    <button type=\"button\" class=\"btn\" id=\"pth-qr-clear\">Clear<\/button>\r\n  <\/div>\r\n\r\n  <div class=\"card\" style=\"margin-bottom:16px\">\r\n    <div class=\"tabs\" role=\"tablist\">\r\n      <button type=\"button\" class=\"tab on\" data-tab=\"qr\" role=\"tab\">QR Code<\/button>\r\n      <button type=\"button\" class=\"tab\" data-tab=\"bc\" role=\"tab\">Barcode<\/button>\r\n      <button type=\"button\" class=\"tab\" data-tab=\"scan\" role=\"tab\">Scanner<\/button>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- ============ QR PANEL ============ -->\r\n  <div class=\"panel on\" data-panel=\"qr\">\r\n    <div class=\"layout\" id=\"pth-qr-layout\">\r\n\r\n      <div class=\"card\">\r\n        <div class=\"hdr\"><h3 class=\"hdr-title\">QR Content<\/h3><\/div>\r\n        <div class=\"card-pad\">\r\n\r\n          <div class=\"sect\">\r\n            <h4>Data Type<\/h4>\r\n            <div class=\"types\" id=\"pth-qr-types\">\r\n              <button type=\"button\" class=\"type on\" data-t=\"url\"><span class=\"ic\" aria-hidden=\"true\">&#127760;<\/span>URL \/ Text<\/button>\r\n              <button type=\"button\" class=\"type\" data-t=\"wifi\"><span class=\"ic\" aria-hidden=\"true\">&#128246;<\/span>WiFi<\/button>\r\n              <button type=\"button\" class=\"type\" data-t=\"vcard\"><span class=\"ic\" aria-hidden=\"true\">&#128100;<\/span>Contact<\/button>\r\n              <button type=\"button\" class=\"type\" data-t=\"email\"><span class=\"ic\" aria-hidden=\"true\">&#9993;<\/span>Email<\/button>\r\n              <button type=\"button\" class=\"type\" data-t=\"sms\"><span class=\"ic\" aria-hidden=\"true\">&#128172;<\/span>SMS<\/button>\r\n              <button type=\"button\" class=\"type\" data-t=\"tel\"><span class=\"ic\" aria-hidden=\"true\">&#128222;<\/span>Phone<\/button>\r\n              <button type=\"button\" class=\"type\" data-t=\"wa\"><span class=\"ic\" aria-hidden=\"true\">&#128241;<\/span>WhatsApp<\/button>\r\n              <button type=\"button\" class=\"type\" data-t=\"geo\"><span class=\"ic\" aria-hidden=\"true\">&#128205;<\/span>Location<\/button>\r\n              <button type=\"button\" class=\"type\" data-t=\"event\"><span class=\"ic\" aria-hidden=\"true\">&#128197;<\/span>Event<\/button>\r\n              <button type=\"button\" class=\"type\" data-t=\"crypto\"><span class=\"ic\" aria-hidden=\"true\">&#8383;<\/span>Crypto<\/button>\r\n              <button type=\"button\" class=\"type\" data-t=\"upi\"><span class=\"ic\" aria-hidden=\"true\">&#128179;<\/span>Payment<\/button>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <div class=\"sect\">\r\n            <h4>Details<\/h4>\r\n            <div id=\"pth-qr-forms\">\r\n\r\n              <div class=\"qf\" data-f=\"url\">\r\n                <div class=\"fld\"><label for=\"qf-url\">Website address or any text<\/label>\r\n                  <textarea id=\"qf-url\" placeholder=\"https:\/\/example.com\">https:\/\/schoolict.net\/tools<\/textarea><\/div>\r\n              <\/div>\r\n\r\n              <div class=\"qf\" data-f=\"wifi\" style=\"display:none\">\r\n                <div class=\"fld\"><label for=\"qf-ssid\">Network name (SSID)<\/label><input type=\"text\" id=\"qf-ssid\" placeholder=\"MyNetwork\"><\/div>\r\n                <div class=\"grid2\">\r\n                  <div class=\"fld\"><label for=\"qf-wpass\">Password<\/label><input type=\"text\" id=\"qf-wpass\" placeholder=\"Network password\"><\/div>\r\n                  <div class=\"fld\"><label for=\"qf-wenc\">Security<\/label>\r\n                    <select id=\"qf-wenc\"><option value=\"WPA\">WPA \/ WPA2<\/option><option value=\"WEP\">WEP<\/option><option value=\"nopass\">Open network<\/option><\/select><\/div>\r\n                <\/div>\r\n                <label class=\"chk\"><input type=\"checkbox\" id=\"qf-whidden\"> Hidden network<\/label>\r\n              <\/div>\r\n\r\n              <div class=\"qf\" data-f=\"vcard\" style=\"display:none\">\r\n                <div class=\"grid2\">\r\n                  <div class=\"fld\"><label for=\"qf-vfn\">First name<\/label><input type=\"text\" id=\"qf-vfn\"><\/div>\r\n                  <div class=\"fld\"><label for=\"qf-vln\">Last name<\/label><input type=\"text\" id=\"qf-vln\"><\/div>\r\n                <\/div>\r\n                <div class=\"grid2\">\r\n                  <div class=\"fld\"><label for=\"qf-vtel\">Phone<\/label><input type=\"tel\" id=\"qf-vtel\"><\/div>\r\n                  <div class=\"fld\"><label for=\"qf-vmail\">Email<\/label><input type=\"email\" id=\"qf-vmail\"><\/div>\r\n                <\/div>\r\n                <div class=\"grid2\">\r\n                  <div class=\"fld\"><label for=\"qf-vorg\">Organisation<\/label><input type=\"text\" id=\"qf-vorg\"><\/div>\r\n                  <div class=\"fld\"><label for=\"qf-vtitle\">Job title<\/label><input type=\"text\" id=\"qf-vtitle\"><\/div>\r\n                <\/div>\r\n                <div class=\"fld\"><label for=\"qf-vurl\">Website<\/label><input type=\"url\" id=\"qf-vurl\"><\/div>\r\n              <\/div>\r\n\r\n              <div class=\"qf\" data-f=\"email\" style=\"display:none\">\r\n                <div class=\"fld\"><label for=\"qf-eto\">Send to<\/label><input type=\"email\" id=\"qf-eto\" placeholder=\"name@example.com\"><\/div>\r\n                <div class=\"fld\"><label for=\"qf-esub\">Subject<\/label><input type=\"text\" id=\"qf-esub\"><\/div>\r\n                <div class=\"fld\"><label for=\"qf-ebody\">Message<\/label><textarea id=\"qf-ebody\"><\/textarea><\/div>\r\n              <\/div>\r\n\r\n              <div class=\"qf\" data-f=\"sms\" style=\"display:none\">\r\n                <div class=\"fld\"><label for=\"qf-snum\">Phone number<\/label><input type=\"tel\" id=\"qf-snum\" placeholder=\"+94771234567\"><\/div>\r\n                <div class=\"fld\"><label for=\"qf-smsg\">Message<\/label><textarea id=\"qf-smsg\"><\/textarea><\/div>\r\n              <\/div>\r\n\r\n              <div class=\"qf\" data-f=\"tel\" style=\"display:none\">\r\n                <div class=\"fld\"><label for=\"qf-tnum\">Phone number<\/label><input type=\"tel\" id=\"qf-tnum\" placeholder=\"+94112345678\"><\/div>\r\n              <\/div>\r\n\r\n              <div class=\"qf\" data-f=\"wa\" style=\"display:none\">\r\n                <div class=\"fld\"><label for=\"qf-wanum\">WhatsApp number with country code, no plus sign<\/label><input type=\"tel\" id=\"qf-wanum\" placeholder=\"94771234567\"><\/div>\r\n                <div class=\"fld\"><label for=\"qf-wamsg\">Starter message<\/label><textarea id=\"qf-wamsg\"><\/textarea><\/div>\r\n              <\/div>\r\n\r\n              <div class=\"qf\" data-f=\"geo\" style=\"display:none\">\r\n                <div id=\"pth-map\"><\/div>\r\n                <div class=\"grid2\">\r\n                  <div class=\"fld\"><label for=\"qf-lat\">Latitude<\/label><input type=\"text\" id=\"qf-lat\" value=\"6.9271\"><\/div>\r\n                  <div class=\"fld\"><label for=\"qf-lng\">Longitude<\/label><input type=\"text\" id=\"qf-lng\" value=\"79.8612\"><\/div>\r\n                <\/div>\r\n                <div class=\"info\">Click anywhere on the map to drop a pin, or type the coordinates directly.<\/div>\r\n              <\/div>\r\n\r\n              <div class=\"qf\" data-f=\"event\" style=\"display:none\">\r\n                <div class=\"fld\"><label for=\"qf-etitle\">Event name<\/label><input type=\"text\" id=\"qf-etitle\"><\/div>\r\n                <div class=\"fld\"><label for=\"qf-eloc\">Location<\/label><input type=\"text\" id=\"qf-eloc\"><\/div>\r\n                <div class=\"grid2\">\r\n                  <div class=\"fld\"><label for=\"qf-edate\">Start date<\/label><input type=\"date\" id=\"qf-edate\"><\/div>\r\n                  <div class=\"fld\"><label for=\"qf-etime\">Start time<\/label><input type=\"time\" id=\"qf-etime\"><\/div>\r\n                <\/div>\r\n                <div class=\"grid2\">\r\n                  <div class=\"fld\"><label for=\"qf-edate2\">End date<\/label><input type=\"date\" id=\"qf-edate2\"><\/div>\r\n                  <div class=\"fld\"><label for=\"qf-etime2\">End time<\/label><input type=\"time\" id=\"qf-etime2\"><\/div>\r\n                <\/div>\r\n              <\/div>\r\n\r\n              <div class=\"qf\" data-f=\"crypto\" style=\"display:none\">\r\n                <div class=\"grid2\">\r\n                  <div class=\"fld\"><label for=\"qf-ccoin\">Coin<\/label>\r\n                    <select id=\"qf-ccoin\"><option value=\"bitcoin\">Bitcoin<\/option><option value=\"ethereum\">Ethereum<\/option><option value=\"litecoin\">Litecoin<\/option><\/select><\/div>\r\n                  <div class=\"fld\"><label for=\"qf-camt\">Amount (optional)<\/label><input type=\"text\" id=\"qf-camt\"><\/div>\r\n                <\/div>\r\n                <div class=\"fld\"><label for=\"qf-caddr\">Wallet address<\/label><input type=\"text\" id=\"qf-caddr\"><\/div>\r\n              <\/div>\r\n\r\n              <div class=\"qf\" data-f=\"upi\" style=\"display:none\">\r\n                <div class=\"fld\"><label for=\"qf-uid\">Payment ID<\/label><input type=\"text\" id=\"qf-uid\" placeholder=\"name@bank\"><\/div>\r\n                <div class=\"grid2\">\r\n                  <div class=\"fld\"><label for=\"qf-uname\">Payee name<\/label><input type=\"text\" id=\"qf-uname\"><\/div>\r\n                  <div class=\"fld\"><label for=\"qf-uamt\">Amount (optional)<\/label><input type=\"text\" id=\"qf-uamt\"><\/div>\r\n                <\/div>\r\n                <div class=\"fld\"><label for=\"qf-unote\">Note<\/label><input type=\"text\" id=\"qf-unote\"><\/div>\r\n                <div class=\"note\">This builds a UPI payment link, which is read by banking apps in India. Check that your own app supports it before printing a batch.<\/div>\r\n              <\/div>\r\n\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <div class=\"sect\">\r\n            <h4>Design<\/h4>\r\n            <div class=\"fld\"><label>Colour presets<\/label>\r\n              <div class=\"presets\" id=\"pth-presets\"><\/div>\r\n            <\/div>\r\n            <div class=\"grid2\">\r\n              <div class=\"fld\"><label for=\"qf-fg\">Foreground<\/label><input type=\"color\" id=\"qf-fg\" value=\"#0f172a\"><\/div>\r\n              <div class=\"fld\"><label for=\"qf-bg\">Background<\/label><input type=\"color\" id=\"qf-bg\" value=\"#ffffff\"><\/div>\r\n            <\/div>\r\n            <div class=\"grid3\">\r\n              <div class=\"fld\"><label for=\"qf-size\">Size: <span id=\"qf-sizev\">300<\/span>px<\/label><input type=\"range\" id=\"qf-size\" min=\"150\" max=\"800\" step=\"10\" value=\"300\"><\/div>\r\n              <div class=\"fld\"><label for=\"qf-dot\">Module style: <span id=\"qf-dotv\">100<\/span>%<\/label><input type=\"range\" id=\"qf-dot\" min=\"40\" max=\"100\" step=\"5\" value=\"100\"><\/div>\r\n              <div class=\"fld\"><label for=\"qf-ec\">Error correction<\/label>\r\n                <select id=\"qf-ec\"><option value=\"L\">L - 7%<\/option><option value=\"M\">M - 15%<\/option><option value=\"Q\">Q - 25%<\/option><option value=\"H\" selected>H - 30%<\/option><\/select><\/div>\r\n            <\/div>\r\n            <div class=\"grid2\">\r\n              <div class=\"fld\"><label for=\"qf-qz\">Quiet zone: <span id=\"qf-qzv\">15<\/span>px<\/label><input type=\"range\" id=\"qf-qz\" min=\"0\" max=\"50\" step=\"1\" value=\"15\"><\/div>\r\n              <div class=\"fld\"><label for=\"qf-logo\">Centre logo (optional)<\/label><input type=\"file\" id=\"qf-logo\" accept=\"image\/*\" aria-label=\"Upload a centre logo\"><\/div>\r\n            <\/div>\r\n            <div class=\"info\">A centre logo covers part of the pattern. Keep error correction at H when you use one, or the code may stop scanning.<\/div>\r\n          <\/div>\r\n\r\n          <div class=\"sect\">\r\n            <h4>Caption Frame<\/h4>\r\n            <div class=\"grid2\">\r\n              <div class=\"fld\"><label for=\"qf-title\">Heading above the code<\/label><input type=\"text\" id=\"qf-title\" placeholder=\"SCAN ME\"><\/div>\r\n              <div class=\"fld\"><label for=\"qf-sub\">Small line below<\/label><input type=\"text\" id=\"qf-sub\" placeholder=\"Menu and prices\"><\/div>\r\n            <\/div>\r\n          <\/div>\r\n\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <div class=\"card\">\r\n        <div class=\"hdr\"><h3 class=\"hdr-title\">Preview<\/h3><\/div>\r\n        <div class=\"card-pad\">\r\n          <div class=\"stage\"><div id=\"pth-qr-out\"><span class=\"ph\">Your QR code appears here<\/span><\/div><\/div>\r\n          <div class=\"row\" style=\"margin-top:14px\">\r\n            <button type=\"button\" class=\"btn btn-primary\" id=\"pth-qr-gen\">Generate<\/button>\r\n            <button type=\"button\" class=\"btn btn-grn\" id=\"pth-qr-png\">PNG<\/button>\r\n            <button type=\"button\" class=\"btn btn-grn\" id=\"pth-qr-svg\">SVG<\/button>\r\n            <button type=\"button\" class=\"btn\" id=\"pth-qr-jpg\">JPG<\/button>\r\n          <\/div>\r\n          <div class=\"info\">SVG stays sharp at any size, so use it for posters, signage and anything going to a printer. PNG suits screens and documents.<\/div>\r\n          <div class=\"note\">Need hundreds of codes from a spreadsheet on a printable sheet? That is a different job - the <a href=\"https:\/\/schoolict.net\/tools\/csv-to-label-maker\/\">CSV to Label Maker<\/a> builds label sheets with barcodes and QR codes from a CSV file.<\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- ============ BARCODE PANEL ============ -->\r\n  <div class=\"panel\" data-panel=\"bc\">\r\n    <div class=\"layout\" id=\"pth-bc-layout\">\r\n\r\n      <div class=\"card\">\r\n        <div class=\"hdr\"><h3 class=\"hdr-title\">Barcode Settings<\/h3><\/div>\r\n        <div class=\"card-pad\">\r\n\r\n          <div class=\"sect\">\r\n            <h4>Format<\/h4>\r\n            <div class=\"fld\">\r\n              <select id=\"bf-format\" aria-label=\"Barcode format\">\r\n                <option value=\"CODE128\">Code 128 - general purpose, any characters<\/option>\r\n                <option value=\"CODE39\">Code 39 - older industrial standard<\/option>\r\n                <option value=\"EAN13\">EAN-13 - retail products worldwide<\/option>\r\n                <option value=\"EAN8\">EAN-8 - small retail packaging<\/option>\r\n                <option value=\"UPC\">UPC-A - retail in North America<\/option>\r\n                <option value=\"ITF14\">ITF-14 - shipping cartons<\/option>\r\n                <option value=\"MSI\">MSI - inventory and warehousing<\/option>\r\n                <option value=\"pharmacode\">Pharmacode - pharmaceutical packaging<\/option>\r\n              <\/select>\r\n            <\/div>\r\n            <div class=\"info\" id=\"bf-hint\">Code 128 accepts letters, numbers and symbols, and is the safest choice when you are making your own internal labels.<\/div>\r\n            <div class=\"fld\"><label for=\"bf-value\">Value to encode<\/label><input type=\"text\" id=\"bf-value\" value=\"PTH-2026-0001\"><\/div>\r\n            <div class=\"err\" id=\"bf-err\"><\/div>\r\n          <\/div>\r\n\r\n          <div class=\"sect\">\r\n            <h4>Appearance<\/h4>\r\n            <div class=\"grid3\">\r\n              <div class=\"fld\"><label for=\"bf-width\">Bar width: <span id=\"bf-widthv\">2<\/span><\/label><input type=\"range\" id=\"bf-width\" min=\"1\" max=\"5\" step=\"0.5\" value=\"2\"><\/div>\r\n              <div class=\"fld\"><label for=\"bf-height\">Height: <span id=\"bf-heightv\">100<\/span>px<\/label><input type=\"range\" id=\"bf-height\" min=\"30\" max=\"200\" step=\"5\" value=\"100\"><\/div>\r\n              <div class=\"fld\"><label for=\"bf-margin\">Margin: <span id=\"bf-marginv\">10<\/span>px<\/label><input type=\"range\" id=\"bf-margin\" min=\"0\" max=\"40\" step=\"1\" value=\"10\"><\/div>\r\n            <\/div>\r\n            <div class=\"grid2\">\r\n              <div class=\"fld\"><label for=\"bf-line\">Bar colour<\/label><input type=\"color\" id=\"bf-line\" value=\"#000000\"><\/div>\r\n              <div class=\"fld\"><label for=\"bf-bg\">Background<\/label><input type=\"color\" id=\"bf-bg\" value=\"#ffffff\"><\/div>\r\n            <\/div>\r\n            <div class=\"grid2\">\r\n              <div class=\"fld\"><label class=\"chk\"><input type=\"checkbox\" id=\"bf-showtext\" checked> Print the number under the bars<\/label><\/div>\r\n              <div class=\"fld\"><label for=\"bf-font\">Text size: <span id=\"bf-fontv\">20<\/span>px<\/label><input type=\"range\" id=\"bf-font\" min=\"10\" max=\"36\" step=\"1\" value=\"20\"><\/div>\r\n            <\/div>\r\n          <\/div>\r\n\r\n          <div class=\"sect\">\r\n            <h4>Check Digits<\/h4>\r\n            <div class=\"info\">EAN-13 needs 12 digits, EAN-8 needs 7 and UPC-A needs 11. The final check digit is worked out and added for you. Enter the full length with the check digit if you already have one and it will be verified instead.<\/div>\r\n          <\/div>\r\n\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <div class=\"card\">\r\n        <div class=\"hdr\"><h3 class=\"hdr-title\">Preview<\/h3><\/div>\r\n        <div class=\"card-pad\">\r\n          <div class=\"stage\"><div id=\"pth-bc-out\"><span class=\"ph\">Your barcode appears here<\/span><\/div><\/div>\r\n          <div class=\"row\" style=\"margin-top:14px\">\r\n            <button type=\"button\" class=\"btn btn-primary\" id=\"pth-bc-gen\">Generate<\/button>\r\n            <button type=\"button\" class=\"btn btn-grn\" id=\"pth-bc-png\">PNG<\/button>\r\n            <button type=\"button\" class=\"btn btn-grn\" id=\"pth-bc-svg\">SVG<\/button>\r\n          <\/div>\r\n          <div class=\"note\">Printing retail barcodes at a small size needs a good printer and enough white space either side. Test one label with the scanner tab before running a full batch.<\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- ============ SCANNER PANEL ============ -->\r\n  <div class=\"panel\" data-panel=\"scan\">\r\n    <div class=\"layout\">\r\n\r\n      <div class=\"card\">\r\n        <div class=\"hdr\"><h3 class=\"hdr-title\">Read a Code<\/h3><\/div>\r\n        <div class=\"card-pad\">\r\n          <div class=\"info\">The reader handles QR codes and the common barcode formats. Camera access is asked for only when you press Start Camera, and the video never leaves your device.<\/div>\r\n          <div class=\"row\">\r\n            <button type=\"button\" class=\"btn btn-primary\" id=\"pth-scan-start\">Start Camera<\/button>\r\n            <button type=\"button\" class=\"btn btn-red\" id=\"pth-scan-stop\" disabled>Stop Camera<\/button>\r\n            <button type=\"button\" class=\"btn\" id=\"pth-scan-file\">Read From Image<\/button>\r\n            <input type=\"file\" id=\"pth-scan-input\" accept=\"image\/*\" style=\"display:none\" aria-label=\"Choose an image containing a code\">\r\n          <\/div>\r\n          <div class=\"scanbox\">\r\n            <video id=\"pth-video\" width=\"460\" height=\"345\" playsinline muted><\/video>\r\n          <\/div>\r\n          <div id=\"pth-scan-result\"><\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <div class=\"card\">\r\n        <div class=\"hdr\">\r\n          <h3 class=\"hdr-title\">Scan History<\/h3>\r\n          <button type=\"button\" class=\"btn btn-sm\" id=\"pth-hist-clear\">Clear<\/button>\r\n        <\/div>\r\n        <div class=\"card-pad\">\r\n          <div class=\"hist\" id=\"pth-hist\"><div class=\"empty\">Nothing scanned yet.<\/div><\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div id=\"pth-qr-toast\" role=\"status\" aria-live=\"polite\"><\/div>\r\n<\/div>\r\n\r\n<script data-no-optimize=\"1\" data-no-minify=\"1\" data-cfasync=\"false\">\r\nwindow.pthQrBarcodeApp = (function () {\r\n  'use strict';\r\n\r\n  \/* Angle-bracket and closing-tag helpers. WordPress + LiteSpeed mangle raw\r\n     closing-tag substrings inside a script (per PTH build rule: ALL closing tags,\r\n     not just structural ones), which kills the whole block and every button. We\r\n     build every angle bracket and closing tag from concatenated pieces and keep\r\n     this file pure ASCII. *\/\r\n  var LT = String.fromCharCode(60); \/* < *\/\r\n  var GT = String.fromCharCode(62); \/* > *\/\r\n  var CT = LT + '\/';                \/* closing-tag opener \"<\/\" *\/\r\n\r\n  var W = null, booted = false;\r\n  var S = {\r\n    type: 'url', logo: null, map: null, marker: null, mapReady: false,\r\n    qrObj: null, hist: [], zxing: null, reader: null, camOn: false, zxLoading: false\r\n  };\r\n\r\n  var PRESETS = [\r\n    ['#0f172a', '#ffffff'], ['#1d4ed8', '#ffffff'], ['#047857', '#ffffff'],\r\n    ['#b91c1c', '#ffffff'], ['#6d28d9', '#ffffff'], ['#b45309', '#ffffff'],\r\n    ['#ffffff', '#0f172a'], ['#0f172a', '#fef3c7']\r\n  ];\r\n\r\n  var HINTS = {\r\n    CODE128: 'Code 128 accepts letters, numbers and symbols, and is the safest choice when you are making your own internal labels.',\r\n    CODE39: 'Code 39 handles capital letters and digits. It produces wider bars than Code 128 for the same content.',\r\n    EAN13: 'EAN-13 is the barcode on retail products worldwide. Enter 12 digits and the check digit is added.',\r\n    EAN8: 'EAN-8 is the shorter retail code used where packaging is too small for EAN-13. Enter 7 digits.',\r\n    UPC: 'UPC-A is the retail standard in North America. Enter 11 digits and the check digit is added.',\r\n    ITF14: 'ITF-14 marks shipping cartons rather than individual products. Enter 13 digits.',\r\n    MSI: 'MSI is used for inventory control and warehouse shelving. Digits only.',\r\n    pharmacode: 'Pharmacode encodes a number between 3 and 131070 and is read on pharmaceutical packaging.'\r\n  };\r\n\r\n  function $(id) { return document.getElementById(id); }\r\n  function qa(sel) { return W ? W.querySelectorAll(sel) : []; }\r\n  function val(id) { var e = $(id); return e ? e.value : ''; }\r\n\r\n  var tTimer = null;\r\n  function toast(msg, kind) {\r\n    var t = $('pth-qr-toast');\r\n    if (!t) { return; }\r\n    t.className = 'show' + (kind ? ' ' + kind : '');\r\n    t.textContent = msg;\r\n    if (tTimer) { clearTimeout(tTimer); }\r\n    tTimer = setTimeout(function () { t.className = ''; }, 3200);\r\n  }\r\n\r\n  function esc(s) {\r\n    return String(s).replace(\/&\/g, '&amp;')\r\n      .replace(new RegExp(LT, 'g'), '&lt;')\r\n      .replace(new RegExp(GT, 'g'), '&gt;')\r\n      .replace(\/\"\/g, '&quot;');\r\n  }\r\n\r\n  function pad2(n) { return (n < 10 ? '0' : '') + n; }\r\n\r\n  \/* ---------- Build the encoded string ---------- *\/\r\n  function buildPayload() {\r\n    var t = S.type, s;\r\n    if (t === 'url') { return val('qf-url'); }\r\n\r\n    if (t === 'wifi') {\r\n      var ssid = val('qf-ssid');\r\n      if (!ssid) { return ''; }\r\n      var enc = val('qf-wenc');\r\n      s = 'WIFI:T:' + enc + ';S:' + ssid + ';';\r\n      if (enc !== 'nopass') { s += 'P:' + val('qf-wpass') + ';'; }\r\n      if ($('qf-whidden').checked) { s += 'H:true;'; }\r\n      return s + ';';\r\n    }\r\n\r\n    if (t === 'vcard') {\r\n      var fn = val('qf-vfn'), ln = val('qf-vln');\r\n      if (!fn && !ln) { return ''; }\r\n      s = 'BEGIN:VCARD\\nVERSION:3.0\\n';\r\n      s += 'N:' + ln + ';' + fn + '\\n';\r\n      s += 'FN:' + (fn + ' ' + ln).replace(\/\\s+\/g, ' ') + '\\n';\r\n      if (val('qf-vorg')) { s += 'ORG:' + val('qf-vorg') + '\\n'; }\r\n      if (val('qf-vtitle')) { s += 'TITLE:' + val('qf-vtitle') + '\\n'; }\r\n      if (val('qf-vtel')) { s += 'TEL;TYPE=CELL:' + val('qf-vtel') + '\\n'; }\r\n      if (val('qf-vmail')) { s += 'EMAIL:' + val('qf-vmail') + '\\n'; }\r\n      if (val('qf-vurl')) { s += 'URL:' + val('qf-vurl') + '\\n'; }\r\n      return s + 'END:VCARD';\r\n    }\r\n\r\n    if (t === 'email') {\r\n      var to = val('qf-eto');\r\n      if (!to) { return ''; }\r\n      s = 'mailto:' + to;\r\n      var qp = [];\r\n      if (val('qf-esub')) { qp.push('subject=' + encodeURIComponent(val('qf-esub'))); }\r\n      if (val('qf-ebody')) { qp.push('body=' + encodeURIComponent(val('qf-ebody'))); }\r\n      if (qp.length) { s += '?' + qp.join('&'); }\r\n      return s;\r\n    }\r\n\r\n    if (t === 'sms') {\r\n      if (!val('qf-snum')) { return ''; }\r\n      return 'SMSTO:' + val('qf-snum') + ':' + val('qf-smsg');\r\n    }\r\n\r\n    if (t === 'tel') {\r\n      if (!val('qf-tnum')) { return ''; }\r\n      return 'tel:' + val('qf-tnum');\r\n    }\r\n\r\n    if (t === 'wa') {\r\n      var wn = val('qf-wanum').replace(\/[^0-9]\/g, '');\r\n      if (!wn) { return ''; }\r\n      s = 'https:\/\/wa.me\/' + wn;\r\n      if (val('qf-wamsg')) { s += '?text=' + encodeURIComponent(val('qf-wamsg')); }\r\n      return s;\r\n    }\r\n\r\n    if (t === 'geo') {\r\n      var la = val('qf-lat'), lo = val('qf-lng');\r\n      if (!la || !lo) { return ''; }\r\n      return 'geo:' + la + ',' + lo;\r\n    }\r\n\r\n    if (t === 'event') {\r\n      var ti = val('qf-etitle');\r\n      if (!ti) { return ''; }\r\n      s = 'BEGIN:VEVENT\\nSUMMARY:' + ti + '\\n';\r\n      if (val('qf-eloc')) { s += 'LOCATION:' + val('qf-eloc') + '\\n'; }\r\n      var d1 = icsStamp(val('qf-edate'), val('qf-etime'));\r\n      var d2 = icsStamp(val('qf-edate2'), val('qf-etime2'));\r\n      if (d1) { s += 'DTSTART:' + d1 + '\\n'; }\r\n      if (d2) { s += 'DTEND:' + d2 + '\\n'; }\r\n      return s + 'END:VEVENT';\r\n    }\r\n\r\n    if (t === 'crypto') {\r\n      var ad = val('qf-caddr');\r\n      if (!ad) { return ''; }\r\n      s = val('qf-ccoin') + ':' + ad;\r\n      if (val('qf-camt')) { s += '?amount=' + val('qf-camt'); }\r\n      return s;\r\n    }\r\n\r\n    if (t === 'upi') {\r\n      var pa = val('qf-uid');\r\n      if (!pa) { return ''; }\r\n      s = 'upi:\/\/pay?pa=' + encodeURIComponent(pa);\r\n      if (val('qf-uname')) { s += '&pn=' + encodeURIComponent(val('qf-uname')); }\r\n      if (val('qf-uamt')) { s += '&am=' + encodeURIComponent(val('qf-uamt')); }\r\n      if (val('qf-unote')) { s += '&tn=' + encodeURIComponent(val('qf-unote')); }\r\n      return s + '&cu=INR';\r\n    }\r\n    return '';\r\n  }\r\n\r\n  function icsStamp(d, t) {\r\n    if (!d) { return ''; }\r\n    var p = d.split('-');\r\n    if (p.length !== 3) { return ''; }\r\n    var hh = '09', mm = '00';\r\n    if (t) { var tp = t.split(':'); hh = tp[0] || '09'; mm = tp[1] || '00'; }\r\n    return p[0] + p[1] + p[2] + 'T' + hh + mm + '00';\r\n  }\r\n\r\n  \/* ---------- QR rendering ---------- *\/\r\n  function qrOptions(text, drawer) {\r\n    var size = parseInt(val('qf-size'), 10) || 300;\r\n    var lvl = val('qf-ec');\r\n    var map = { L: 1, M: 0, Q: 3, H: 2 };\r\n    var opt = {\r\n      text: text, width: size, height: size,\r\n      colorDark: val('qf-fg'), colorLight: val('qf-bg'),\r\n      correctLevel: map[lvl] === undefined ? 2 : map[lvl],\r\n      quietZone: parseInt(val('qf-qz'), 10) || 0,\r\n      quietZoneColor: val('qf-bg'),\r\n      dotScale: (parseInt(val('qf-dot'), 10) || 100) \/ 100,\r\n      drawer: drawer || 'canvas'\r\n    };\r\n    var ti = val('qf-title'), sb = val('qf-sub');\r\n    if (ti) {\r\n      opt.title = ti; opt.titleColor = val('qf-fg'); opt.titleHeight = 48;\r\n      opt.titleFont = 'bold 20px Inter, system-ui, sans-serif';\r\n      opt.titleBackgroundColor = val('qf-bg'); opt.titleTop = 22;\r\n    }\r\n    if (sb) {\r\n      opt.subTitle = sb; opt.subTitleColor = val('qf-fg');\r\n      opt.subTitleFont = '14px Inter, system-ui, sans-serif';\r\n      if (!ti) { opt.titleHeight = 34; }\r\n      opt.subTitleTop = ti ? 44 : 22;\r\n    }\r\n    if (S.logo) {\r\n      opt.logo = S.logo;\r\n      opt.logoWidth = Math.floor(size * 0.2);\r\n      opt.logoHeight = Math.floor(size * 0.2);\r\n      opt.logoBackgroundColor = val('qf-bg');\r\n    }\r\n    return opt;\r\n  }\r\n\r\n  function genQR() {\r\n    var text = buildPayload();\r\n    if (!text) { toast('Fill in the details for this code type first.', 'err'); return; }\r\n    if (text.length > 2000) { toast('That is a lot of data - the code may be hard to scan.', 'err'); }\r\n    var box = $('pth-qr-out');\r\n    box.innerHTML = '';\r\n    try {\r\n      S.qrObj = new window.QRCode(box, qrOptions(text, 'canvas'));\r\n      toast('QR code generated.', 'ok');\r\n    } catch (e) {\r\n      box.innerHTML = LT + 'span class=\"ph\"' + GT + 'Could not build that code.' + CT + 'span' + GT;\r\n      toast('Could not build the code. Try shorter content.', 'err');\r\n    }\r\n  }\r\n\r\n  function qrCanvas() {\r\n    var box = $('pth-qr-out');\r\n    return box ? box.querySelector('canvas') : null;\r\n  }\r\n\r\n  function dlURL(url, name) {\r\n    var a = document.createElement('a');\r\n    a.href = url; a.download = name;\r\n    document.body.appendChild(a); a.click(); document.body.removeChild(a);\r\n  }\r\n\r\n  function dlBlob(blob, name) {\r\n    var u = URL.createObjectURL(blob);\r\n    dlURL(u, name);\r\n    setTimeout(function () { URL.revokeObjectURL(u); }, 1200);\r\n  }\r\n\r\n  function saveQR(kind) {\r\n    var cv = qrCanvas();\r\n    if (kind === 'svg') {\r\n      var text = buildPayload();\r\n      if (!text) { toast('Generate a code first.', 'err'); return; }\r\n      var tmp = document.createElement('div');\r\n      tmp.style.cssText = 'position:absolute;left:-9999px;top:0;';\r\n      document.body.appendChild(tmp);\r\n      try {\r\n        var q = new window.QRCode(tmp, qrOptions(text, 'svg'));\r\n        setTimeout(function () {\r\n          var svg = tmp.querySelector('svg');\r\n          if (!svg) { toast('SVG export is not available for this code.', 'err'); document.body.removeChild(tmp); return; }\r\n          svg.setAttribute('xmlns', 'http:\/\/www.w3.org\/2000\/svg');\r\n          var src = new XMLSerializer().serializeToString(svg);\r\n          dlBlob(new Blob([src], { type: 'image\/svg+xml' }), 'qr-code.svg');\r\n          document.body.removeChild(tmp);\r\n          toast('SVG downloaded.', 'ok');\r\n        }, 260);\r\n      } catch (e) {\r\n        document.body.removeChild(tmp);\r\n        toast('SVG export failed.', 'err');\r\n      }\r\n      return;\r\n    }\r\n    if (!cv) { toast('Generate a code first.', 'err'); return; }\r\n    if (kind === 'jpg') {\r\n      var flat = document.createElement('canvas');\r\n      flat.width = cv.width; flat.height = cv.height;\r\n      var fx = flat.getContext('2d');\r\n      fx.fillStyle = val('qf-bg');\r\n      fx.fillRect(0, 0, flat.width, flat.height);\r\n      fx.drawImage(cv, 0, 0);\r\n      dlURL(flat.toDataURL('image\/jpeg', 0.92), 'qr-code.jpg');\r\n    } else {\r\n      dlURL(cv.toDataURL('image\/png'), 'qr-code.png');\r\n    }\r\n    toast(kind.toUpperCase() + ' downloaded.', 'ok');\r\n  }\r\n\r\n  \/* ---------- Barcode ---------- *\/\r\n  function bcOptions() {\r\n    return {\r\n      format: val('bf-format'),\r\n      width: parseFloat(val('bf-width')) || 2,\r\n      height: parseInt(val('bf-height'), 10) || 100,\r\n      displayValue: $('bf-showtext').checked,\r\n      fontSize: parseInt(val('bf-font'), 10) || 20,\r\n      margin: parseInt(val('bf-margin'), 10) || 10,\r\n      lineColor: val('bf-line'),\r\n      background: val('bf-bg'),\r\n      font: 'Inter, system-ui, sans-serif',\r\n      valid: function (ok) { if (!ok) { bcError('That value does not fit the ' + val('bf-format') + ' rules. Check the length and allowed characters.'); } }\r\n    };\r\n  }\r\n\r\n  function bcError(msg) {\r\n    var e = $('bf-err');\r\n    if (!msg) { e.className = 'err'; e.textContent = ''; return; }\r\n    e.className = 'err on';\r\n    e.textContent = msg;\r\n  }\r\n\r\n  function genBC() {\r\n    var v = val('bf-value');\r\n    if (!v) { bcError('Enter a value to encode.'); toast('Enter a value first.', 'err'); return; }\r\n    bcError('');\r\n    var box = $('pth-bc-out');\r\n    box.innerHTML = '';\r\n    var cv = document.createElement('canvas');\r\n    cv.width = 300; cv.height = 150;\r\n    box.appendChild(cv);\r\n    try {\r\n      window.JsBarcode(cv, v, bcOptions());\r\n      if (!cv.width || cv.width < 5) { throw new Error('empty'); }\r\n      toast('Barcode generated.', 'ok');\r\n    } catch (e) {\r\n      box.innerHTML = LT + 'span class=\"ph\"' + GT + 'Could not build that barcode.' + CT + 'span' + GT;\r\n      bcError('That value does not fit the ' + val('bf-format') + ' rules. Check the length and allowed characters.');\r\n    }\r\n  }\r\n\r\n  function saveBC(kind) {\r\n    var v = val('bf-value');\r\n    if (!v) { toast('Generate a barcode first.', 'err'); return; }\r\n    if (kind === 'svg') {\r\n      var svg = document.createElementNS('http:\/\/www.w3.org\/2000\/svg', 'svg');\r\n      try {\r\n        window.JsBarcode(svg, v, bcOptions());\r\n        svg.setAttribute('xmlns', 'http:\/\/www.w3.org\/2000\/svg');\r\n        var src = new XMLSerializer().serializeToString(svg);\r\n        dlBlob(new Blob([src], { type: 'image\/svg+xml' }), 'barcode.svg');\r\n        toast('SVG downloaded.', 'ok');\r\n      } catch (e) { toast('SVG export failed - check the value.', 'err'); }\r\n      return;\r\n    }\r\n    var cv = $('pth-bc-out').querySelector('canvas');\r\n    if (!cv) { toast('Generate a barcode first.', 'err'); return; }\r\n    dlURL(cv.toDataURL('image\/png'), 'barcode.png');\r\n    toast('PNG downloaded.', 'ok');\r\n  }\r\n\r\n  \/* ---------- Scanner (library loaded on demand) ---------- *\/\r\n  function loadZXing(cb) {\r\n    if (window.ZXing) { cb(true); return; }\r\n    if (S.zxLoading) { setTimeout(function () { loadZXing(cb); }, 300); return; }\r\n    S.zxLoading = true;\r\n    var sc = document.createElement('script');\r\n    sc.src = 'https:\/\/cdn.jsdelivr.net\/npm\/@zxing\/library@0.20.0\/umd\/index.min.js';\r\n    sc.setAttribute('data-no-optimize', '1');\r\n    sc.setAttribute('data-no-minify', '1');\r\n    sc.setAttribute('data-cfasync', 'false');\r\n    sc.onload = function () { S.zxLoading = false; cb(!!window.ZXing); };\r\n    sc.onerror = function () { S.zxLoading = false; cb(false); };\r\n    document.head.appendChild(sc);\r\n    toast('Loading the reader...');\r\n  }\r\n\r\n  function showResult(text, fmt) {\r\n    var box = $('pth-scan-result');\r\n    box.innerHTML = LT + 'div class=\"result\"' + GT + LT + 'div class=\"rt\"' + GT + esc(fmt || 'CODE') + CT + 'div' + GT\r\n      + LT + 'div class=\"rv\"' + GT + esc(text) + CT + 'div' + GT + CT + 'div' + GT;\r\n    var actions = document.createElement('div');\r\n    actions.className = 'row';\r\n    actions.style.marginTop = '10px';\r\n\r\n    var cp = document.createElement('button');\r\n    cp.type = 'button'; cp.className = 'btn btn-sm'; cp.textContent = 'Copy';\r\n    cp.addEventListener('click', function () {\r\n      if (navigator.clipboard && navigator.clipboard.writeText) {\r\n        navigator.clipboard.writeText(text).then(function () { toast('Copied.', 'ok'); })\r\n          ['catch'](function () { toast('Copy blocked by the browser.', 'err'); });\r\n      } else { toast('Copy is not available in this browser.', 'err'); }\r\n    });\r\n    actions.appendChild(cp);\r\n\r\n    if (\/^https?:\\\/\\\/\/i.test(text)) {\r\n      var op = document.createElement('a');\r\n      op.className = 'btn btn-sm'; op.textContent = 'Open Link';\r\n      op.href = text; op.target = '_blank'; op.rel = 'noopener nofollow';\r\n      actions.appendChild(op);\r\n    }\r\n    box.appendChild(actions);\r\n\r\n    S.hist.unshift({ t: text, f: fmt || 'CODE' });\r\n    if (S.hist.length > 25) { S.hist.pop(); }\r\n    renderHist();\r\n  }\r\n\r\n  function renderHist() {\r\n    var box = $('pth-hist');\r\n    if (!S.hist.length) { box.innerHTML = LT + 'div class=\"empty\"' + GT + 'Nothing scanned yet.' + CT + 'div' + GT; return; }\r\n    var html = '', i;\r\n    for (i = 0; i < S.hist.length; i++) {\r\n      html += LT + 'div class=\"hitem\"' + GT + LT + 'b' + GT + esc(S.hist[i].f) + CT + 'b' + GT\r\n        + LT + 'div' + GT + esc(S.hist[i].t) + CT + 'div' + GT + CT + 'div' + GT;\r\n    }\r\n    box.innerHTML = html;\r\n  }\r\n\r\n  function startCam() {\r\n    loadZXing(function (ok) {\r\n      if (!ok) { toast('The reader could not be loaded. Check your connection.', 'err'); return; }\r\n      try {\r\n        if (!S.reader) { S.reader = new window.ZXing.BrowserMultiFormatReader(); }\r\n        S.reader.decodeFromVideoDevice(null, $('pth-video'), function (result, err) {\r\n          if (result) {\r\n            var fmt = result.getBarcodeFormat ? String(result.getBarcodeFormat()) : 'CODE';\r\n            showResult(result.getText(), fmt);\r\n            toast('Code read.', 'ok');\r\n          }\r\n        });\r\n        S.camOn = true;\r\n        $('pth-scan-start').disabled = true;\r\n        $('pth-scan-stop').disabled = false;\r\n        toast('Camera running - hold a code in view.', 'ok');\r\n      } catch (e) {\r\n        toast('Camera could not be started. Check the browser permission.', 'err');\r\n      }\r\n    });\r\n  }\r\n\r\n  function stopCam() {\r\n    if (S.reader) { try { S.reader.reset(); } catch (e) { } }\r\n    S.camOn = false;\r\n    $('pth-scan-start').disabled = false;\r\n    $('pth-scan-stop').disabled = true;\r\n    toast('Camera stopped.');\r\n  }\r\n\r\n  function readImage(file) {\r\n    if (!file) { return; }\r\n    loadZXing(function (ok) {\r\n      if (!ok) { toast('The reader could not be loaded.', 'err'); return; }\r\n      var fr = new FileReader();\r\n      fr.onload = function (ev) {\r\n        try {\r\n          if (!S.reader) { S.reader = new window.ZXing.BrowserMultiFormatReader(); }\r\n          S.reader.decodeFromImageUrl(ev.target.result).then(function (result) {\r\n            var fmt = result.getBarcodeFormat ? String(result.getBarcodeFormat()) : 'CODE';\r\n            showResult(result.getText(), fmt);\r\n            toast('Code read from the image.', 'ok');\r\n          })['catch'](function () {\r\n            toast('No code found in that image. Try a sharper, closer picture.', 'err');\r\n          });\r\n        } catch (e) { toast('Could not read that image.', 'err'); }\r\n      };\r\n      fr.readAsDataURL(file);\r\n    });\r\n  }\r\n\r\n  \/* ---------- Map ---------- *\/\r\n  function initMap() {\r\n    if (S.mapReady || !window.L) { return; }\r\n    var el = $('pth-map');\r\n    if (!el || !el.offsetWidth) { return; }\r\n    S.map = window.L.map(el).setView([6.9271, 79.8612], 12);\r\n    window.L.tileLayer('https:\/\/{s}.tile.openstreetmap.org\/{z}\/{x}\/{y}.png', {\r\n      maxZoom: 19, attribution: 'Map data from OpenStreetMap'\r\n    }).addTo(S.map);\r\n    S.marker = window.L.marker([6.9271, 79.8612]).addTo(S.map);\r\n    S.map.on('click', function (e) {\r\n      S.marker.setLatLng(e.latlng);\r\n      $('qf-lat').value = e.latlng.lat.toFixed(6);\r\n      $('qf-lng').value = e.latlng.lng.toFixed(6);\r\n    });\r\n    S.mapReady = true;\r\n    setTimeout(function () { S.map.invalidateSize(); }, 220);\r\n  }\r\n\r\n  \/* ---------- Type switching ---------- *\/\r\n  function setType(t) {\r\n    S.type = t;\r\n    var btns = qa('.type'), i;\r\n    for (i = 0; i < btns.length; i++) {\r\n      if (btns[i].getAttribute('data-t') === t) { btns[i].classList.add('on'); }\r\n      else { btns[i].classList.remove('on'); }\r\n    }\r\n    var forms = qa('.qf');\r\n    for (i = 0; i < forms.length; i++) {\r\n      forms[i].style.display = forms[i].getAttribute('data-f') === t ? 'block' : 'none';\r\n    }\r\n    if (t === 'geo') { setTimeout(initMap, 90); }\r\n  }\r\n\r\n  \/* ---------- Sample ---------- *\/\r\n  function loadSample() {\r\n    setType('vcard');\r\n    $('qf-vfn').value = 'Nimal';\r\n    $('qf-vln').value = 'Perera';\r\n    $('qf-vtel').value = '+94771234567';\r\n    $('qf-vmail').value = 'nimal@example.com';\r\n    $('qf-vorg').value = 'Prime Tool Hub';\r\n    $('qf-vtitle').value = 'ICT Educator';\r\n    $('qf-vurl').value = 'https:\/\/schoolict.net\/tools';\r\n    $('qf-title').value = 'SCAN ME';\r\n    $('qf-sub').value = 'Save my contact';\r\n    genQR();\r\n    $('bf-format').value = 'EAN13';\r\n    $('bf-value').value = '590123412345';\r\n    $('bf-hint').textContent = HINTS.EAN13;\r\n    genBC();\r\n    toast('Sample contact card and EAN-13 loaded.', 'ok');\r\n  }\r\n\r\n  \/* ---------- Wiring ---------- *\/\r\n  function bind() {\r\n    var i;\r\n\r\n    var tabs = qa('.tab');\r\n    for (i = 0; i < tabs.length; i++) {\r\n      tabs[i].addEventListener('click', function () {\r\n        var name = this.getAttribute('data-tab'), k;\r\n        var all = qa('.tab'), pans = qa('.panel');\r\n        for (k = 0; k < all.length; k++) { all[k].classList.remove('on'); }\r\n        for (k = 0; k < pans.length; k++) { pans[k].classList.remove('on'); }\r\n        this.classList.add('on');\r\n        var p = W.querySelector('.panel[data-panel=\"' + name + '\"]');\r\n        if (p) { p.classList.add('on'); }\r\n        if (name === 'qr' && S.type === 'geo') { setTimeout(initMap, 90); }\r\n        if (name !== 'scan' && S.camOn) { stopCam(); }\r\n      });\r\n    }\r\n\r\n    var types = qa('.type');\r\n    for (i = 0; i < types.length; i++) {\r\n      types[i].addEventListener('click', function () { setType(this.getAttribute('data-t')); });\r\n    }\r\n\r\n    var pbox = $('pth-presets');\r\n    for (i = 0; i < PRESETS.length; i++) {\r\n      (function (p) {\r\n        var b = document.createElement('button');\r\n        b.type = 'button';\r\n        b.className = 'preset';\r\n        b.style.background = 'linear-gradient(135deg,' + p[0] + ' 50%,' + p[1] + ' 50%)';\r\n        b.setAttribute('aria-label', 'Colour preset');\r\n        b.addEventListener('click', function () {\r\n          $('qf-fg').value = p[0];\r\n          $('qf-bg').value = p[1];\r\n          genQR();\r\n        });\r\n        pbox.appendChild(b);\r\n      })(PRESETS[i]);\r\n    }\r\n\r\n    $('qf-size').addEventListener('input', function () { $('qf-sizev').textContent = this.value; });\r\n    $('qf-dot').addEventListener('input', function () { $('qf-dotv').textContent = this.value; });\r\n    $('qf-qz').addEventListener('input', function () { $('qf-qzv').textContent = this.value; });\r\n\r\n    $('qf-logo').addEventListener('change', function () {\r\n      var f = this.files[0];\r\n      if (!f) { return; }\r\n      if (f.size > 1048576) { toast('Logo too large - keep it under 1MB.', 'err'); this.value = ''; return; }\r\n      var fr = new FileReader();\r\n      fr.onload = function (ev) { S.logo = ev.target.result; genQR(); toast('Logo added.', 'ok'); };\r\n      fr.readAsDataURL(f);\r\n    });\r\n\r\n    $('pth-qr-gen').addEventListener('click', genQR);\r\n    $('pth-qr-png').addEventListener('click', function () { saveQR('png'); });\r\n    $('pth-qr-svg').addEventListener('click', function () { saveQR('svg'); });\r\n    $('pth-qr-jpg').addEventListener('click', function () { saveQR('jpg'); });\r\n\r\n    $('bf-format').addEventListener('change', function () {\r\n      $('bf-hint').textContent = HINTS[this.value] || '';\r\n      bcError('');\r\n    });\r\n    $('bf-width').addEventListener('input', function () { $('bf-widthv').textContent = this.value; });\r\n    $('bf-height').addEventListener('input', function () { $('bf-heightv').textContent = this.value; });\r\n    $('bf-margin').addEventListener('input', function () { $('bf-marginv').textContent = this.value; });\r\n    $('bf-font').addEventListener('input', function () { $('bf-fontv').textContent = this.value; });\r\n    $('pth-bc-gen').addEventListener('click', genBC);\r\n    $('pth-bc-png').addEventListener('click', function () { saveBC('png'); });\r\n    $('pth-bc-svg').addEventListener('click', function () { saveBC('svg'); });\r\n\r\n    $('pth-scan-start').addEventListener('click', startCam);\r\n    $('pth-scan-stop').addEventListener('click', stopCam);\r\n    $('pth-scan-file').addEventListener('click', function () { $('pth-scan-input').click(); });\r\n    $('pth-scan-input').addEventListener('change', function () { readImage(this.files[0]); this.value = ''; });\r\n    $('pth-hist-clear').addEventListener('click', function () {\r\n      S.hist = []; renderHist(); toast('History cleared.');\r\n    });\r\n\r\n    $('pth-qr-sample').addEventListener('click', loadSample);\r\n    $('pth-qr-fw').addEventListener('click', function () {\r\n      $('pth-qr-layout').classList.toggle('fw');\r\n      $('pth-bc-layout').classList.toggle('fw');\r\n      if (S.map) { setTimeout(function () { S.map.invalidateSize(); }, 240); }\r\n    });\r\n    $('pth-qr-clear').addEventListener('click', function () {\r\n      var ins = qa('input[type=\"text\"], input[type=\"tel\"], input[type=\"email\"], input[type=\"url\"], textarea, input[type=\"date\"], input[type=\"time\"]');\r\n      var k;\r\n      for (k = 0; k < ins.length; k++) { ins[k].value = ''; }\r\n      S.logo = null;\r\n      $('qf-logo').value = '';\r\n      $('pth-qr-out').innerHTML = LT + 'span class=\"ph\"' + GT + 'Your QR code appears here' + CT + 'span' + GT;\r\n      $('pth-bc-out').innerHTML = LT + 'span class=\"ph\"' + GT + 'Your barcode appears here' + CT + 'span' + GT;\r\n      $('pth-scan-result').innerHTML = '';\r\n      bcError('');\r\n      toast('Cleared.');\r\n    });\r\n  }\r\n\r\n  function boot() {\r\n    if (booted) { return; }\r\n    W = document.getElementById('pth-qrcode-wrapper');\r\n    if (!W) { return; }\r\n    if (!window.QRCode || !window.JsBarcode) { return; }\r\n    booted = true;\r\n    bind();\r\n    setType('url');\r\n    genQR();\r\n    genBC();\r\n  }\r\n\r\n  boot();\r\n  if (document.readyState === 'loading') {\r\n    document.addEventListener('DOMContentLoaded', boot);\r\n  }\r\n  window.addEventListener('load', function () { setTimeout(boot, 50); });\r\n  if (!booted && window.MutationObserver) {\r\n    var mo = new MutationObserver(function () { boot(); if (booted) { mo.disconnect(); } });\r\n    try { mo.observe(document.documentElement, { childList: true, subtree: true }); } catch (e) { }\r\n    setTimeout(function () { try { mo.disconnect(); } catch (e2) { } }, 10000);\r\n  }\r\n\r\n  return { boot: boot };\r\n})();\r\n<\/script>\n\n\n\n\n<style>\n.pth-c36 { max-width: 900px; margin: 38px auto 0; font-family: 'Inter', system-ui, sans-serif; color: #1e293b; line-height: 1.75; }\n.pth-c36 h2 { font-size: 25px; font-weight: 800; color: #0f172a; margin: 32px 0 12px; }\n.pth-c36 h3 { font-size: 18px; font-weight: 700; color: #1e293b; margin: 22px 0 8px; }\n.pth-c36 h4 { font-size: 15px; font-weight: 700; color: #334155; margin: 16px 0 6px; }\n.pth-c36 ul, .pth-c36 ol { margin: 0 0 15px; padding-left: 22px; }\n.pth-c36 li { margin-bottom: 7px; color: #1e293b; font-weight: 500; }\n.pth-c36 a { color: #1d4ed8; font-weight: 600; text-decoration: none; }\n.pth-c36 a:hover { text-decoration: underline; }\n.pth-c36 code { background: #f1f5f9; padding: 2px 6px; border-radius: 4px; font-family: 'Courier New', monospace; font-size: 14px; color: #be123c; }\n.pth-c36-feat { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 12px; margin: 18px 0; }\n.pth-c36-card { border: 1px solid #e2e8f0; border-radius: 10px; padding: 15px 17px; background: #f8fafc; }\n.pth-c36-card b { display: block; color: #0f172a; font-size: 15px; margin-bottom: 4px; }\n.pth-c36-card span { font-size: 14px; color: #475569; font-weight: 500; }\n.pth-c36-steps { counter-reset: pthq; list-style: none; padding-left: 0; }\n.pth-c36-steps li { counter-increment: pthq; position: relative; padding: 5px 0 5px 42px; }\n.pth-c36-steps li::before { content: counter(pthq); position: absolute; left: 0; top: 5px; width: 27px; height: 27px; background: #2563eb; color: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 13px; }\n.pth-c36-tbl { width: 100%; border-collapse: collapse; margin: 0 0 18px; font-size: 14px; }\n.pth-c36-tbl th, .pth-c36-tbl td { border: 1px solid #e2e8f0; padding: 9px 12px; text-align: left; color: #1e293b; }\n.pth-c36-tbl th { background: #f8fafc; font-weight: 700; color: #0f172a; }\n.pth-c36-warn { border-left: 4px solid #b45309; background: #fffbeb; border-radius: 0 8px 8px 0; padding: 13px 17px; margin: 0 0 18px; color: #78350f; font-weight: 500; }\n.pth-c36-links { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 11px; margin: 16px 0; }\n.pth-c36-links a { display: block; border: 1px solid #e2e8f0; border-radius: 10px; padding: 13px 15px; background: #f8fafc; font-weight: 700; }\n.pth-c36-links a:hover { border-color: #2563eb; background: #eff6ff; text-decoration: none; }\n.pth-c36-links a em { display: block; font-style: normal; font-weight: 500; font-size: 13px; color: #475569; margin-top: 3px; }\n.pth-c36-more { max-height: 100%; overflow: visible; }\n@media (max-width: 640px) {\n  .pth-c36-more { max-height: 420px; overflow: hidden; position: relative; }\n  .pth-c36-more.pth-open { max-height: 100%; }\n  .pth-c36-more:not(.pth-open)::after { content: \"\"; position: absolute; left: 0; right: 0; bottom: 0; height: 70px; background: linear-gradient(rgba(255,255,255,0), #ffffff); }\n  .pth-c36-btn { display: block; width: 100%; margin: 10px 0 0; padding: 11px; border: 1px solid #cbd5e1; border-radius: 9px; background: #f1f5f9; color: #0f172a; font-weight: 700; font-size: 14px; cursor: pointer; font-family: inherit; }\n}\n@media (min-width: 641px) { .pth-c36-btn { display: none; } }\n<\/style>\n \n<div class=\"pth-c36\">\n \n<!-- HERO IMAGE PLACEHOLDER - paste the tag below once the image is uploaded to Media Library\n<img decoding=\"async\" src=\"MEDIA_URL_HERE\" alt=\"QR code and retail barcode being generated side by side in a browser tool\" width=\"1200\" height=\"630\" loading=\"eager\" fetchpriority=\"high\" data-no-lazy=\"1\">\n-->\n \n<div class=\"pth-c36-feat\">\n  <div class=\"pth-c36-card\"><b>Eleven QR types<\/b><span>Website, WiFi, contact card, email, SMS, phone, WhatsApp, location, event, crypto and payment.<\/span><\/div>\n  <div class=\"pth-c36-card\"><b>Eight barcode formats<\/b><span>Code 128, Code 39, EAN-13, EAN-8, UPC-A, ITF-14, MSI and Pharmacode.<\/span><\/div>\n  <div class=\"pth-c36-card\"><b>Check digits done for you<\/b><span>Type 12 digits for EAN-13 and the final digit is worked out and appended.<\/span><\/div>\n  <div class=\"pth-c36-card\"><b>Read codes back<\/b><span>Point your camera at a code, or upload a photo of one, and see what it contains.<\/span><\/div>\n  <div class=\"pth-c36-card\"><b>Print-ready SVG<\/b><span>Vector output stays sharp on a poster or a shelf label at any size.<\/span><\/div>\n  <div class=\"pth-c36-card\"><b>Nothing uploaded<\/b><span>Codes are drawn in your browser. WiFi passwords and wallet addresses stay on your device.<\/span><\/div>\n<\/div>\n \n\n\n\n<p class=\"wp-block-paragraph\">Last Updated: August 2026<\/p>\n\n\n\n<h2 id=\"\ud83d\udfe2-one-page-for-making-codes-and-reading-them\" class=\"wp-block-heading\">\ud83d\udfe2 One Page For Making Codes And Reading Them<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Most code generators do one half of the job. You get a QR code, you print it, and then you find out at the shop counter whether it actually scans. This page keeps the generator and the reader together, so you can check your own output before committing it to a hundred printed labels.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It matters more than it sounds. A QR code with a logo dropped in the middle, or a barcode printed slightly too small, will often look perfect and scan badly.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Tab<\/th><th>What it handles<\/th><\/tr><\/thead><tbody><tr><td>QR Code<\/td><td>Eleven data types, colour and module styling, centre logo, caption frame, PNG, SVG and JPG export<\/td><\/tr><tr><td>Barcode<\/td><td>Eight 1D formats with automatic check digits, adjustable bar width and height, PNG and SVG<\/td><\/tr><tr><td>Scanner<\/td><td>Camera reading or image upload for QR codes and barcodes, with a running history<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 id=\"\ud83d\udfe1-making-a-wi-fi-code-start-to-finish\" class=\"wp-block-heading\">\ud83d\udfe1 Making A WiFi Code, Start To Finish<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This is the request that brings most people here, so here is the whole sequence.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>On the QR tab, choose the\u00a0<strong>WiFi<\/strong>\u00a0data type.<\/li>\n\n\n\n<li>Type the network name exactly as it appears on your router, including capitals.\u00a0<code>Home_Net<\/code>\u00a0and\u00a0<code>home_net<\/code>\u00a0are different networks to a phone.<\/li>\n\n\n\n<li>Enter the password and pick the security type. WPA covers WPA2 and WPA3 as well, and is what almost every home router uses.<\/li>\n\n\n\n<li>Add a caption if the code is going on a wall &#8211; a heading of\u00a0<code>GUEST WIFI<\/code>\u00a0and a small line underneath saves people asking.<\/li>\n\n\n\n<li>Press Generate, then download SVG if it is going to a printer or PNG if it is going on a screen.<\/li>\n\n\n\n<li>Open the Scanner tab and read your own code with a phone before you print twenty copies.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">A WiFi QR code contains your password in plain text. Anyone who photographs the code on your wall has your network. For a guest network that is usually fine, and for your main network it usually is not.<\/p>\n\n\n\n<h2 id=\"\ud83d\udfe2-choosing-a-barcode-format\" class=\"wp-block-heading\">\ud83d\udfe2 Choosing A Barcode Format<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The format list looks intimidating and the decision is actually simple: are you selling through someone else&#8217;s till, or labelling your own things?<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>You are doing this<\/th><th>Use<\/th><th>Input needed<\/th><\/tr><\/thead><tbody><tr><td>Labelling your own stock, files or equipment<\/td><td>Code 128<\/td><td>Letters, numbers and symbols, any length<\/td><\/tr><tr><td>Selling a product in shops outside North America<\/td><td>EAN-13<\/td><td>12 digits from your allocated prefix<\/td><\/tr><tr><td>Selling a product in the United States or Canada<\/td><td>UPC-A<\/td><td>11 digits<\/td><\/tr><tr><td>Small packaging with no room for EAN-13<\/td><td>EAN-8<\/td><td>7 digits<\/td><\/tr><tr><td>Marking outer shipping cartons<\/td><td>ITF-14<\/td><td>13 digits<\/td><\/tr><tr><td>Older systems that expect it<\/td><td>Code 39<\/td><td>Capitals and digits<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">One point that trips people up: a retail barcode number is not something you invent. EAN and UPC numbers come from a company prefix issued to your business. Making up a plausible-looking EAN-13 produces a valid barcode that belongs to somebody else&#8217;s product.<\/p>\n\n\n\n<h4 id=\"a-real-example\" class=\"wp-block-heading\">A real example<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Enter&nbsp;<code>590123412345<\/code>&nbsp;with EAN-13 selected. That is twelve digits. The tool calculates the thirteenth &#8211; the check digit &#8211; and the finished barcode reads&nbsp;<code>5901234123457<\/code>. Change any single digit of your input and the check digit changes too, which is exactly how a till knows a scan was misread.<\/p>\n\n\n\n<h2 id=\"\ud83d\udfe1-two-jobs-worth-knowing-about\" class=\"wp-block-heading\">\ud83d\udfe1 Two Jobs Worth Knowing About<\/h2>\n\n\n\n<h3 id=\"contact-cards-for-an-event\" class=\"wp-block-heading\">Contact cards for an event<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Pick the Contact type, fill in name, phone, email and organisation, add a&nbsp;<code>SCAN ME<\/code>&nbsp;caption, and print it on a badge. Anyone scanning gets a contact ready to save &#8211; no app, no typing.<\/p>\n\n\n\n<h3 id=\"asset-labels-for-a-school-or-office\" class=\"wp-block-heading\">Asset labels for a school or office<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Code 128 handles text, so&nbsp;<code>ICT-LAB-042<\/code>&nbsp;works directly as a barcode value. Generate SVG, and if you need the whole inventory printed on a sticker sheet, take the list to the&nbsp;<a href=\"https:\/\/schoolict.net\/tools\/csv-to-label-maker\/\">CSV to Label Maker<\/a>, which builds label sheets with codes from a spreadsheet.<\/p>\n\n\n\n<h2 id=\"\ud83d\udd34-common-mistakes-and-real-limits\" class=\"wp-block-heading\">\ud83d\udd34 Common Mistakes and Real Limits<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ud83d\udd35\u00a0<strong>Adding a logo without raising error correction.<\/strong>\u00a0The logo covers real data. Keep error correction at H when a logo is present, and always test the result in the Scanner tab.<\/li>\n\n\n\n<li>\ud83d\udfe0\u00a0<strong>Removing the white border.<\/strong>\u00a0The quiet zone around a code is part of the code. Set it to zero and many scanners will simply not see it.<\/li>\n\n\n\n<li>\ud83d\udfe3\u00a0<strong>Low contrast colours.<\/strong>\u00a0A pale code on a coloured background looks stylish and scans badly. Keep the pattern much darker than its background, and never invert unless you have tested it.<\/li>\n\n\n\n<li>\ud83d\udd35\u00a0<strong>Printing PNG at poster size.<\/strong>\u00a0PNG is a fixed grid of pixels and goes blurry when enlarged. Use SVG for anything a printer touches.<\/li>\n\n\n\n<li>\ud83d\udfe0\u00a0<strong>Inventing retail numbers.<\/strong>\u00a0EAN and UPC codes belong to registered company prefixes. Use Code 128 for internal labelling instead.<\/li>\n\n\n\n<li>\ud83d\udfe3\u00a0<strong>Expecting the code to change later.<\/strong>\u00a0Everything generated here is static &#8211; the content is baked into the pattern. Editing the destination after printing needs a redirect service, which is a paid product and one that can track scans.<\/li>\n\n\n\n<li>\ud83d\udd35\u00a0<strong>Camera scanning needs HTTPS and permission.<\/strong>\u00a0If the browser blocks the camera you will see a message rather than a broken screen, and reading from an uploaded photo still works.<\/li>\n<\/ul>\n\n\n\n\n<style>\n.pth-faq-wrap { max-width: 900px; margin: 30px auto 0; font-family: 'Inter', system-ui, sans-serif; }\n.pth-faq-title { font-size: 25px; font-weight: 800; color: #0f172a; margin: 0 0 16px; }\n.pth-faq-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 13px; }\n.pth-faq-card { border: 1px solid #e2e8f0; border-radius: 11px; padding: 16px 18px; background: #f8fafc; }\n.pth-faq-q { font-size: 15px; font-weight: 800; color: #0f172a; margin: 0 0 7px; line-height: 1.45; }\n.pth-faq-a { font-size: 14px; font-weight: 500; color: #334155; margin: 0; line-height: 1.65; }\n@media (max-width: 900px) { .pth-faq-grid { grid-template-columns: repeat(2, 1fr); } }\n@media (max-width: 600px) { .pth-faq-grid { grid-template-columns: 1fr; } }\n<\/style>\n \n<div class=\"pth-faq-wrap\">\n  <p class=\"pth-faq-title\">Frequently Asked Questions<\/p>\n  <div class=\"pth-faq-grid\">\n \n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Do these QR codes ever expire?<\/p>\n      <p class=\"pth-faq-a\">No. The content is encoded directly into the pattern, so the code works forever and needs no service behind it. The trade-off is that you cannot change where it points after printing.<\/p>\n    <\/div>\n \n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Is my data uploaded anywhere?<\/p>\n      <p class=\"pth-faq-a\">No. Codes are drawn by your browser, so WiFi passwords, contact details and wallet addresses never leave your device. There is no account and no watermark.<\/p>\n    <\/div>\n \n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Can I add my logo to a QR code?<\/p>\n      <p class=\"pth-faq-a\">Yes. Keep error correction at H so the pattern can survive the covered area, keep the logo to about a fifth of the width, and test the result in the Scanner tab before printing.<\/p>\n    <\/div>\n \n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Should I download PNG or SVG?<\/p>\n      <p class=\"pth-faq-a\">SVG for anything being printed, because it is vector and stays sharp at any size. PNG for screens, documents and email signatures where a fixed pixel size is fine.<\/p>\n    <\/div>\n \n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Which barcode format should I choose?<\/p>\n      <p class=\"pth-faq-a\">Code 128 for your own internal labelling, since it accepts letters and numbers. EAN-13 or UPC-A only if you are selling retail with a company prefix issued to your business.<\/p>\n    <\/div>\n \n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Do I need to work out the check digit?<\/p>\n      <p class=\"pth-faq-a\">No. Enter 12 digits for EAN-13, 7 for EAN-8 or 11 for UPC-A and the final digit is calculated and added. Enter the full length instead and it is verified for you.<\/p>\n    <\/div>\n \n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Why will my printed code not scan?<\/p>\n      <p class=\"pth-faq-a\">Usually the white border was removed, the contrast is too low, or a PNG was enlarged until it blurred. Check those three first, then read the printed copy with the Scanner tab.<\/p>\n    <\/div>\n \n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">Does the scanner work on barcodes as well as QR?<\/p>\n      <p class=\"pth-faq-a\">Yes, it reads QR codes and the common 1D formats. Camera access needs a secure connection and your permission, and reading from an uploaded photo works either way.<\/p>\n    <\/div>\n \n    <div class=\"pth-faq-card\">\n      <p class=\"pth-faq-q\">How do I make hundreds of codes at once?<\/p>\n      <p class=\"pth-faq-a\">Use the CSV to Label Maker instead. It reads a spreadsheet and lays the codes out on a printable label sheet, which is a different job from designing one code carefully.<\/p>\n    <\/div>\n \n  <\/div>\n<\/div>\n \n","protected":false},"excerpt":{"rendered":"<p>Design Standout QR Codes for Free \u2014 Add Custom Logos, Colors &amp; Brand Styling Instantly Create custom QR codes instantly with our 100% offline Advanced QR Code Generator. Embed logos, change colors, and generate WiFi or vCard QR codes securely. \u00a0 Eleven QR typesWebsite, WiFi, contact card, email, SMS, phone, WhatsApp, location, event, crypto and &#8230; <a title=\"Free Advanced QR Code Generator &#8211; Custom Logo &amp; Colors\" class=\"read-more\" href=\"https:\/\/schoolict.net\/tools\/advanced-qr-code-generator-offline\/\" aria-label=\"Read more about Free Advanced QR Code Generator &#8211; Custom Logo &amp; Colors\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":2226,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-2217","page","type-page","status-publish","has-post-thumbnail"],"_links":{"self":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages\/2217","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/comments?post=2217"}],"version-history":[{"count":2,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages\/2217\/revisions"}],"predecessor-version":[{"id":6984,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages\/2217\/revisions\/6984"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/media\/2226"}],"wp:attachment":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/media?parent=2217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}