PageSourceSearch

https://tattsafe.us/app.js?v=30b5307767f5

js tattsafe.us collected 2026-10-08 17:39:27 UTC 182,402 bytes, 781 lines download raw bytes

1// BEGIN QR GENERATOR
2var PortalQR=(()=>{var g=(n,t)=>()=>{try{return t||n((t={exports:{}}).exports,t),t.exports}catch(e){throw t=0,e}};var _t=g((Sn,Lt)=>{Lt.exports=function(){return typeof Promise=="function"&&Promise.prototype&&Promise.prototype.then}});var I=g(P=>{var st,Le=[0,26,44,70,100,134,172,196,242,292,346,404,466,532,581,655,733,815,901,991,1085,1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,2611,2761,2876,3034,3196,3362,3532,3706];P.getSymbolSize=function(t){if(!t)throw new Error('"version" cannot be null or undefined');if(t<1||t>40)throw new Error('"version" should be in range from 1 to 40');return t*4+17};P.getSymbolTotalCodewords=function(t){return Le[t]};P.getBCHDigit=function(n){let t=0;for(;n!==0;)t++,n>>>=1;return t};P.setToSJISFunction=function(t){if(typeof t!="function")throw new Error('"toSJISFunc" is not a valid function.');st=t};P.isKanjiModeEnabled=function(){return typeof st<"u"};P.toSJIS=function(t){return st(t)}});var j=g(m=>{m.L={bit:1};m.M={bit:0};m.Q={bit:3};m.H={bit:2};function _e(n){if(typeof n!="string")throw new Error("Param is not a string");switch(n.toLowerCase()){case"l":case"low":return m.L;case"m":case"medium":return m.M;case"q":case"quartile":return m.Q;case"h":case"high":return m.H;default:throw new Error("Unknown EC Level: "+n)}}m.isValid=function(t){return t&&typeof t.bit<"u"&&t.bit>=0&&t.bit<4};m.from=function(t,e){if(m.isValid(t))return t;try{return _e(t)}catch{return e}}});var qt=g((Rn,Ut)=>{function xt(){this.buffer=[],this.length=0}xt.prototype={get:function(n){let t=Math.floor(n/8);return(this.buffer[t]>>>7-n%8&1)===1},put:function(n,t){for(let e=0;e<t;e++)this.putBit((n>>>t-e-1&1)===1)},getLengthInBits:function(){return this.length},putBit:function(n){let t=Math.floor(this.length/8);this.buffer.length<=t&&this.buffer.push(0),n&&(this.buffer[t]|=128>>>this.length%8),this.length++}};Ut.exports=xt});var Ft=g((Ln,Dt)=>{function k(n){if(!n||n<1)throw new Error("BitMatrix size must be defined and greater than 0");this.size=n,this.data=new Uint8Array(n*n),this.reservedBit=new Uint8Array(n*n)}k.prototype.set=function(n,t,e,r){let o=n*this.size+t;this.data[o]=e,r&&(this.reservedBit[o]=!0)};k.prototype.get=function(n,t){return this.data[n*this.size+t]};k.prototype.xor=function(n,t,e){this.data[n*this.size+t]^=e};k.prototype.isReserved=function(n,t){return this.reservedBit[n*this.size+t]};Dt.exports=k});var kt=g(G=>{var xe=I().getSymbolSize;G.getRowColCoords=function(t){if(t===1)return[];let e=Math.floor(t/7)+2,r=xe(t),o=r===145?26:Math.ceil((r-13)/(2*e-2))*2,i=[r-7];for(let s=1;s<e-1;s++)i[s]=i[s-1]-o;return i.push(6),i.reverse()};G.getPositions=function(t){let e=[],r=G.getRowColCoords(t),o=r.length;for(let i=0;i<o;i++)for(let s=0;s<o;s++)i===0&&s===0||i===0&&s===o-1||i===o-1&&s===0||e.push([r[i],r[s]]);return e}});var Ht=g(Vt=>{var Ue=I().getSymbolSize,zt=7;Vt.getPositions=function(t){let e=Ue(t);return[[0,0],[e-zt,0],[0,e-zt]]}});var Kt=g(d=>{d.Patterns={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7};var b={N1:3,N2:3,N3:40,N4:10};d.isValid=function(t){return t!=null&&t!==""&&!isNaN(t)&&t>=0&&t<=7};d.from=function(t){return d.isValid(t)?parseInt(t,10):void 0};d.getPenaltyN1=function(t){let e=t.size,r=0,o=0,i=0,s=null,u=null;for(let c=0;c<e;c++){o=i=0,s=u=null;for(let l=0;l<e;l++){let a=t.get(c,l);a===s?o++:(o>=5&&(r+=b.N1+(o-5)),s=a,o=1),a=t.get(l,c),a===u?i++:(i>=5&&(r+=b.N1+(i-5)),u=a,i=1)}o>=5&&(r+=b.N1+(o-5)),i>=5&&(r+=b.N1+(i-5))}return r};d.getPenaltyN2=function(t){let e=t.size,r=0;for(let o=0;o<e-1;o++)for(let i=0;i<e-1;i++){let s=t.get(o,i)+t.get(o,i+1)+t.get(o+1,i)+t.get(o+1,i+1);(s===4||s===0)&&r++}return r*b.N2};d.getPenaltyN3=function(t){let e=t.size,r=0,o=0,i=0;for(let s=0;s<e;s++){o=i=0;for(let u=0;u<e;u++)o=o<<1&2047|t.get(s,u),u>=10&&(o===1488||o===93)&&r++,i=i<<1&2047|t.get(u,s),u>=10&&(i===1488||i===93)&&r++}return r*b.N3};d.getPenaltyN4=function(t){let e=0,r=t.data.length;for(let i=0;i<r;i++)e+=t.data[i];return Math.abs(Math.ceil(e*100/r/5)-10)*b.N4};function qe(n,t,e){switch(n){case d.Patterns.PATTERN000:return(t+e)%2===0;case d.Patterns.PATTERN001:return t%2===0;case d.Patterns.PATTERN010:return e%3===0;case d.Patterns.PATTERN011:return(t+e)%3===0;case d.Patterns.PATTERN100:return(Math.floor(t/2)+Math.floor(e/3))%2===0;case d.Patterns.PATTERN101:return t*e%2+t*e%3===0;case d.Patterns.PATTERN110:return(t*e%2+t*e%3)%2===0;case d.Patterns.PATTERN111:return(t*e%3+(t+e)%2)%2===0;default:throw new Error("bad maskPattern:"+n)}}d.applyMask=function(t,e){let r=e.size;
2for(let o=0;o<r;o++)for(let i=0;i<r;i++)e.isReserved(i,o)||e.xor(i,o,qe(t,i,o))};d.getBestMask=function(t,e){let r=Object.keys(d.Patterns).length,o=0,i=1/0;for(let s=0;s<r;s++){e(s),d.applyMask(s,t);let u=d.getPenaltyN1(t)+d.getPenaltyN2(t)+d.getPenaltyN3(t)+d.getPenaltyN4(t);d.applyMask(s,t),u<i&&(i=u,o=s)}return o}});var ct=g(ut=>{var N=j(),Q=[1,1,1,1,1,1,1,1,1,1,2,2,1,2,2,4,1,2,4,4,2,4,4,4,2,4,6,5,2,4,6,6,2,5,8,8,4,5,8,8,4,5,8,11,4,8,10,11,4,9,12,16,4,9,16,16,6,10,12,18,6,10,17,16,6,11,16,19,6,13,18,21,7,14,21,25,8,16,20,25,8,17,23,25,9,17,23,34,9,18,25,30,10,20,27,32,12,21,29,35,12,23,34,37,12,25,34,40,13,26,35,42,14,28,38,45,15,29,40,48,16,31,43,51,17,33,45,54,18,35,48,57,19,37,51,60,19,38,53,63,20,40,56,66,21,43,59,70,22,45,62,74,24,47,65,77,25,49,68,81],$=[7,10,13,17,10,16,22,28,15,26,36,44,20,36,52,64,26,48,72,88,36,64,96,112,40,72,108,130,48,88,132,156,60,110,160,192,72,130,192,224,80,150,224,264,96,176,260,308,104,198,288,352,120,216,320,384,132,240,360,432,144,280,408,480,168,308,448,532,180,338,504,588,196,364,546,650,224,416,600,700,224,442,644,750,252,476,690,816,270,504,750,900,300,560,810,960,312,588,870,1050,336,644,952,1110,360,700,1020,1200,390,728,1050,1260,420,784,1140,1350,450,812,1200,1440,480,868,1290,1530,510,924,1350,1620,540,980,1440,1710,570,1036,1530,1800,570,1064,1590,1890,600,1120,1680,1980,630,1204,1770,2100,660,1260,1860,2220,720,1316,1950,2310,750,1372,2040,2430];ut.getBlocksCount=function(t,e){switch(e){case N.L:return Q[(t-1)*4+0];case N.M:return Q[(t-1)*4+1];case N.Q:return Q[(t-1)*4+2];case N.H:return Q[(t-1)*4+3];default:return}};ut.getTotalCodewordsCount=function(t,e){switch(e){case N.L:return $[(t-1)*4+0];case N.M:return $[(t-1)*4+1];case N.Q:return $[(t-1)*4+2];case N.H:return $[(t-1)*4+3];default:return}}});var Jt=g(Z=>{var z=new Uint8Array(512),W=new Uint8Array(256);(function(){let t=1;for(let e=0;e<255;e++)z[e]=t,W[t]=e,t<<=1,t&256&&(t^=285);for(let e=255;e<512;e++)z[e]=z[e-255]})();Z.log=function(t){if(t<1)throw new Error("log("+t+")");return W[t]};Z.exp=function(t){return z[t]};Z.mul=function(t,e){return t===0||e===0?0:z[W[t]+W[e]]}});var Yt=g(V=>{var lt=Jt();V.mul=function(t,e){let r=new Uint8Array(t.length+e.length-1);for(let o=0;o<t.length;o++)for(let i=0;i<e.length;i++)r[o+i]^=lt.mul(t[o],e[i]);return r};V.mod=function(t,e){let r=new Uint8Array(t);for(;r.length-e.length>=0;){let o=r[0];for(let s=0;s<e.length;s++)r[s]^=lt.mul(e[s],o);let i=0;for(;i<r.length&&r[i]===0;)i++;r=r.slice(i)}return r};V.generateECPolynomial=function(t){let e=new Uint8Array([1]);for(let r=0;r<t;r++)e=V.mul(e,new Uint8Array([1,lt.exp(r)]));return e}});var Gt=g((kn,jt)=>{var Ot=Yt();function at(n){this.genPoly=void 0,this.degree=n,this.degree&&this.initialize(this.degree)}at.prototype.initialize=function(t){this.degree=t,this.genPoly=Ot.generateECPolynomial(this.degree)};at.prototype.encode=function(t){if(!this.genPoly)throw new Error("Encoder not initialized");let e=new Uint8Array(t.length+this.degree);e.set(t);let r=Ot.mod(e,this.genPoly),o=this.degree-r.length;if(o>0){let i=new Uint8Array(this.degree);return i.set(r,o),i}return r};jt.exports=at});var ft=g(Qt=>{Qt.isValid=function(t){return!isNaN(t)&&t>=1&&t<=40}});var gt=g(B=>{var $t="[0-9]+",De="[A-Z $%*+\\-./:]+",H="(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";H=H.replace(/u/g,"\\u");var Fe="(?:(?![A-Z0-9 $%*+\\-./:]|"+H+`)(?:.|[\r
3]))+`;B.KANJI=new RegExp(H,"g");B.BYTE_KANJI=new RegExp("[^A-Z0-9 $%*+\\-./:]+","g");B.BYTE=new RegExp(Fe,"g");B.NUMERIC=new RegExp($t,"g");B.ALPHANUMERIC=new RegExp(De,"g");var ke=new RegExp("^"+H+"$"),ze=new RegExp("^"+$t+"$"),Ve=new RegExp("^[A-Z0-9 $%*+\\-./:]+$");B.testKanji=function(t){return ke.test(t)};B.testNumeric=function(t){return ze.test(t)};B.testAlphanumeric=function(t){return Ve.test(t)}});var M=g(p=>{var He=ft(),dt=gt();p.NUMERIC={id:"Numeric",bit:1,ccBits:[10,12,14]};p.ALPHANUMERIC={id:"Alphanumeric",bit:2,ccBits:[9,11,13]};p.BYTE={id:"Byte",bit:4,ccBits:[8,16,16]};p.KANJI={id:"Kanji",bit:8,ccBits:[8,10,12]};p.MIXED={bit:-1};p.getCharCountIndicator=function(t,e){if(!t.ccBits)throw new Error("Invalid mode: "+t);if(!He.isValid(e))throw new Error("Invalid version: "+e);return e>=1&&e<10?t.ccBits[0]:e<27?t.ccBits[1]:t.ccBits[2]};p.getBestModeForData=function(t){return dt.testNumeric(t)?p.NUMERIC:dt.testAlphanumeric(t)?p.ALPHANUMERIC:dt.testKanji(t)?p.KANJI:p.BYTE};p.toString=function(t){if(t&&t.id)return t.id;throw new Error("Invalid mode")};p.isValid=function(t){return t&&t.bit&&t.ccBits};
3function Ke(n){if(typeof n!="string")throw new Error("Param is not a string");switch(n.toLowerCase()){case"numeric":return p.NUMERIC;case"alphanumeric":return p.ALPHANUMERIC;case"kanji":return p.KANJI;case"byte":return p.BYTE;default:throw new Error("Unknown mode: "+n)}}p.from=function(t,e){if(p.isValid(t))return t;try{return Ke(t)}catch{return e}}});var te=g(R=>{var X=I(),Je=ct(),Wt=j(),S=M(),ht=ft(),Xt=7973,Zt=X.getBCHDigit(Xt);function Ye(n,t,e){for(let r=1;r<=40;r++)if(t<=R.getCapacity(r,e,n))return r}function vt(n,t){return S.getCharCountIndicator(n,t)+4}function Oe(n,t){let e=0;return n.forEach(function(r){let o=vt(r.mode,t);e+=o+r.getBitsLength()}),e}function je(n,t){for(let e=1;e<=40;e++)if(Oe(n,e)<=R.getCapacity(e,t,S.MIXED))return e}R.from=function(t,e){return ht.isValid(t)?parseInt(t,10):e};R.getCapacity=function(t,e,r){if(!ht.isValid(t))throw new Error("Invalid QR Code version");typeof r>"u"&&(r=S.BYTE);let o=X.getSymbolTotalCodewords(t),i=Je.getTotalCodewordsCount(t,e),s=(o-i)*8;if(r===S.MIXED)return s;let u=s-vt(r,t);switch(r){case S.NUMERIC:return Math.floor(u/10*3);case S.ALPHANUMERIC:return Math.floor(u/11*2);case S.KANJI:return Math.floor(u/13);case S.BYTE:default:return Math.floor(u/8)}};R.getBestVersionForData=function(t,e){let r,o=Wt.from(e,Wt.M);if(Array.isArray(t)){if(t.length>1)return je(t,o);if(t.length===0)return 1;r=t[0]}else r=t;return Ye(r.mode,r.getLength(),o)};R.getEncodedBits=function(t){if(!ht.isValid(t)||t<7)throw new Error("Invalid QR Code version");let e=t<<12;for(;X.getBCHDigit(e)-Zt>=0;)e^=Xt<<X.getBCHDigit(e)-Zt;return t<<12|e}});var oe=g(re=>{var pt=I(),ne=1335,Ge=21522,ee=pt.getBCHDigit(ne);re.getEncodedBits=function(t,e){let r=t.bit<<3|e,o=r<<10;for(;pt.getBCHDigit(o)-ee>=0;)o^=ne<<pt.getBCHDigit(o)-ee;return(r<<10|o)^Ge}});var se=g((Yn,ie)=>{var Qe=M();function x(n){this.mode=Qe.NUMERIC,this.data=n.toString()}x.getBitsLength=function(t){return 10*Math.floor(t/3)+(t%3?t%3*3+1:0)};x.prototype.getLength=function(){return this.data.length};x.prototype.getBitsLength=function(){return x.getBitsLength(this.data.length)};x.prototype.write=function(t){let e,r,o;for(e=0;e+3<=this.data.length;e+=3)r=this.data.substr(e,3),o=parseInt(r,10),t.put(o,10);let i=this.data.length-e;i>0&&(r=this.data.substr(e),o=parseInt(r,10),t.put(o,i*3+1))};ie.exports=x});var ce=g((On,ue)=>{var $e=M(),wt=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":"];function U(n){this.mode=$e.ALPHANUMERIC,this.data=n}U.getBitsLength=function(t){return 11*Math.floor(t/2)+6*(t%2)};U.prototype.getLength=function(){return this.data.length};U.prototype.getBitsLength=function(){return U.getBitsLength(this.data.length)};U.prototype.write=function(t){let e;for(e=0;e+2<=this.data.length;e+=2){let r=wt.indexOf(this.data[e])*45;r+=wt.indexOf(this.data[e+1]),t.put(r,11)}this.data.length%2&&t.put(wt.indexOf(this.data[e]),6)};ue.exports=U});var ae=g((jn,le)=>{var We=M();function q(n){this.mode=We.BYTE,typeof n=="string"?this.data=new TextEncoder().encode(n):this.data=new Uint8Array(n)}q.getBitsLength=function(t){return t*8};q.prototype.getLength=function(){return this.data.length};q.prototype.getBitsLength=function(){return q.getBitsLength(this.data.length)};q.prototype.write=function(n){for(let t=0,e=this.data.length;t<e;t++)n.put(this.data[t],8)};le.exports=q});var ge=g((Gn,fe)=>{var Ze=M(),Xe=I();function D(n){this.mode=Ze.KANJI,this.data=n}D.getBitsLength=function(t){return t*13};D.prototype.getLength=function(){return this.data.length};D.prototype.getBitsLength=function(){return D.getBitsLength(this.data.length)};D.prototype.write=function(n){let t;for(t=0;t<this.data.length;t++){let e=Xe.toSJIS(this.data[t]);if(e>=33088&&e<=40956)e-=33088;else if(e>=57408&&e<=60351)e-=49472;else throw new Error("Invalid SJIS character: "+this.data[t]+`
4Make sure your charset is UTF-8`);e=(e>>>8&255)*192+(e&255),n.put(e,13)}};fe.exports=D});var de=g((Qn,mt)=>{"use strict";var K={single_source_shortest_paths:function(n,t,e){var r={},o={};o[t]=0;var i=K.PriorityQueue.make();i.push(t,0);for(var s,u,c,l,a,w,h,y,A;!i.empty();){s=i.pop(),u=s.value,l=s.cost,a=n[u]||{};for(c in a)a.hasOwnProperty(c)&&(w=a[c],h=l+w,y=o[c],A=typeof o[c]>"u",(A||y>h)&&(o[c]=h,i.push(c,h),r[c]=u))}if(typeof e<"u"&&typeof o[e]>"u"){var T=["Could not find a path from ",t," to ",e,"."].join("");throw new Error(T)}return r},extract_shortest_path_from_predecessor_list:function(n,t){for(var e=[],r=t,o;r;)e.push(r),o=n[r],r=n[r];return e.reverse(),e},find_path:function(n,t,e){var r=K.single_source_shortest_paths(n,t,e);return K.extract_shortest_path_from_predecessor_list(r,e)},PriorityQueue:{make:function(n){var t=K.PriorityQueue,e={},r;n=n||{};for(r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);return e.queue=[],e.sorter=n.sorter||t.default_sorter,e},default_sorter:function(n,t){return n.cost-t.cost},push:function(n,t){var e={value:n,cost:t};this.queue.push(e),this.queue.sort(this.sorter)},pop:function(){return this.queue.shift()},empty:function(){return this.queue.length===0}}};typeof mt<"u"&&(mt.exports=K)});var Be=g(F=>{var f=M(),we=se(),me=ce(),ye=ae(),Ee=ge(),J=gt(),v=I(),ve=de();function he(n){return unescape(encodeURIComponent(n)).length}function Y(n,t,e){let r=[],o;for(;(o=n.exec(e))!==null;)r.push({data:o[0],index:o.index,mode:t,length:o[0].length});return r}function Ce(n){let t=Y(J.NUMERIC,f.NUMERIC,n),e=Y(J.ALPHANUMERIC,f.ALPHANUMERIC,n),r,o;return v.isKanjiModeEnabled()?(r=Y(J.BYTE,f.BYTE,n),o=Y(J.KANJI,f.KANJI,n)):(r=Y(J.BYTE_KANJI,f.BYTE,n),o=[]),t.concat(e,r,o).sort(function(s,u){return s.index-u.index}).map(function(s){return{data:s.data,mode:s.mode,length:s.length}})}function yt(n,t){switch(t){case f.NUMERIC:return we.getBitsLength(n);case f.ALPHANUMERIC:return me.getBitsLength(n);case f.KANJI:return Ee.getBitsLength(n);case f.BYTE:return ye.getBitsLength(n)}}function tn(n){return n.reduce(function(t,e){let r=t.length-1>=0?t[t.length-1]:null;return r&&r.mode===e.mode?(t[t.length-1].data+=e.data,t):(t.push(e),t)},[])}function en(n){let t=[];for(let e=0;e<n.length;e++){let r=n[e];switch(r.mode){case f.NUMERIC:t.push([r,{data:r.data,mode:f.ALPHANUMERIC,length:r.length},{data:r.data,mode:f.BYTE,length:r.length}]);break;case f.ALPHANUMERIC:t.push([r,{data:r.data,mode:f.BYTE,length:r.length}]);break;case f.KANJI:t.push([r,{data:r.data,mode:f.BYTE,length:he(r.data)}]);break;case f.BYTE:t.push([{data:r.data,mode:f.BYTE,length:he(r.data)}])}}return t}function nn(n,t){let e={},r={start:{}},o=["start"];for(let i=0;i<n.length;i++){let s=n[i],u=[];for(let c=0;c<s.length;c++){let l=s[c],a=""+i+c;
vendor: 4,097 bytes, lines 4-8
4u.push(a),e[a]={node:l,lastCount:0},r[a]={};for(let w=0;w<o.length;w++){let h=o[w];e[h]&&e[h].node.mode===l.mode?(r[h][a]=yt(e[h].lastCount+l.length,l.mode)-yt(e[h].lastCount,l.mode),e[h].lastCount+=l.length):(e[h]&&(e[h].lastCount=l.length),r[h][a]=yt(l.length,l.mode)+4+f.getCharCountIndicator(l.mode,t))}}o=u}for(let i=0;i<o.length;i++)r[o[i]].end=0;return{map:r,table:e}}function pe(n,t){let e,r=f.getBestModeForData(n);if(e=f.from(t,r),e!==f.BYTE&&e.bit<r.bit)throw new Error('"'+n+'" cannot be encoded with mode '+f.toString(e)+`.
5 Suggested mode is: `+f.toString(r));switch(e===f.KANJI&&!v.isKanjiModeEnabled()&&(e=f.BYTE),e){case f.NUMERIC:return new we(n);case f.ALPHANUMERIC:return new me(n);case f.KANJI:return new Ee(n);case f.BYTE:return new ye(n)}}F.fromArray=function(t){return t.reduce(function(e,r){return typeof r=="string"?e.push(pe(r,null)):r.data&&e.push(pe(r.data,r.mode)),e},[])};F.fromString=function(t,e){let r=Ce(t,v.isKanjiModeEnabled()),o=en(r),i=nn(o,e),s=ve.find_path(i.map,"start","end"),u=[];for(let c=1;c<s.length-1;c++)u.push(i.table[s[c]].node);return F.fromArray(tn(u))};F.rawSplit=function(t){return F.fromArray(Ce(t,v.isKanjiModeEnabled()))}});var Te=g(Ae=>{var et=I(),Et=j(),rn=qt(),on=Ft(),sn=kt(),un=Ht(),At=Kt(),Tt=ct(),cn=Gt(),tt=te(),ln=oe(),an=M(),Ct=Be();function fn(n,t){let e=n.size,r=un.getPositions(t);for(let o=0;o<r.length;o++){let i=r[o][0],s=r[o][1];for(let u=-1;u<=7;u++)if(!(i+u<=-1||e<=i+u))for(let c=-1;c<=7;c++)s+c<=-1||e<=s+c||(u>=0&&u<=6&&(c===0||c===6)||c>=0&&c<=6&&(u===0||u===6)||u>=2&&u<=4&&c>=2&&c<=4?n.set(i+u,s+c,!0,!0):n.set(i+u,s+c,!1,!0))}}function gn(n){let t=n.size;for(let e=8;e<t-8;e++){let r=e%2===0;n.set(e,6,r,!0),n.set(6,e,r,!0)}}function dn(n,t){let e=sn.getPositions(t);for(let r=0;r<e.length;r++){let o=e[r][0],i=e[r][1];for(let s=-2;s<=2;s++)for(let u=-2;u<=2;u++)s===-2||s===2||u===-2||u===2||s===0&&u===0?n.set(o+s,i+u,!0,!0):n.set(o+s,i+u,!1,!0)}}function hn(n,t){let e=n.size,r=tt.getEncodedBits(t),o,i,s;for(let u=0;u<18;u++)o=Math.floor(u/3),i=u%3+e-8-3,s=(r>>u&1)===1,n.set(o,i,s,!0),n.set(i,o,s,!0)}function Bt(n,t,e){let r=n.size,o=ln.getEncodedBits(t,e),i,s;for(i=0;i<15;i++)s=(o>>i&1)===1,i<6?n.set(i,8,s,!0):i<8?n.set(i+1,8,s,!0):n.set(r-15+i,8,s,!0),i<8?n.set(8,r-i-1,s,!0):i<9?n.set(8,15-i-1+1,s,!0):n.set(8,15-i-1,s,!0);n.set(r-8,8,1,!0)}function pn(n,t){let e=n.size,r=-1,o=e-1,i=7,s=0;for(let u=e-1;u>0;u-=2)for(u===6&&u--;;){for(let c=0;c<2;c++)if(!n.isReserved(o,u-c)){let l=!1;s<t.length&&(l=(t[s]>>>i&1)===1),n.set(o,u-c,l),i--,i===-1&&(s++,i=7)}if(o+=r,o<0||e<=o){o-=r,r=-r;break}}}function wn(n,t,e){let r=new rn;e.forEach(function(c){r.put(c.mode.bit,4),r.put(c.getLength(),an.getCharCountIndicator(c.mode,n)),c.write(r)});let o=et.getSymbolTotalCodewords(n),i=Tt.getTotalCodewordsCount(n,t),s=(o-i)*8;for(r.getLengthInBits()+4<=s&&r.put(0,4);r.getLengthInBits()%8!==0;)r.putBit(0);let u=(s-r.getLengthInBits())/8;for(let c=0;c<u;c++)r.put(c%2?17:236,8);return mn(r,n,t)}function mn(n,t,e){let r=et.getSymbolTotalCodewords(t),o=Tt.getTotalCodewordsCount(t,e),i=r-o,s=Tt.getBlocksCount(t,e),u=r%s,c=s-u,l=Math.floor(r/s),a=Math.floor(i/s),w=a+1,h=l-a,y=new cn(h),A=0,T=new Array(s),bt=new Array(s),rt=0,Re=new Uint8Array(n.buffer);for(let _=0;_<s;_++){let it=_<c?a:w;T[_]=Re.slice(A,A+it),bt[_]=y.encode(T[_]),A+=it,rt=Math.max(rt,it)}let ot=new Uint8Array(r),Rt=0,E,C;for(E=0;E<rt;E++)for(C=0;C<s;C++)E<T[C].length&&(ot[Rt++]=T[C][E]);for(E=0;E<h;E++)for(C=0;C<s;C++)ot[Rt++]=bt[C][E];return ot}function yn(n,t,e,r){let o;if(Array.isArray(n))o=Ct.fromArray(n);else if(typeof n=="string"){let l=t;if(!l){let a=Ct.rawSplit(n);l=tt.getBestVersionForData(a,e)}o=Ct.fromString(n,l||40)}else throw new Error("Invalid data");let i=tt.getBestVersionForData(o,e);if(!i)throw new Error("The amount of data is too big to be stored in a QR Code");if(!t)t=i;else if(t<i)throw new Error(`
6The chosen QR Code version cannot contain this amount of data.
7Minimum version required to store current data is: `+i+`.
8`);let s=wn(t,e,o),u=et.getSymbolSize(t),c=new on(u);return fn(c,t),gn(c),dn(c,t),Bt(c,e,0),t>
8=7&&hn(c,t),pn(c,s),isNaN(r)&&(r=At.getBestMask(c,Bt.bind(null,c,e))),At.applyMask(r,c),Bt(c,e,r),{modules:c,version:t,errorCorrectionLevel:e,maskPattern:r,segments:o}}Ae.create=function(t,e){if(typeof t>"u"||t==="")throw new Error("No input text");let r=Et.M,o,i;return typeof e<"u"&&(r=Et.from(e.errorCorrectionLevel,Et.M),o=tt.from(e.version),i=At.from(e.maskPattern),e.toSJISFunc&&et.setToSJISFunction(e.toSJISFunc)),yn(t,o,r,i)}});var It=g(L=>{function Ie(n){if(typeof n=="number"&&(n=n.toString()),typeof n!="string")throw new Error("Color should be defined as hex string");let t=n.slice().replace("#","").split("");if(t.length<3||t.length===5||t.length>8)throw new Error("Invalid hex color: "+n);(t.length===3||t.length===4)&&(t=Array.prototype.concat.apply([],t.map(function(r){return[r,r]}))),t.length===6&&t.push("F","F");let e=parseInt(t.join(""),16);return{r:e>>24&255,g:e>>16&255,b:e>>8&255,a:e&255,hex:"#"+t.slice(0,6).join("")}}L.getOptions=function(t){t||(t={}),t.color||(t.color={});let e=typeof t.margin>"u"||t.margin===null||t.margin<0?4:t.margin,r=t.width&&t.width>=21?t.width:void 0,o=t.scale||4;
8return{width:r,scale:r?4:o,margin:e,color:{dark:Ie(t.color.dark||"#000000ff"),light:Ie(t.color.light||"#ffffffff")},type:t.type,rendererOpts:t.rendererOpts||{}}};L.getScale=function(t,e){return e.width&&e.width>=t+e.margin*2?e.width/(t+e.margin*2):e.scale};L.getImageWidth=function(t,e){let r=L.getScale(t,e);return Math.floor((t+e.margin*2)*r)};L.qrToImageData=function(t,e,r){let o=e.modules.size,i=e.modules.data,s=L.getScale(o,r),u=Math.floor((o+r.margin*2)*s),c=r.margin*s,l=[r.color.light,r.color.dark];for(let a=0;a<u;a++)for(let w=0;w<u;w++){let h=(a*u+w)*4,y=r.color.light;if(a>=c&&w>=c&&a<u-c&&w<u-c){let A=Math.floor((a-c)/s),T=Math.floor((w-c)/s);y=l[i[A*o+T]?1:0]}t[h++]=y.r,t[h++]=y.g,t[h++]=y.b,t[h]=y.a}}});var Ne=g(nt=>{var Nt=It();function En(n,t,e){n.clearRect(0,0,t.width,t.height),t.style||(t.style={}),t.height=e,t.width=e,t.style.height=e+"px",t.style.width=e+"px"}function Cn(){try{return document.createElement("canvas")}catch{throw new Error("You need to specify a canvas element")}}nt.render=function(t,e,r){let o=r,i=e;typeof o>"u"&&(!e||!e.getContext)&&(o=e,e=void 0),e||(i=Cn()),o=Nt.getOptions(o);let s=Nt.getImageWidth(t.modules.size,o),u=i.getContext("2d"),c=u.createImageData(s,s);return Nt.qrToImageData(c.data,t,o),En(u,i,s),u.putImageData(c,0,0),i};nt.renderToDataURL=function(t,e,r){let o=r;typeof o>"u"&&(!e||!e.getContext)&&(o=e,e=void 0),o||(o={});let i=nt.render(t,e,o),s=o.type||"image/png",u=o.rendererOpts||{};return i.toDataURL(s,u.quality)}});var Pe=g(Se=>{var Bn=It();function Me(n,t){let e=n.a/255,r=t+'="'+n.hex+'"';return e<1?r+" "+t+'-opacity="'+e.toFixed(2).slice(1)+'"':r}function Mt(n,t,e){let r=n+t;return typeof e<"u"&&(r+=" "+e),r}function An(n,t,e){let r="",o=0,i=!1,s=0;for(let u=0;u<n.length;u++){let c=Math.floor(u%t),l=Math.floor(u/t);!c&&!i&&(i=!0),n[u]?(s++,u>0&&c>0&&n[u-1]||(r+=i?Mt("M",c+e,.5+l+e):Mt("m",o,0),o=0,i=!1),c+1<t&&n[u+1]||(r+=Mt("h",s),s=0)):o++}return r}Se.render=function(t,e,r){let o=Bn.getOptions(e),i=t.modules.size,s=t.modules.data,u=i+o.margin*2,c=o.color.light.a?"<path "+Me(o.color.light,"fill")+' d="M0 0h'+u+"v"+u+'H0z"/>':"",l="<path "+Me(o.color.dark,"stroke")+' d="'+An(s,i,o.margin)+'"/>',a='viewBox="0 0 '+u+" "+u+'"',h='<svg xmlns="http://www.w3.org/2000/svg" '+(o.width?'width="'+o.width+'" height="'+o.width+'" ':"")+a+' shape-rendering="crispEdges">'+c+l+`</svg>
9`;return typeof r=="function"&&r(null,h),h}});var Nn=g(O=>{var Tn=_t(),St=Te(),be=Ne(),In=Pe();function Pt(n,t,e,r,o){let i=[].slice.call(arguments,1),s=i.length,u=typeof i[s-1]=="function";if(!u&&!Tn())throw new Error("Callback required as last argument");if(u){if(s<2)throw new Error("Too few arguments provided");s===2?(o=e,e=t,t=r=void 0):s===3&&(t.getContext&&typeof o>"u"?(o=r,r=void 0):(o=r,r=e,e=t,t=void 0))}else{if(s<1)throw new Error("Too few arguments provided");return s===1?(e=t,t=r=void 0):s===2&&!t.getContext&&(r=e,e=t,t=void 0),new Promise(function(c,l){try{let a=St.create(e,r);c(n(a,t,r))}catch(a){l(a)}})}try{let c=St.create(e,r);o(null,n(c,t,r))}catch(c){o(c)}}O.create=St.create;O.toCanvas=Pt.bind(null,be.render);O.toDataURL=Pt.bind(null,be.renderToDataURL);O.toString=Pt.bind(null,function(n,t,e){return In.render(n,e)})});return Nn();})();
10
11// END QR GENERATOR
12// BEGIN CONTACT RENDERER
13const contactIcons={"Instagram": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJpbnN0YWdyYW0iIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1NiAyNTYuMDIiPjxwYXRoIGQ9Ik0yNTUuMjMsNzUuMjNjLS42Mi0xMy42Mi0yLjc5LTIyLjkzLTUuOTUtMzEuMDctMy4yMS04LjU0LTguMjUtMTYuMjgtMTQuNzYtMjIuNjctNi4zOS02LjUxLTE0LjEzLTExLjU1LTIyLjY3LTE0Ljc3LTguMTQtMy4xNi0xNy40NS01LjMyLTMxLjA3LTUuOTQtMTMuNjUtLjYyLTE4LjAxLS43Ny01Mi43Ny0uNzdzLTM5LjEyLjE1LTUyLjc3Ljc3Yy0xMy42Mi42Mi0yMi45MywyLjc5LTMxLjA3LDUuOTUtOC41NSwzLjIyLTE2LjI4LDguMjUtMjIuNjcsMTQuNzctNi41MSw2LjM5LTExLjU1LDE0LjEyLTE0Ljc3LDIyLjY3LTMuMTYsOC4xNC01LjMyLDE3LjQ1LTUuOTQsMzEuMDctLjYzLDEzLjY1LS43NywxOC4wMS0uNzcsNTIuNzhzLjE1LDM5LjEyLjc3LDUyLjc4Yy42MiwxMy42MiwyLjc5LDIyLjkzLDUuOTUsMzEuMDcsMy4yMSw4LjU0LDguMjUsMTYuMjgsMTQuNzYsMjIuNjcsNi4zOSw2LjUxLDE0LjEzLDExLjU1LDIyLjY3LDE0Ljc2LDguMTQsMy4xNiwxNy40NSw1LjMzL
13DMxLjA3LDUuOTUsMTMuNjUuNjIsMTguMDEuNzcsNTIuNzcuNzdzMzkuMTItLjE0LDUyLjc3LS43N2MxMy42Mi0uNjIsMjIuOTMtMi43OSwzMS4wNy01Ljk1LDE3LjE5LTYuNjQsMzAuNzgtMjAuMjQsMzcuNDQtMzcuNDQsMy4xNi04LjE0LDUuMzMtMTcuNDUsNS45NS0zMS4wNy42Mi0xMy42NS43Ny0xOC4wMS43Ny01Mi43OHMtLjE1LTM5LjEzLS43Ny01Mi43OVpNMjMyLjE5LDE3OS43M2MtLjU3LDEyLjQ4LTIuNjUsMTkuMjYtNC40MSwyMy43Ni00LjMxLDExLjE2LTEzLjEzLDE5Ljk5LTI0LjI5LDI0LjI5LTQuNTEsMS43NS0xMS4yOSwzLjg0LTIzLjc2LDQuNDEtMTMuNS42MS0xNy41NC43NS01MS43Mi43NXMtMzguMjMtLjEzLTUxLjcyLS43NWMtMTIuNDgtLjU3LTE5LjI2LTIuNjUtMjMuNzYtNC40MS01LjU2LTIuMDYtMTAuNTktNS4zMi0xNC43MS05LjU4LTQuMjUtNC4xMy03LjUyLTkuMTUtOS41OC0xNC43MS0xLjc1LTQuNTEtMy44NC0xMS4yOS00LjQxLTIzLjc2LS42MS0xMy41LS43NS0xNy41NC0uNzUtNTEuNzJzLjEzLTM4LjIyLjc1LTUxLjcyYy41NS0xMi40OSwyLjYzLTE5LjI2LDQuMzgtMjMuNzcsMi4wNi01LjU2LDUuMzMtMTAuNiw5LjU4LTE0LjcyLDQuMTMtNC4yNSw5LjE2LTcuNTIsMTQuNzItOS41OCw0LjUxLTEuNzUsMTEuMjktMy44NCwyMy43Ni00LjQxLDEzLjUtLjYxLDE3LjU0LS43NCw1MS43Mi0uNzRoMGMzNC4xOCwwLDM4LjIyLjEzLDUxLjcyLjc1LDEyLjQ4LjU3LDE5LjI2LDIuNjUsMjMuNzYsNC40MSw1LjU2LDIuMDYsMTAuNTksNS4zMiwxNC43MSw5LjU4LDQuMjUsNC4xMyw3LjUyLDkuMTYsOS41OCwxNC43MiwxLjc1LDQuNTEsMy44NCwxMS4yOSw0LjQxLDIzLjc2LjYxLDEzLjUuNzUsMTcuNTQuNzUsNTEuNzJzLS4xMiwzOC4yMi0uNzMsNTEuNzJaIiBmaWxsPSIjZmZmIiBzdHJva2Utd2lkdGg9IjAiLz48cGF0aCBkPSJNMTI3Ljk5LDYyLjI4Yy0zNi4zLDAtNjUuNzIsMjkuNDMtNjUuNzIsNjUuNzJzMjkuNDMsNjUuNzMsNjUuNzIsNjUuNzMsNjUuNzMtMjkuNDMsNjUuNzMtNjUuNzMtMjkuNDMtNjUuNzItNjUuNzMtNjUuNzJaTTEyNy45OSwxNzAuNjdjLTIzLjU2LDAtNDIuNjYtMTkuMS00Mi42Ni00Mi42N3MxOS4xLTQyLjY3LDQyLjY3LTQyLjY3LDQyLjY3LDE5LjEsNDIuNjcsNDIuNjctMTkuMTEsNDIuNjctNDIuNjgsNDIuNjdaIiBmaWxsPSIjZmZmIiBzdHJva2Utd2lkdGg9IjAiLz48cGF0aCBkPSJNMjExLjY4LDU5LjY4YzAsOC40OC02Ljg4LDE1LjM2LTE1LjM2LDE1LjM2cy0xNS4zNi02Ljg4LTE1LjM2LTE1LjM2LDYuODgtMTUuMzYsMTUuMzYtMTUuMzYsMTUuMzYsNi44OCwxNS4zNiwxNS4zNloiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPjwvc3ZnPg==", "YouTube": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJZb3VUdWJlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNjUuNzEgMjU2Ij48cGF0aCBkPSJNMzU4LjA3LDM5Ljk4Yy00LjIxLTE1LjczLTE2LjYtMjguMTMtMzIuMzMtMzIuMzNDMjk3LjIyLDAsMTgyLjg2LDAsMTgyLjg2LDBjMCwwLTExNC4zNiwwLTE0Mi44OCw3LjY0QzI0LjI0LDExLjg1LDExLjg1LDI0LjI0LDcuNjQsMzkuOTgsMCw2OC40OSwwLDEyOCwwLDEyOGMwLDAsMCw1OS41MSw3LjY0LDg4LjAyLDQuMjEsMTUuNzMsMTYuNiwyOC4xMywzMi4zMywzMi4zMywyOC41Miw3LjY0LDE0Mi44OCw3LjY0LDE0Mi44OCw3LjY0LDAsMCwxMTQuMzYsMCwxNDIuODgtNy42NCwxNS43My00LjIxLDI4LjEzLTE2LjYsMzIuMzMtMzIuMzMsNy42NC0yOC41Miw3LjY0LTg4LjAyLDcuNjQtODguMDIsMCwwLDAtNTkuNTEtNy42NC04OC4wMlpNMTQ2LjI5LDE4Mi44NnYtMTA5LjcxbDk1LjAxLDU0Ljg2LTk1LjAxLDU0Ljg2WiIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+PC9zdmc+", "Facebook": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJGYWNlYm9vayIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgMTI5LjMyIDI1NiI+PHBhdGggZD0iTTQuMTMsMTM2LjM1aDI4LjA2djExNS41M2MwLDIuMjgsMS44NSw0LjEzLDQuMTMsNC4xM2g0Ny41OGMyLjI4LDAsNC4xMy0xLjg1LDQuMTMtNC4xM3YtMTE0Ljk4aDMyLjI2YzIuMSwwLDMuODYtMS41Nyw0LjEtMy42Nmw0LjktNDIuNTNjLjEzLTEuMTctLjI0LTIuMzQtMS4wMi0zLjIyLS43OC0uODgtMS45MS0xLjM4LTMuMDgtMS4zOGgtMzcuMTZ2LTI2LjY2YzAtOC4wNCw0LjMzLTEyLjExLDEyLjg2LTEyLjExaDI0LjNjMi4yOCwwLDQuMTMtMS44NSw0LjEzLTQuMTNWNC4xNmMwLTIuMjgtMS44NS00LjEzLTQuMTMtNC4xM2gtMzMuNDhjLS4yNC0uMDEtLjc2LS4wMy0xLjUzLS4wMy01LjgxLDAtMjYsMS4xNC00MS45NSwxNS44Mi0xNy42NywxNi4yNi0xNS4yMiwzNS43My0xNC42MywzOS4xMXYzMS4xOEg0LjEzYy0yLjI4LDAtNC4xMywxLjg1LTQuMTMsNC4xM3Y0MS45OWMwLDIuMjgsMS44NSw0LjEzLDQuMTMsNC4xM1oiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPjwvc3ZnPg==", "TikTok": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJ0aWt0b2siIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDIyMS44OCAyNTYiPjxwYXRoIGQ9Ik0xOTQuMjUsNTQuNzVjLTEuNzMtLjg5LTMuNDEtMS44Ny01LjA0LTIuOTMtNC43NC0zLjEzLTkuMDktNi44My0xMi45NC0xMS05LjY1LTExLjA0LTEzLjI2LTIyLjI1LTE0LjU5LTMwLjA5aC4wNWMtMS4xMS02LjUxLS42NS0xMC43Mi0uNTgtMTAuNzJoLTQzLjk3djE3MC4wMWMwLDIuMjgsMCw0LjU0LS4xLDYuNzcsMCwuMjgtLjAzLjUzLS4wNC44MywwLC4xMiwwLC4yNS0uMDMuMzh2LjFjLS45NCwxMi4zOS03Ljk4LDIzLjQ5LTE4Ljc4LDI5LjYzLTUuNTQsMy4xNS0xMS44MSw0LjgxLTE4LjE5LDQuOC0yMC40OCwwLTM3LjA5LTE2LjctMzcuMDktMzcuMzNzMTYuNi0zNy4zMywzNy4wOS0zNy4zM2MzLjg4LDAsNy43My42MSwxMS40MiwxLjgxbC4wNS00NC43N2MtMjIuNjMtMi45Mi00NS40NSwzLjc1LTYyLjkzLDE4LjQxLTcuNTgsNi41OC0xMy45NSwxNC40NC0xOC44MywyMy4yMS0xLjg2LDMuMi04Ljg2LDE2LjA2LTkuNzEsMzYuOTMtLjUzLDExLjg0LDMuMDIsMjQuMTIsNC43MiwyOS4xOXYuMTFjMS4wNywyLjk5LDUuMiwxMy4xOCwxMS45NCwyMS43Nyw1LjQzLDYuODksMTEuODUsMTIuOTUsMTkuMDQsMTcuOTd2LS4xMWwuMTEuMTFjMjEuMjgsMTQuNDYsNDQuODgsMTMuNTEsNDQuODgsMTMuNTEsNC4wOS0uMTcsMTcuNzcsMCwzMy4zMS03LjM2LDE3LjI0LTguMTYsMjcuMDUtMjAuMzMsMjcuMDUtMjAuMzMsNi4yNy03LjI3LDExLjI1LT
13E1LjU1LDE0Ljc0LTI0LjQ5LDMuOTgtMTAuNDYsNS4zMS0yMyw1LjMxLTI4LjAxdi05MC4xOWMuNTMuMzIsNy42NCw1LjAyLDcuNjQsNS4wMiwwLDAsMTAuMjMsNi41NiwyNi4yLDEwLjgzLDExLjQ2LDMuMDQsMjYuODksMy42OCwyNi44OSwzLjY4di00My42NWMtNS40MS41OS0xNi4zOS0xLjEyLTI3LjYzLTYuNzJaIiBmaWxsPSIjZmZmIiBzdHJva2Utd2lkdGg9IjAiLz48L3N2Zz4=", "X": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI4My4yMiAyNTYiPjxnIGlkPSJ4IiBpbWFnZS1yZW5kZXJpbmc9Im9wdGltaXplUXVhbGl0eSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iIHRleHQtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPjxwYXRoIGQ9Ik0yMjMuMDUsMGg0My40M2wtOTQuODgsMTA4LjQ0LDExMS42MiwxNDcuNTZoLTg3LjRsLTY4LjQ1LTg5LjUtNzguMzIsODkuNUg1LjU5bDEwMS40OC0xMTUuOTlMMCwwaDg5LjYxbDYxLjg3LDgxLjhMMjIzLjA1LDBaTTIwNy44MSwyMzBoMjQuMDdMNzYuNTQsMjQuNjNoLTI1LjgybDE1Ny4wOSwyMDUuMzdoMFoiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPjwvZz48L3N2Zz4=", "WhatsApp": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBpZD0id2EiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmVyc2lvbj0iMS4xIiB2aWV3Qm94PSIwIDAgMjU2IDI1NiI+CiAgPGRlZnM+CiAgICA8c3R5bGU+CiAgICAgIC5jbHMtMSB7CiAgICAgICAgZmlsbDogI2ZmZjsKICAgICAgICBzdHJva2Utd2lkdGg6IDBweDsKICAgICAgfQogICAgPC9zdHlsZT4KICA8L2RlZnM+CiAgPHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTMwLjMsMEM2MS40LDAsNS42LDU1LjgsNS42LDEyNC43czYuNSw0NS42LDE3LjksNjQuNEwxLDI1Nmw2OS0yMi4xYzE3LjksOS45LDM4LjQsMTUuNSw2MC4zLDE1LjUsNjguOSwwLDEyNC43LTU1LjgsMTI0LjctMTI0LjdTMTk5LjIsMCwxMzAuMywwWk0xMzAuMywyMjguNWMtMjEuMSwwLTQwLjctNi4zLTU3LjEtMTcuMmwtMzkuOSwxMi44LDEzLTM4LjVjLTEyLjQtMTcuMS0xOS44LTM4LjEtMTkuOC02MC45LDAtNTcuMiw0Ni42LTEwMy44LDEwMy44LTEwMy44czEwMy44LDQ2LjYsMTAzLjgsMTAzLjgtNDYuNiwxMDMuOC0xMDMuOCwxMDMuOFpNMTg4LjgsMTUzYy0zLjEtMS43LTE4LjUtMTAtMjEuNC0xMS4yLTIuOS0xLjItNS0xLjgtNy4yLDEuMy0yLjIsMy4xLTguNiwxMC0xMC41LDEyLjEtMS45LDIuMS0zLjgsMi4yLTYuOS41LTMuMS0xLjctMTMuMy01LjUtMjUtMTYuOC05LjEtOC44LTE1LjEtMTkuNS0xNi45LTIyLjctMS43LTMuMywwLTQuOSwxLjYtNi40LDEuNS0xLjQsMy4zLTMuNiw1LTUuNCwxLjctMS44LDIuMi0zLjEsMy40LTUuMiwxLjEtMi4xLjctNCwwLTUuNi0uNy0xLjYtNi41LTE3LjUtOC45LTI0LTIuNC02LjUtNS4xLTUuNS03LTUuNi0xLjksMC00LS40LTYuMS0uNS0yLjEsMC01LjYuNi04LjYsMy43LTMsMy4xLTExLjUsMTAuNS0xMi4xLDI2LjEtLjYsMTUuNywxMC4zLDMxLjIsMTEuOCwzMy40LDEuNSwyLjIsMjAuNywzNi4xLDUyLjYsNTAuMSwzMS45LDE0LDMyLjEsOS43LDM3LjksOS40LDUuOS0uMywxOS4xLTcsMjIuMS0xNC4zLDIuOS03LjMsMy4yLTEzLjcsMi40LTE1LjEtLjctMS40LTIuOC0yLjItNi0zLjlaIi8+Cjwvc3ZnPg==", "Signal": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJzaWduYWwiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDI1NiAyNTYiPjxwYXRoIGQ9Ik0xMjguMDEsMjRjLTU3LjQ0LjAyLTEwMy45OSw0Ni42Mi0xMDMuOTUsMTA0LjAzLDAsMTkuNTgsNS41MiwzOC43MywxNS45NCw1NS4yOWwtMTAsNDIuNjYsNDIuNjctMTBjNDguNjEsMzAuNiwxMTIuODIsMTYuMDIsMTQzLjQzLTMyLjU4LDMwLjYxLTQ4LjYsMTYuMDItMTEyLjgtMzIuNTktMTQzLjQtMTYuNjEtMTAuNDgtMzUuODYtMTYuMDItNTUuNS0xNmgwWk02OC42MSwyMjcuNzdsLTE3LjE5LDQsMi43MywxMS42OSwxMi42NS0yLjk0YzkuNTgsNS4yMywxOS44MSw5LjE5LDMwLjQyLDExLjc5bDIuODgtMTEuNjRjLTExLjA0LTIuNzUtMjEuNjMtNy4xMi0zMS40LTEyLjk4bC0uMDguMDhoMFpNMTIuNjEsMjAxLjc4bDExLjY5LDIuNzEsNC0xNy4xOWMtNS44My05Ljc5LTEwLjE5LTIwLjQyLTEyLjktMzEuNDhsLTExLjY1LDIuODdjMi42LDEwLjYsNi41OCwyMC44MywxMS43OSwzMC40MWwtMi45NCwxMi42N2gwWk00MC43NywyMzQuMTlsLTI0Ljc3LDUuNzksNS43Ny0yNC43Ny0xMS42OS0yLjczLTUuNzcsMjQuNzdjLTEuNTIsNi40NiwyLjUsMTIuOTIsOC45NCwxNC40MiwxLjc5LjQyLDMuNjcuNDIsNS40OCwwbDI0Ljc1LTUuNjktMi43MS0xMS43OWgwWk0xMTAuNjMsMTMuMjljMTEuNTItMS43MywyMy4yMy0xLjczLDM0Ljc1LDBsMS43OS0xMS44NWMtMTIuNzEtMS45Mi0yNS42NS0xLjkyLTM4LjM2LDBsMS44MSwxMS44NWgwWk0yMzcuNjIsNjEuODNsLTEwLjI3LDYuMTdjNi4wMiw5Ljk4LDEwLjUsMjAuODEsMTMuMjksMzIuMTJsMTEuNjUtMi44N2MtMy4wOC0xMi40OC04LjAyLTI0LjQxLTE0LjY3LTM1LjQxaDBaTTM0LjYzLDU5LjJjNi45Mi05LjM3LDE1LjIxLTE3LjY3LDI0LjU5LTI0LjU4bC03LjIxLTkuNjdjLTEwLjMxLDcuNi0xOS40NCwxNi43My0yNy4wNCwyNy4wNGw5LjY3LDcuMjFoMFpNMTk2LjgxLDM0LjYyYzkuMzgsNi45MiwxNy42NywxNS4yMSwyNC41OSwyNC41OGw5LjY3LTcuMjFjLTcuNi0xMC4zMS0xNi43My0xOS40NC0yNy4wNC0yNy4wNGwtNy4yMSw5LjY3aDBaTTIyMS4zOSwxOTYuOGMtNi45Miw5LjM3LTE1LjIxLDE3LjY0LTI0LjU5LDI0LjU2bDcuMTMsOS42N2MxMC4zMy03LjYsMTkuNDgtMTYuNzMsMjcuMTMtMjcuMDRsLTkuNjctNy4xOWgwWk0xNDUuMzksMjQyLjY5Yy0xMS41MiwxLjczLTIzLjIzLDEuNzMtMzQuNzUsMGwtMS43OSwx
13MS44N2MxMi43MSwxLjkyLDI1LjY1LDEuOTIsMzguMzYsMGwtMS44MS0xMS44N2gwWk0yNTIuMjcsMTU4LjcybC0xMS42NS0yLjg3Yy0yLjc5LDExLjMzLTcuMjcsMjIuMTYtMTMuMjksMzIuMTZsMTAuMjcsNi4xOWM2LjY3LTExLjAyLDExLjYxLTIzLDE0LjY3LTM1LjQ4aDBaTTI0NC4wMiwxMjcuOTljMCw1LjgxLS40NCwxMS42Mi0xLjMxLDE3LjM3bDExLjg2LDEuODFjMS45Mi0xMi43MSwxLjkyLTI1LjY0LDAtMzguMzVsLTExLjg2LDEuNzljLjg4LDUuNzUsMS4zMSwxMS41NiwxLjMxLDE3LjM3aDBaTTE5NC4xOCwyMzcuNThsLTYuMTctMTAuMjdjLTkuOTgsNi4wMi0yMC44MSwxMC41LTMyLjEzLDEzLjI5bDIuODgsMTEuNjRjMTIuNDgtMy4wOCwyNC40Mi04LjAyLDM1LjQyLTE0LjY3aDBaTTEyLDEyNy45OWMwLTUuODEuNDQtMTEuNjIsMS4yOS0xNy4zN2wtMTEuODYtMS43OWMtMS45MiwxMi43MS0xLjkyLDI1LjY0LDAsMzguMzVsMTEuODYtMS44MWMtLjg1LTUuNzUtMS4yOS0xMS41Ni0xLjI5LTE3LjM3aDBaTTE4LjQsNjEuODNjLTYuNjUsMTEuMDItMTEuNTgsMjIuOTYtMTQuNjcsMzUuNDNsMTEuNjUsMi44N2MyLjc5LTExLjMzLDcuMjctMjIuMTYsMTMuMjktMzIuMTZsLTEwLjI3LTYuMTVoMFpNMTU4LjcyLDMuNzNsLTIuODgsMTEuNjRjMTEuMzMsMi43OSwyMi4xNyw3LjI3LDMyLjE3LDEzLjI5bDYuMTktMTAuMjdjLTExLTYuNjUtMjIuOTgtMTEuNTgtMzUuNDgtMTQuNjdoMFpNOTcuMjgsMy43M2wyLjg4LDExLjY0Yy0xMS4zMywyLjc5LTIyLjE3LDcuMjctMzIuMTcsMTMuMjlsLTYuMTctMTAuMjdjMTEuMDQtNi42NSwyMi45OC0xMS41OCwzNS40Ni0xNC42N2gwWiIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+PC9zdmc+", "InstagramTile": "data:image/jpeg;base64,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"};
14const contactEscape=value=>String(value??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
15function contactIcon(type,featured=false){
16 const image=contactIcons[featured&&type==='Instagram'?'InstagramTile':type];
17 if(image)return `<img src="${image}" alt="" aria-hidden="true">`;
18 if(type==='Text')return `<svg viewBox="0 0 24 24" fill="${featured?'currentColor':'none'}" stroke="${featured?'none':'currentColor'}" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3C6.48 3 2 6.58 2 11c0 2.2 1.1 4.2 2.9 5.65L3.5 21l5.1-2.45c1.06.3 2.2.45 3.4.45 5.52 0 10-3.58 10-8s-4.48-8-10-8Z"/></svg>`;
19 const shapes={Text:'<path d="M4 4h16v12H9l-5 4z"/>',Call:'<path d="M5 3l4 4-2 3c2 4 3 5 7 7l3-2 4 4c-2 5-7 3-12-2S0 5 5 3z"/>',Email:'<rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 5 9 8 9-8"/>',Website:'<circle cx="12" cy="12" r="9"/><ellipse cx="12" cy="12" rx="4" ry="9"/><path d="M3 12h18M5 6h14M5 18h14"/>'};
20 return `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" aria-hidden="true">${shapes[type]||shapes.Website}</svg>`;
21}
22function renderContactMarkup(profile){
23 const reviews=profile.links.filter(l=>['write','read'].includes(l.googleReviewAction));
24 const links=profile.links.filter(l=>!l.googleReviewAction),featured=['primary','secondary'].flatMap(role=>links.filter(l=>l.status===role));
25 const subtitle=l=>['Instagram','Facebook','YouTube','TikTok','X'].includes(l.type)?'@'+l.value.replace(/^@/,''):l.value;
26 const top=`<div class="contact-featured">${featured.map(l=>`<a class="contact-feature" href="${contactEscape(l.url)}" target="_blank" rel="noopener noreferrer"><span class="contact-feature-icon ${['Text','Call'].includes(l.type)?'contact-green':''}">
26${contactIcon(l.type,true)}</span><span class="contact-feature-copy"><strong>${contactEscape(l.type)}</strong><span>${contactEscape(subtitle(l))}</span></span></a>`).join('')}</div>`;
27 const shop=profile.shop?renderLocationMarkup(profile.shop):'';
28 const footer=links.filter(l=>l.isInFooter);
29 const rows=Array.from({length:Math.ceil(footer.length/5)},(_,i)=>footer.slice(i*5,i*5+5));
30 const bottom=`<div class="contact-socials">${rows.map(row=>`<div class="contact-social-row">${row.map(l=>`<a href="${contactEscape(l.url)}" aria-label="${contactEscape(l.type)}" title="${contactEscape(l.type)}" target="_blank" rel="noopener noreferrer">${contactIcon(l.type)}</a>`).join('')}</div>`).join('')}</div>`;
31 const googleReviewIcon='<img class="google-review-logo" src="data:image/png;base64,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" alt="" aria-hidden="true">';
32 const reviewButtons=reviews.length?`<section class="contact-reviews" aria-label="Google Reviews">${['write','read'].map(action=>{const link=reviews.find(l=>l.googleReviewAction===action);return link?`<a class="${action==='write'?'google-review-write':'google-review-read'}" href="${contactEscape(link.url)}" target="_blank" rel="noopener noreferrer">${action==='write'?googleReviewIcon:''}<span>${action==='write'?'Leave a Google review':'Read reviews on Google'}</span>${action==='read'?' <span aria-hidden="true">↗</span>':''}</a>`:'';}).join('')}</section>`:'';
33 return top+shop+bottom+reviewButtons+(!featured.length&&!footer.length&&!reviews.length&&!profile.shop?'<p class="empty-state">No contact information has been shared yet.</p>':'');
34}
35
36function renderLocationMarkup(s,{label='Tattoo studio',query=[s.title,s.address].filter(
36Boolean).join(' '),showTitle=true}={}) {
37  const url=`https://maps.apple.com/?q=${encodeURIComponent(query)}`;
38  let map='';
39  if(Number.isFinite(s.latitude)&&Number.isFinite(s.longitude)&&Math.abs(s.latitude)<85&&Math.abs(s.longitude)<=180){
40   const src=contactMapURL(s);
41   map=`<div class="contact-map-image"><img src="${contactEscape(src)}" alt="Satellite map of ${contactEscape(s.title)}" loading="eager" fetchpriority="high" decoding="async"><span class="contact-map-pin" aria-hidden="true"></span></div>`;
42  }
43  return `<section class="contact-shop"><div class="contact-map-wrap"><a class="contact-map" data-map-query="${contactEscape(query)}" href="${contactEscape(url)}" target="_blank" rel="noopener noreferrer" aria-label="Open ${contactEscape(s.title)} in Maps"><div class="contact-shop-header"><span>${contactEscape(label)}</span><span>${contactEscape(s.title)}</span></div>${map}</a>${map?'<details class="contact-map-credit"><summary aria-label="Map credits">i</summary><div>Powered by Esri · Esri, Maxar, Earthstar Geographics, and the GIS User Community</div></details>':''}</div>${showTitle?`<h2>${contactEscape(s.title)}</h2>`:''}<p>${contactEscape(s.address)}</p></section>`;
44}
45
46function contactMapURL(s){
47 if(!s||!Number.isFinite(s.latitude)||!Number.isFinite(s.longitude)||Math.abs(s.latitude)>
47=85||Math.abs(s.longitude)>180)return null;
48   const x=s.longitude*20037508.34/180,y=Math.log(Math.tan((90+s.latitude)*Math.PI/360))*20037508.34/Math.PI;
49   return 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/export?'+new URLSearchParams({bbox:[x-300,y-150,x+300,y+150].join(','),bboxSR:'3857',imageSR:'3857',size:'900,450',format:'jpg',f:'image'});
50}
51// END CONTACT RENDERER
52// Choose the destination app without changing the embedded map provider.
53function updateMapDestination(event){
54 const link=event.target.closest?.('a[data-map-query]');
55 if(!link)return;
56 const apple=/iPhone|iPad|iPod|Macintosh|Mac OS X/i.test(navigator.userAgent)&&!/Android/i.test(navigator.userAgent);
57 const query=encodeURIComponent(link.dataset.mapQuery);
58 link.href=apple?`https://maps.apple.com/?q=${query}`:`https://www.google.com/maps/search/?api=1&query=${query}`;
59}
60for(const event of ['pointerdown','click','auxclick','contextmenu'])document.addEventListener(event,updateMapDestination,true);
61// BEGIN PLACEMENT OPTIONS
62const placementOptions={"Torso (Front)":["Chest","Chest (Left)","Chest (Right)","Sternum","Breast","Underbreast","Clavicle (Left)","Clavicle (Right)","Stomach","Abdomen (Upper)","Abdomen (Lower)","Navel","Groin","Side / Flank","Ribs","Ribs (Left)","Ribs (Right)","Hip (Left)","Hip (Right)"],"Torso (Back)":["Ribs","Ribs (Left)","Ribs (Right)","Hip (Left)","Hip (Right)","Back","Back (Upper)","Back (Middle)","Back (Lower)","Spine","Shoulder Blade (Left)","Shoulder Blade (Right)","Buttocks","Buttocks (Left)","Buttocks (Right)"],"Arm (Left)":["Sleeve (Quarter)","Sleeve (Half)","Sleeve (Full)","Forearm","Forearm (Inner)","Forearm (Outer)","Elbow","Elbow (Inner)","Elbow (Outer)","Bicep","Bicep (Inner)","Bicep (Outer)","Shoulder","Upper Arm","Tricep / Back of Upper Arm","Armpit","Wrist (Inner)","Wrist (Outer)"],"Arm (Right)":["Sleeve (Quarter)","Sleeve (Half)","Sleeve (Full)","Forearm","Forearm (Inner)","Forearm (Outer)","Elbow","Elbow (Inner)","Elbow (Outer)","Bicep","Bicep (Inner)","Bicep (Outer)","Shoulder","Upper Arm","Tricep / Back of Upper Arm","Armpit","Wrist (Inner)","Wrist (Outer)"],"Hand (Left)":["Wrist (Inner)","Wrist (Outer)","Palm (Back)","Palm","Side of Hand","Fingers","Side of Finger","Fingertips","Knuckles","Thumb","Index Finger","Middle Finger","Ring Finger","Pinky Finger"],"Hand (Right)":["Wrist (Inner)","Wrist (Outer)","Palm (Back)","Palm","Side of Hand","Fingers","Side of Finger","Fingertips","Knuckles","Thumb","Index Finger","Middle Finger","Ring Finger","Pinky Finger"],"Leg (Left)":["Thigh","Thigh (Front)","Thigh (Upper)","Thigh (Lower)","Thigh (Inner)","Thigh (Outer)","Thigh (Rear)","Knee (Front)","Knee (Back)","Shin","Calf","Calf (Inner)","Calf (Outer)","Full Leg / Sleeve"],"Leg (Right)":["Thigh","Thigh (Front)","Thigh (Upper)","Thigh (Lower)","Thigh (Inner)","Thigh (Outer)","Thigh (Rear)","Knee (Front)","Knee (Back)","Shin","Calf","Calf (Inner)","Calf (Outer)","Full Leg / Sleeve"],"Foot (Left)":["Ankle (Inner)","Ankle (Outer)","Bridge (Top)","Foot (Inner Side)","Foot (Outer Side)","Heel","Achilles / Back of Ankle","Sole (Bottom)","Toe(s)"],"Foot (Right)":["Ankle (Inner)","Ankle (Outer)","Bridge (Top)","Foot (Inner Side)","Foot (Outer Side)","Heel","Achilles / Back of Ankle","Sole (Bottom)","Toe(s)"],"Face":["Mouth (Inner)","Mouth (Outer)","Forehead","Nose","Jawline","Chin","Under Chin","Cheek (Left)","Cheek (Right)","Temple (Left)","Temple (Right)"],"Head":["Ear (Left)","Ear (Right)","Behind Ear (Left)","Behind Ear (Right)","Scalp","Scalp (Crown)","Scalp (Back)","Scalp (Side)"],"Neck":["Neck (Throat)","Neck (Back)","Neck (Left)","Neck (Right)"]};
63// END PLACEMENT OPTIONS
64const app=document.querySelector('#app'),dialog=document.querySelector('#detail'),detail=document.querySelector('#dialog-content');
65const escape=value=>String(value??'').replace(/[&<>"']/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
66const money=value=>new Intl.NumberFormat('en-US',{style:'currency',currency:'USD',maximumFractionDigits:2}).format(value);
67const labels={event:'Events',flash:'Flash',portfolio:'Portfolio',contact:'Contact',book:'Book'};
68let fullProfileRequest;
69const bookingWeekdays=new Set();
70const tabPanels=new Map();
71let profile,activeTab,selectedDay,displayMonth,selectedFlash=null,bookingView='calendar';
72const path=decodeURIComponent(location.pathname).split('/').filter(
72Boolean);
73const artistUsername=path[0];
74const demo=artistUsername==='demo' && ['localhost','127.0.0.1'].includes(location.hostname);
75function dateLabel(value,options={dateStyle:'full'}) {return new Intl.DateTimeFormat('en-US',{timeZone:profile.timezone,...options}).format(new Date(value));}
76function dayKey(value) {return new Intl.DateTimeFormat('en-CA',{timeZone:profile.timezone,year:'numeric',month:'2-digit',day:'2-digit'}).format(new Date(value));}
77let dialogScrollCleanup=()=>{};
78let dialogPageLock=null;
79function lockDialogPage(){
80 // Keep the document in normal flow: repeatedly fixing the body can strand
81 // Safari's touch scrolling after a scrollable dialog followed by a short one.
82 if(!dialogPageLock)dialogPageLock={x:window.scrollX,y:window.scrollY};
83}
84function unlockDialogPage(){
85 if(dialog.open||!dialogPageLock)return;
86 const saved=dialogPageLock;dialogPageLock=null;
87 window.scrollTo({left:saved.x,top:saved.y,behavior:'instant'});
88}
89// Contain gestures only inside the open dialog, never lock the page itself.
90let dialogTouchY=null;
91dialog.addEventListener('touchstart',event=>{dialogTouchY=event.touches.length===1?event.touches[0].clientY:null;},{passive:true});
92dialog.addEventListener('touchmove',event=>{
93 if(!dialog.open||dialogTouchY===null||event.touches.length!==1)return;
94 const y=event.touches[0].clientY,delta=dialogTouchY-y;dialogTouchY=y;
95 if(dialog.scrollHeight<=dialog.clientHeight+1||(delta<0&&dialog.scrollTop<=0)||(delta>0&&dialog.scrollTop+dialog.clientHeight>=dialog.scrollHeight-1))event.preventDefault();
96},{passive:false});
97dialog.addEventListener('touchend',()=>{dialogTouchY=null;},{passive:true});
98dialog.addEventListener('touchcancel',()=>{dialogTouchY=null;},{passive:true});
99dialog.addEventListener('close',unlockDialogPage);
100function showDialog(markup){dialogScrollCleanup();detail.innerHTML=markup;if(!dialog.open){lockDialogPage();try{dialog.showModal();}catch(error){unlockDialogPage();throw error;}}dialog.scrollTop=0;const heading=detail.querySelector('#dialog-title');if(heading){heading.tabIndex=-1;heading.focus({preventScroll:true});}}
101function closeDialogFromPointer(){
102 // Restore scrolling now, without waiting for the queued close event.
103 dialog.close();unlockDialogPage();dialogScrollCleanup();
104 requestAnimationFrame(()=>{if(!dialog.open&&document.activeElement instanceof HTMLElement)document.activeElement.blur();});
105}
106dialog.addEventListener('cancel',event=>{event.preventDefault();closeDialogFromPointer();});
107new MutationObserver(()=>{if(!dialog.open)unlockDialogPage();}).observe(dialog,{attributes:true,attributeFilter:['open']});
108window.addEventListener('pageshow',()=>{if(!dialog.open)unlockDialogPage();});
109document.querySelector('.close').onclick=closeDialogFromPointer;
110dialog.addEventListener('click',event=>{if(event.target===dialog){const r=dialog.getBoundingClientRect();if(event.clientX<r.left||event.clientX>r.right||event.clientY<r.top||event.clientY>r.bottom)closeDialogFromPointer();}});
111async function api(url,options){const response=await fetch(url,options);let result;try{result=await response.json();}catch{throw new Error('The portal could not be reached. Please try again.');}if(!response.ok)throw new Error(result.message||'Please try again.');return result;}
112// Analytics contain only event categories and public design IDs, never form contents.
113const trackedAnalytics=new Set();
114function trackAnalytics(type,target='',onceKey=''){
115  if(demo||window.tattSafePreview||!profile||navigator.webdriver)return;
116  if(onceKey&&trackedAnalytics.has(onceKey))return;
117  if(onceKey)trackedAnalytics.add(onceKey);
118  try {
119    const body=JSON.stringify({id:crypto.randomUUID(),type,target});
120    fetch(`/api/profiles/${encodeURIComponent(profile.username.toLowerCase())}/analytics`,{
121      method:'POST',headers:{'content-type':'application/json'},body,keepalive:true
122    }).catch(()=>{});
123  }catch{} // Tracking must never interrupt navigation or booking.
124}
125document.addEventListener('click',event=>{
126  const link=event.target.closest?.('a');if(!link)return;
127  let type;
128  if(link.matches('.contact-feature'))type=link.querySelector('strong')?.textContent;
129  else if(link.closest('.contact-socials'))type=link.getAttribute('aria-label');
130  else if(link.matches('.contact-map')||link.closest('.contact-shop'))type='Directions';
131  else if(link.closest('.contact-reviews'))type='Google review';
132  if(type)trackAnalytics('contact',type);
133});
134function profileEventID(hash){
135 const match=/^#event\/([a-zA-Z0-9_-]{1,180})$/.exec(hash);
136 return match?match[1]:null;
137}
138function eventArtistMarkup(artist,eventID){
139  const photo=artist.image?`<img class="event-artist-avatar" src="${escape(artist.image)}" alt="" loading="lazy">`:`<span class="event-artist-avatar event-artist-initial" aria-hidden="true">${escape((artist.name||artist.username||'?').slice(0,1).toUpperCase())}</span>`;
140  const destination=artist.isGuest?artist.websiteURL:artist.portalURL?`${artist.portalURL}#portfolio`:null;
141  const avatar=destination?`<a class="event-artist-photo-link" href="${escape(destination)}" ${artist.isGuest?'target="_blank" rel="noopener noreferrer"':''} aria-label="View ${escape(artist.name)}’s ${artist.isGuest?'profile':'portfolio'}">${photo}</a>`:photo;
142  return `<div class="event-artist-card">${avatar}<strong>${escape(artist.name)}</strong><span>@${escape(artist.username)}</span></div>`;
143}
144async function load(){
145  try {
146    if(artistUsername==='events'&&path.length===2){await loadEventPage(path[1]);return;}
147    if(!artistUsername){app.innerHTML='<div class="message"><h1>Your artist. Your next tattoo.</h1><p>Open the profile link shared by your artist to view their work and request a date.</p></div>';return;}
148    if(path.length!==1||!/^[a-z0-9][a-z0-9_.-]{2,39}$/i.test(artistUsername))throw new Error('This artist link is not valid. Please check the link your artist shared.');
149    const initial=document.querySelector('#initial-profile');
150    profile=demo?demoProfile():initial?JSON.parse(initial.textContent):await api(`/api/profiles/${encodeURIComponent(artistUsername.toLowerCase())}`);
151    document.title=`${profile.name||profile.username} | Tattoo Artist${[profile.shop?.city,profile.shop?.state].filter(Boolean).length?' in '+[profile.shop.city,profile.shop.state].filter(Boolean).join(', '):''} | TattSafe`;
152    const hash=profileEventID(location.hash)?'event':location.hash.slice(1);activeTab=profile.tabs.includes(hash)?hash:(profile.tabs.includes(profile.defaultTab)?profile.defaultTab:(profile.tabs.includes('portfolio')?'portfolio':profile.tabs[0]));
153    trackAnalytics('visit','','visit');
154    installPortalShare();renderProfile();registerAgentTools();if(activeTab==='book')refreshVisibleAvailability();
155    // Let the initial view paint and its visible images start first.
156    setTimeout(warmProfileTabs,600);
157  }catch(error){app.innerHTML=`<div class="message"><h1>Profile unavailable</h1><p>${escape(error.message)}</p><button class="secondary" id="retry">Try again</button></div>`;document.querySelector('#retry').onclick=load;}
158  finally{app.setAttribute('aria-busy','false');}
159}
160function renderProfile(){
161  const tabOrder=['flash','portfolio','event','contact','book'];
162  profile.tabs.sort((a,b)=>tabOrder.indexOf(a)-tabOrder.indexOf(b));
163  tabPanels.clear();
164  app.innerHTML=`${demo?'<div class="preview-note">Local preview · Example availability. Booking requests are disabled here.</div>':''}${profile.banner?`<div class="profile-banner"><img src="${escape(profile.banner)}" alt="" fetchpriority="high"></div>`:''}<section class="identity">${profile.image?`<img class="avatar" src="${escape(profile.image)}" alt="${escape(profile.name)}">`:`<div class="avatar empty" aria-hidden="true">${escape((profile.name||profile.username)[0]?.toUpperCase())}</div>`}<div><h1>${escape(profile.name||profile.username)}</h1><p class="username">@${escape(profile.username)}</p>${profile.shop?`<p class="artist-location">${escape([profile.shop.title,[profile.shop.city,profile.shop.state].filter(Boolean).join(', ')].filter(Boolean).join(' · '))}</p>`:''}${profile.bio?`<p class="bio">${escape(profile.bio)}</p>`:''}</div></section><nav class="tabs" role="tablist" aria-label="Artist profile">${profile.tabs.map(tab=>`<button role="tab" id="tab-${tab}" aria-controls="panel-${tab}" aria-selected="${tab===activeTab}" tabindex="${tab===activeTab?0:-1}" data-tab="${tab}">${labels[tab]}</button>`).join('')}</nav><div id="content"></div>`;
165  const avatar=document.querySelector('.avatar'),identityCopy=document.querySelector('.identity>div:last-child');
166  const sizeAvatar=()=>{const width=avatar.getBoundingClientRect().width;avatar.style.height=`${Math.max(width*1.25,Math.min(identityCopy.scrollHeight,width*1.5))}px`;};
167  new ResizeObserver(sizeAvatar).observe(identityCopy);sizeAvatar();
168  document.querySelectorAll('[data-tab]').forEach(button=>{button.onclick=()=>selectTab(button.dataset.tab);button.onkeydown=event=>{if(!['ArrowLeft','ArrowRight','Home','End'].includes(event.key))return;event.preventDefault();const i=profile.tabs.indexOf(activeTab),next=event.key==='Home'?0:event.key==='End'?profile.tabs.length-1:(i+(event.key==='ArrowRight'?1:-1)+profile.tabs.length)%profile.tabs.length;selectTab(profile.tabs[next]);document.querySelector(`#tab-${activeTab}`).focus();};});
169  renderTab();
170}
171let availabilityRequest;
172async function refreshAvailability(){
173  if(demo)return;
174  if(availabilityRequest)return availabilityRequest;
175  availabilityRequest=(async()=>{
176    const latest=await api(`/api/profiles/${encodeURIComponent(artistUsername.toLowerCase())}/availability`,{cache:'no-store'});
177    const changed=JSON.stringify(profile.slots)!==JSON.stringify(latest.slots)||profile.timezone!==latest.timezone;
178    profile.slots=latest.slots;profile.timezone=latest.timezone;
179    if(changed){
180      if(!profile.slots.some(slot=>dayKey(slot.start)===selectedDay)){selectedDay=profile.slots.length?dayKey(profile.slots[0].start):null;displayMonth=selectedDay?.slice(0,7);}
181      const panel=tabPanels.get('book');if(panel?.dataset.ready==='true')renderBooking(panel);
182      const calendar=detail.querySelector('#flash-calendar');
182if(dialog.open&&calendar)renderBooking(calendar,true);
183    }
184  })();
185  try{await availabilityRequest;}finally{availabilityRequest=null;}
186}
187async function refreshVisibleAvailability(){
188  if(!profile||document.visibilityState==='hidden'||(activeTab!=='book'&&!dialog.open))return;
189  try{await refreshAvailability();document.querySelector('#availability-error')?.remove();}
190  catch{
191    const panel=tabPanels.get('book');
192    if(panel&&!panel.querySelector('#availability-error'))panel.insertAdjacentHTML('afterbegin','<p class="note" id="availability-error" role="status">Unable to refresh availability. Reconnecting… Dates will be checked again before you book.</p>');
193  }
194}
195window.addEventListener('pageshow',refreshVisibleAvailability);
196window.addEventListener('focus',refreshVisibleAvailability);
197document.addEventListener('visibilitychange',refreshVisibleAvailability);
198setInterval(refreshVisibleAvailability,30000);
199function selectTab(tab){if(tab==='event'){const panel=tabPanels.get('event');if(panel?.dataset.eventID){delete panel.dataset.ready;delete panel.dataset.loading;panel.dataset.request=String(Number(panel.dataset.request||0)+1);}}activeTab=tab;selectedFlash=null;history.replaceState(null,'',`#${tab}`);document.querySelectorAll('[data-tab]').forEach(b=>{b.setAttribute('aria-selected',String(b.dataset.tab===tab));b.tabIndex=b.dataset.tab===tab?0:-1;});renderTab().then(()=>{if(tab==='book')refreshVisibleAvailability();});}
200async function renderTab(){
201  const tab=activeTab,container=document.querySelector('#content');
202  if(!tab){container.innerHTML='<p class="empty-state">This artist hasn’t shared any sections yet.</p>';return;}
203  let content=tabPanels.get(tab);
204  if(!content){
205    content=document.createElement('section');
206    content.id=`panel-${tab}`;
207    content.setAttribute('role','tabpanel');
208    content.setAttribute('aria-labelledby',`tab-${tab}`);
209    content.tabIndex=0;
210    container.append(content);
211    tabPanels.set(tab,content);
212  }
213  for(const [name,panel] of tabPanels)panel.hidden=name!==tab;
214  // Keep loaded image elements mounted when another tab is shown.
215  if(content.dataset.ready==='true'||content.dataset.loading==='true')return;
216  if(profile.deferred && !(profile.loadedTabs||['contact']).includes(tab)) {
217    content.dataset.loading='true';
218    content.innerHTML='<p class="message" role="status">Loading this section…</p>';
219    try {
220      fullProfileRequest??=api(`/api/profiles/${encodeURIComponent(artistUsername.toLowerCase())}`);
221      profile=await fullProfileRequest;
222      registerAgentTools();
223    } catch(error) {
224      fullProfileRequest=null;
225      content.innerHTML=`<p class="message">${escape(error.message)}</p><button class="secondary">Try again</button>`;
226      content.querySelector('button').onclick=()=>renderTab();
227      return;
228    } finally {
229      delete content.dataset.loading;
230    }
231  }
232  if(tab==='event'){await renderProfileEvents(content);return;}
233  if(tab==='flash')renderFlash(content);
234  if(tab==='portfolio')renderPortfolio(content);
235  if(tab==='contact')renderContact(content);
236  if(tab==='book')renderBooking(content);
237  content.dataset.ready='true';
238}
239
240// Warm only the first gallery page, with bounded image requests so the visible tab wins.
241async function warmProfileTabs(){
242 try{
243  if(profile.deferred){
244   fullProfileRequest??=api(`/api/profiles/${encodeURIComponent(artistUsername.toLowerCase())}`);
245   profile=await fullProfileRequest;
246   registerAgentTools();
247  }
248  const tabs=activeTab==='portfolio'?['portfolio','flash']:['flash','portfolio'];
249  const groups={flash:(profile.flash||[]).slice(0,12).map(item=>item.preview||item.image),portfolio:(profile.portfolio||[]).slice(0,12).map(item=>item.preview||item.image),event:(profile.events||[]).slice(0,12).map(item=>item.coverImage),contact:[contactMapURL(profile.shop)]};
250  const order=[activeTab,...['event','contact',...tabs].filter(tab=>tab!==activeTab)];
251  const urls=[...new Set(Array.from({length:12},(_,i)=>order.map(tab=>groups[tab]?.[i])).flat().filter(Boolean))];
252  let next=0;
253  await Promise.all(Array.from({length:4},async()=>{
254   while(next<urls.length){
255    const url=urls[next++];
256    await new Promise(resolve=>{const image=new Image();const timer=setTimeout(resolve,10000);image.onload=image.onerror=()=>{clearTimeout(timer);resolve();};image.fetchPriority='low';image.src=url;});
257   }
258  }));
259 }catch{fullProfileRequest=null;} // A tab can retry normally if background loading fails.
260}
261// Append pages rather than rebuilding existing images; retain a keyboard-accessible fallback.
262function paginateGallery(content,items,markup,bind){
263 content.galleryObserver?.disconnect();
264 const grid=content.querySelector('.grid');
265 if(!grid)return;
266 let count=Math.min(12,items.length);
267 bind();
268 if(count===items.length)return;
269 const more=document.createElement('button');
270 more.type='button';more.className='secondary gallery-more';more.textContent='Load more';
271 grid.after(more);
272 const append=()=>{
273  const end=Math.min(count+12,items.length);
274  grid.insertAdjacentHTML('beforeend',items.slice(count,end).map((item,index)=>markup(item,count+index)).join(''));
275  count=end;bind();
276  if(count===items.length){content.galleryObserver?.disconnect();more.remove();}
277 };
278 more.onclick=append;
279 if('IntersectionObserver' in window){
280  content.galleryObserver=new IntersectionObserver(entries=>{
281   if(entries.some(entry=>entry.isIntersecting)&&!content.hidden)append();
282  },{rootMargin:'400px'});
283  content.galleryObserver.observe(more);
284 }
285}
286function collapseFlashStyles(target){
287 document.querySelectorAll('.flash-style-filter[open]').forEach(menu=>{
288  if(!menu.contains(target))menu.open=false;
289 });
290}
291document.addEventListener('pointerdown',event=>collapseFlashStyles(event.target),true);
292document.addEventListener('keydown',event=>{
293 if(event.key==='Escape')document.querySelectorAll('.flash-style-filter[open]').forEach(menu=>{menu.open=false;menu.querySelector('summary')?.focus();});
294});
295function filteredFlashItems(flash,styles){
296 return flash.filter(item=>!styles.size||(item.styles||[]).some(style=>styles.has(style)));
297}
298function renderFlash(content,sort='preferred',selectedStyles=new Set(),filtersOpen=false){
299  const styles=[...new Set(profile.flash.flatMap(item=>item.styles||[]))].sort((a,b)=>a.localeCompare(b));
300  const items=filteredFlashItems(profile.flash,selectedStyles);
301  if(sort==='low')items.sort((a,b)=>a.total-b.total);
302  if(sort==='high')items.sort((a,b)=>b.total-a.total);
303  if(sort==='title')items.sort((a,b)=>a.title.localeCompare(b.title));
304  content.galleryObserver?.disconnect();
305  const flashCard=(flash,i)=>`<button class="card" data-flash="${i}" aria-label="${escape(flash.title||'Flash')} · ${escape(money(flash.total))}">${(flash.preview||flash.image)?`<img src="${escape(flash.preview||flash.image)}" alt="${escape(flash.title)}" loading="lazy">`:'<div class="art-empty">Image unavailable</div>'}<div class="card-body"><span class="price">${money(flash.total)}</span></div></button>`;
306  const markup=`${profile.flash.length?`<div class="flash-controls">${styles.length?`<details class="flash-style-filter" ${filtersOpen?'open':''}><summary><span>Styles: ${selectedStyles.size?`${selectedStyles.size} selected`:'All'}</span></summary><div class="flash-style-options"><button type="button" id="clear-flash-styles" aria-pressed="${!selectedStyles.size}">All Styles</button>${styles.map((style,i)=>`<button type="button" data-flash-style="${i}" aria-pressed="${selectedStyles.has(style)}">${escape(style)}</button>`).join('')}</div></details>`:''}<label class="flash-sort-control"><span class="flash-sort-label">Sort:</span><select id="flash-sort" aria-label="Sort flash"><option value="preferred">Artist Preferred</option><option value="title">Title A–Z</option><option value="low">Price: Low to High</option><option value="high">Price: High to Low</option></select></label></div>${!items.length?'<p class="empty-state">No designs match these styles. Choose another style or All Styles.</p>':''}
306<div class="grid flash-grid">${items.slice(0,12).map(flashCard).join('')}</div>`:'<p class="empty-state">No flash is available right now. Check back for new designs.</p>'}`;
307  const controls=content.querySelector('.flash-controls');
308  if(controls){
309    // Keep the tapped controls mounted so Safari cannot move focus to the page
310    // or close the menu while the filtered gallery is being refreshed.
311    const updated=document.createElement('div');updated.innerHTML=markup;
312    updated.querySelector('.flash-controls')?.remove();
313    for(const child of [...content.children])if(child!==controls)child.remove();
314    content.append(...updated.childNodes);
315    const menu=controls.querySelector('.flash-style-filter');
316    if(menu){menu.open=filtersOpen;menu.querySelector('summary span').textContent=`Styles: ${selectedStyles.size?`${selectedStyles.size} selected`:'All'}`;}
317    controls.querySelectorAll('[data-flash-style]').forEach(button=>button.setAttribute('aria-pressed',String(selectedStyles.has(styles[Number(button.dataset.flashStyle)]))));
318    controls.querySelector('#clear-flash-styles')?.setAttribute('aria-pressed',String(!selectedStyles.size));
319  }else content.innerHTML=markup;
320  paginateGallery(content,items,flashCard,()=>content.querySelectorAll('[data-flash]').forEach(b=>b.onclick=()=>flashDetail(items[Number(b.dataset.flash)])));
321  const picker=content.querySelector('#flash-sort');if(picker){picker.value=sort;picker.onchange=()=>renderFlash(content,picker.value,selectedStyles,content.querySelector('.flash-style-filter')?.open);}
322  content.querySelectorAll('[data-flash-style]').forEach(button=>button.onclick=()=>{
323    const style=styles[Number(button.dataset.flashStyle)],next=new Set(selectedStyles);
324    if(next.has(style))next.delete(style);else next.add(style);
325    renderFlash(content,sort,next,true);
326    content.querySelector(`[data-flash-style="${button.dataset.flashStyle}"]`)?.focus({preventScroll:true});
327  });
328  const clear=content.querySelector('#clear-flash-styles');if(clear)clear.onclick=()=>renderFlash(content,sort,new Set(),true);
329
330}
331function flashDetail(flash){
332  trackAnalytics('flash_view',flash.id,`flash:${flash.id}`);
333  showDialog(`${flash.image?`<img class="detail-image" src="${escape(flash.image)}" alt="${escape(flash.title)}">`:''}<h2 id="dialog-title">${escape(flash.title||'Flash')}</h2>${flash.detail?.trim()?`<p class="detail-copy">${escape(flash.detail.trim())}</p>`:''}<div class="flash-price-breakdown" aria-label="Price breakdown"><div class="flash-price-row"><span aria-hidden="true"></span><span>Deposit <small>Due after approval</small></span><strong>${money(flash.deposit)}</strong></div><div class="flash-price-row"><span aria-hidden="true">+</span><span>Remaining balance <small>Due when your tattoo is finished</small></span><strong>${money((Math.round(flash.total*100)-Math.round(flash.deposit*100))/100)}</strong></div><div class="flash-price-row flash-price-total"><span aria-hidden="true">=</span><span>Total price</span><strong>${money(flash.total)}</strong></div></div><p class="note">Your deposit counts toward the total price.</p>${flashPlacementSummary(flash)}<p class="note">Send a request to your artist. Your appointment is confirmed after they respond. No payment is collected here.</p>${profile.slots.length?'<button class="primary full" id="choose-flash-date">Choose a date</button>':'<p class="empty-state">No availability posted right now.</p>'}`);
334  installFlashScrollHint();
335  const choose=document.querySelector('#choose-flash-date');
335if(choose)choose.onclick=()=>{selectedFlash=flash;showDialog('<h2 id="dialog-title">Choose a date</h2><p class="meta">'+escape(flash.title)+'</p><div id="flash-calendar"></div>');renderBooking(document.querySelector('#flash-calendar'),true);};
336}
337function renderPortfolio(content){content.galleryObserver?.disconnect();const photoCard=(item,i)=>`<button class="card" data-photo="${i}" aria-label="View tattoo ${i+1}">${(item.preview||item.image)?`<img src="${escape(item.preview||item.image)}" alt="${escape(item.styles.join(', ')||'Tattoo portfolio')}" loading="lazy">`:'<span class="art-empty">Image unavailable</span>'}</button>`;content.innerHTML=`${profile.portfolio.length?`<div class="grid portfolio-grid">${profile.portfolio.slice(0,12).map(photoCard).join('')}</div>`:'<p class="empty-state">No portfolio images have been shared yet.</p>'}`;paginateGallery(content,profile.portfolio,photoCard,()=>content.querySelectorAll('[data-photo]').forEach(b=>b.onclick=()=>{const item=profile.portfolio[Number(b.dataset.photo)];showPortfolioPhoto(item);}));}
338function showPortfolioPhoto(item){
339  const photos=profile.portfolio?.includes(item)?profile.portfolio:[item];
340  let index=Math.max(0,photos.indexOf(item)),touch=null,pinching=false;
341  const warmed=new Set();
342  showDialog(`<section class="portfolio-lightbox"><h2 id="dialog-title">Portfolio</h2><div class="photo-viewer" aria-busy="true"><div class="photo-status" role="status"><span class="photo-spinner" aria-hidden="true"></span><span>Loading photo…</span></div><img class="detail-image" alt="Tattoo portfolio" draggable="false" hidden><button class="secondary photo-retry" hidden>Try again</button></div><nav class="photo-navigation" aria-label="Portfolio photos"${photos.length<2?' hidden':''}><button class="secondary photo-previous" aria-label="Previous photo">‹</button><span class="photo-counter" role="status" aria-live="polite" aria-atomic="true"></span><button class="secondary photo-next" aria-label="Next photo">›</button></nav><p class="photo-swipe-hint meta"${photos.length<2?' hidden':''}>Swipe left or right to browse</p><div class="meta photo-styles"></div></section>`);
343  const root=detail.querySelector('.portfolio-lightbox'),viewer=root.querySelector('.photo-viewer'),photo=viewer.querySelector('img'),status=viewer.querySelector('.photo-status'),retry=viewer.querySelector('button');
344  const previous=root.querySelector('.photo-previous'),next=root.querySelector('.photo-next'),counter=root.querySelector('.photo-counter'),styles=root.querySelector('.photo-styles');
345  const load=()=>{
346    const selected=photos[index];
347    viewer.setAttribute('aria-busy','true');photo.hidden=true;retry.hidden=true;status.hidden=false;
348    counter.textContent=`${index+1} of ${photos.length}`;previous.disabled=index===0;next.disabled=index===photos.length-1;
349    photo.alt=`Tattoo portfolio photo ${index+1} of ${photos.length}`;
350    styles.innerHTML=(selected.styles||[]).map(style=>`<div>${escape(style)}</div>`).join('');
351    status.innerHTML='<span class="photo-spinner" aria-hidden="true"></span><span>Loading photo…</span>';
352    photo.onload=()=>{viewer.setAttribute('aria-busy','false');status.hidden=true;photo.hidden=false;};
353    photo.onerror=()=>{viewer.setAttribute('aria-busy','false');status.textContent='This photo couldn’t load. Please try again.';retry.hidden=false;};
354    const url=selected.image||selected.preview;
355    if(url){photo.src=url;}else{photo.removeAttribute('src');photo.onerror();retry.hidden=true;status.textContent='Photo unavailable.';}
356    for(const neighbor of [photos[index-1],photos[index+1]]){const src=neighbor?.image||neighbor?.preview;if(src&&!warmed.has(src)){warmed.add(src);const image=new Image();image.decoding='async';image.src=src;}}
357  };
358  const navigate=delta=>{const target=index+delta;if(target<0||target>=photos.length)return;index=target;load();trackAnalytics('portfolio_view',photos[index].id,`portfolio:${photos[index].id}`);};
359  previous.onclick=()=>navigate(-1);next.onclick=()=>navigate(1);retry.onclick=load;
360  root.addEventListener('keydown',event=>{if(event.key==='ArrowLeft'||event.key==='ArrowRight'){event.preventDefault();navigate(event.key==='ArrowLeft'?-1:1);}});
361  viewer.addEventListener('touchstart',event=>{if(event.touches.length!==1){touch=null;pinching=true;return;}if(!pinching){const t=event.touches[0];touch={x:t.clientX,y:t.clientY};}},{passive:true});
362  viewer.addEventListener('touchend',event=>{if(event.touches.length)return;const start=touch;touch=null;const ignore=pinching;pinching=false;if(ignore||!start||event.changedTouches.length!==1||(window.visualVie
362wport?.scale||1)>1.05)return;const t=event.changedTouches[0],dx=t.clientX-start.x,dy=t.clientY-start.y;if(Math.abs(dx)>=55&&Math.abs(dx)>Math.abs(dy)*1.5)navigate(dx<0?1:-1);},{passive:true});
363  viewer.addEventListener('touchcancel',()=>{touch=null;pinching=false;},{passive:true});
364  trackAnalytics('portfolio_view',item.id,`portfolio:${item.id}`);load();
365}
366
367function renderContact(content){content.innerHTML=renderContactMarkup(profile);}
368
369function matchesBookingWeekday(date,weekdays){
370  return weekdays.size===0||weekdays.has(new Date(`${date}T12:00:00Z`).getUTCDay());
371}
372function renderBooking(content,compact=false){
373  if(!profile.slots.length){content.innerHTML='<p class="empty-state">No availability posted. Check back for new dates.</p>';return;}
374  selectedDay??=dayKey(profile.slots[0].start);displayMonth??=selectedDay.slice(0,7);
375  const [year,month]=displayMonth.split('-').map(Number),first=new Date(Date.UTC(year,month-1,1)),count=new Date(Date.UTC(year,month,0)).getUTCDate();
376  const dates=new Set(profile.slots.map(s=>dayKey(s.start))),selected=profile.slots.filter(s=>dayKey(s.start)===selectedDay);
377  const monthTitle=new Intl.DateTimeFormat('en-US',{month:'long',year:'numeric',timeZone:'UTC'}).format(first);
378  const switcher=compact?'':`<div class="booking-switch" role="tablist" aria-label="Availability view"><button role="tab" data-booking-view="calendar" aria-selected="${bookingView==='calendar'}">Calendar</button><button role="tab" data-booking-view="list" aria-selected="${bookingView==='list'}">List</button></div>`;
379  const calendarView=`<div class="booking-layout"><div class="calendar"><div class="calendar-header"><button id="prev-month" aria-label="Previous month">‹</button><strong>${monthTitle}</strong><button id="next-month" aria-label="Next month">›</button></div><div class="days">${['Sun','Mon','Tue','Wed','Thu','Fri','Sat'].map(d=>`<span class="day-name" aria-hidden="true">${d}</span>`).join('')}${'<span></span>'.repeat(first.getUTCDay())}${Array.from({length:count},(_,i)=>{const date=`${displayMonth}-${String(i+1).padStart(2,'0')}`,available=dates.has(date);return `<button class="day ${available?'available':''} ${date===selectedDay?'selected':''}" ${available?'':'disabled'} data-day="${date}" aria-pressed="${date===selectedDay}" aria-label="${monthTitle} ${i+1}${available?', available':''}"><span class="day-number">${i+1}</span></button>`;}).join('')}</div></div><div class="slots"><h3>${dateLabel(`${selectedDay}T12:00:00Z`,{weekday:'long',year:'numeric',month:'long',day:'numeric',timeZone:'UTC'})}</h3>${selected.map((slot,i)=>`<button class="slot" data-slot="${i}"><span>${dateLabel(slot.start,{hour:'numeric',minute:'2-digit'})}–${dateLabel(slot.end,{hour:'numeric',minute:'2-digit'})}</span><span>Request →</span></button>`).join('')||'<p class="note">Select an available day.</p>'}</div></div>`;
380  const weekdayNames=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
381  const filteredDates=[...dates].filter(date=>matchesBookingWeekday(date,bookingWeekdays));
382  const weekdayPicker=`<div class="weekday-filter" role="group" aria-label="Filter availability by weekday">${weekdayNames.map((name,i)=>`<button type="button" data-weekday="${i}" aria-label="${name}" aria-pressed="${bookingWeekdays.has(i)}"><span class="weekday-label">${name.slice(0,3)}</span></button>`).join('')}</div>`;
383  const listView=`${weekdayPicker}<div class="booking-list">${filteredDates.map(date=>`<section><h3>${dateLabel(`${date}T12:00:00Z`,{weekday:'long',year:'numeric',month:'long',day:'numeric',timeZone:'UTC'})}</h3>${profile.slots.map((slot,i)=>dayKey(slot.start)===date?`<button class="slot" data-all-slot="${i}"><span>${dateLabel(slot.start,{hour:'numeric',minute:'2-digit'})}–${dateLabel(slot.end,{hour:'numeric',minute:'2-digit'})}</span><span>Request →</span></button>`:'').join('')}</section>`).join('')||`<p class="empty-state">No availability on the selected weekdays. Choose other days or deselect them to show all dates.</p>`}</div>`;
384  content.innerHTML=`${switcher}${compact||bookingView==='calendar'?calendarView:listView}`;
385  content.querySelectorAll('[data-weekday]').forEach(button=>button.onclick=()=>{
386    const day=Number(button.dataset.weekday);
387    if(bookingWeekdays.has(day))bookingWeekdays.delete(day);else bookingWeekdays.add(day);
388    renderBooking(content,compact);
389    content.querySelector(`[data-weekday="${day}"]`)?.focus({preventScroll:true});
390  });
391  const shift=delta=>{const next=new Date(Date.UTC(year,month-1+delta,1));displayMonth=`${next.getUTCFullYear()}-${String(next.getUTCMonth()+1).padStart(2,'0')}`;const candidate=[...dates].find(d=>d.startsWith(displayMonth));selectedDay=candidate||`${displayMonth}-01`;renderBooking(content,compact);};
392  const minimum=dayKey(new Date()).slice(0,7),maximum=dayKey(profile.slots.at(-1).start).slice(0,7);
393  const previous=content.querySelector('#prev-month'),next=content.querySelector('#next-month');if(previous&&next){previous.disabled=displayMonth<=minimum;next.disabled=displayMonth>=maximum;previous.onclick=()=>shift(-1);next.onclick=()=>shift(1);}
394  content.querySelectorAll('[data-booking-view]').forEach(b=>b.onclick=()=>{bookingView=b.dataset.bookingView;renderBooking(content,compact);});
395  content.querySelectorAll('[data-day]').forEach(b=>b.onclick=()=>{selectedDay=b.dataset.day;renderBooking(content,compact);});
396  content.querySelectorAll('[data-slot]').forEach(b=>b.onclick=()=>bookingForm(selected[Number(b.dataset.slot)],selectedFlash));
397  content.querySelectorAll('[data-all-slot]').forEach(b=>b.onclick=()=>bookingForm(profile.slots[Number(b.dataset.allSlot)],selectedFlash));
398}
399async function bookingImage(file){
400  if(!file.type.startsWith('image/'))throw new Error('Choose an image file.');
401  const bitmap=await createImageBitmap(file),scale=Math.min(1,900/Math.max(bitmap.width,bitmap.height)),canvas=document.createElement('canvas');
402  canvas.width=Math.round(bitmap.width*scale);canvas.height=Math.round(bitmap.height*scale);canvas.getContext('2d').drawImage(bitmap,0,0,canvas.width,canvas.height);bitmap.close();
403  for(const quality of [.78,.68,.58,.48,.38]){const blob=await new Promise(resolve=>canvas.toBlob(resolve,'image/jpeg',quality));if(blob&&blob.size<=90000)return await new Promise((resolve,reject)=>{const reader=new FileReader();reader.onload=()=>resolve(reader.result);reader.onerror=reject;reader.readAsDataURL(blob);});}
404  throw new Error('One of the images is too large. Try a smaller image.');
405}
406function formatBookingPhone(value){
407  const raw=String(value??'');
408  const digits=raw.replace(/\D/g,'');
409  // Leave international numbers and extensions intact.
410  if(/[a-z#]/i.test(raw)||(raw.trim().startsWith('+')&&!raw.trim().startsWith('+1'))||digits.length>11||(digits.length===11&&!digits.startsWith('1')))return raw;
411  const country=digits.startsWith('1')&&(raw.trim().startsWith('+1')||digits.length===11);
412  const local=country?digits.slice(1):digits;
413  const formatted=local.length<=3?local:local.length<=6?`(${local.slice(0,3)}) ${local.slice(3)}`:`(${local.slice(0,3)}) ${local.slice(3,6)}-${local.slice(6)}`;
414  return (country?'+1 ':'')+formatted;
415}
416function formatBookingPhoneInput(input){
417  const raw=input.value,position=input.selectionStart??raw.length;
418  const count=raw.slice(0,position).replace(/\D/g,'').length;
419  const formatted=formatBookingPhone(raw);
420  if(formatted===raw)return;
421  input.value=formatted;
422  let cursor=0,seen=0;
423  while(cursor<formatted.length&&seen<count){if(/\d/.test(formatted[cursor]))seen++;cursor++;}
424  if(position===raw.length)cursor=formatted.length;
425  input.setSelectionRange(cursor,cursor);
426}
427function bookingSocial(social, platform){
428  if(!social)return {socialPlatform:null,socialURL:null};
429  const hosts={Instagram:['instagram.com'],TikTok:['tiktok.com'],Facebook:['facebook.com'],X:['x.com','twitter.com']};
430  const label=Object.keys(hosts).find(p=>p.toLowerCase()===String(platform||'').toLowerCase());
431  if(platform&&!label)throw new Error('Choose Instagram, TikTok, Facebook, or X.');
432  if(!label)return {socialPlatform:null,socialURL:null}; // Older clients did not provide a platform.
433  let url;
434  if(/^https?:\/\//i.test(social)){
435    try{url=new URL(social);}catch{throw new Error('Enter a valid social profile link.');}
436    const host=url.hostname.toLowerCase();
437    if(url.username||url.password||!hosts[label].some(h=>host===h||host==='www.'+h||host==='m.'+h))throw new Error('The social link must match the selected platform.');
438    url.protocol='https:';
439    if(url.pathname==='/')throw new Error('Enter your profile link, not just the platform website.');
440  }else{
441    const handle=social.replace(/^@/,'');
442    if(!/^[a-zA-Z0-9_.-]+$/.test(handle))throw new Error('Enter a social username or full profile link.');
443    url=new URL('https://'+hosts[label][0]+'/'+(label==='TikTok'?'@':'')+encodeURIComponent(handle));
444  }
445  return {socialPlatform:label,socialURL:url.href};
446}
447
448function setupBookingSocialFields(form,usernameField){
449  const platform=form.elements.socialPlatform,username=form.elements.social;
450  const update=()=>{
451    const visible=Boolean(platform.value);
452    usernameField.hidden=!visible;
453    username.disabled=!visible;
454  };
455  platform.addEventListener('change',update);
456  update();
457}
458
459async function bookingForm(slot,flash,values={}){
460  if(!demo){
461    showDialog('<h2 id="dialog-title">Checking availability…</h2><p class="note" role="status">Confirming this date is still available.</p>');
462    try{
463      await refreshAvailability();
464      if(!profile.slots.some(current=>current.id===slot.id)){
465        showDialog('<h2 id="dialog-title">Date no longer available</h2><p>This time has been removed. Please choose another date.</p>');return;
466      }
467    }catch{showDialog('<h2 id="dialog-title">Couldn’t check availability</h2><p>Please close this window and try again when you’re connected.</p>');return;}
468    if(!dialog.open)return;
469  }
470
471  const requestId=values.requestId||crypto.randomUUID();
472  trackAnalytics('booking_start','',`booking:${requestId}`);
473  showDialog(`<h2 id="dialog-title">${flash?'Request this flash':'Tell us about your tattoo'}</h2><p class="meta">${escape(dateLabel(slot.start))} · ${escape(dateLabel(slot.start,{hour:'numeric',minute:'2-digit'}))}${flash?`<br>${escape(flash.title)} · ${money(flash.total)}`:''}</p><form id="booking-form"><label class="form-field">Your name<input name="name" autocomplete="name" maxlength="100" required value="${escape(values.name)}"></label><div class="form-grid"><label class="form-field">Email<input name="email" type="email" autocomplete="email" maxlength="254" value="${escape(values.email)}"></label><label class="form-field">Phone<input name="phone" type="tel" inputmode="tel" placeholder="(417) 986-6110" autocomplete="tel" maxlength="40" value="${escape(values.phone)}"></label></div><div class="booking-social-fields"><label class="form-field">Social platform<select name="socialPlatform"><option value="">Choose platform</option>${['Instagram','TikTok','Facebook','X'].map(p=>`<option value="${p}" ${values.socialPlatform===p?'selected':''}>${p}</option>`).join('')}</select></label><label class="form-field" id="social-username-field" hidden>Username<input name="social" disabled maxlength="100" autocapitalize="none" autocorrect="off" spellcheck="false" autocomplete="username" placeholder="@yourname" value="${escape(values.social)}"></label></div><p class="note">Add at least one contact method so your artist can reply.</p>${!flash?`<label class="form-field">Your tattoo idea<textarea name="idea" required maxlength="3000">${escape(values.idea)}</textarea></label>`:''}<div class="form-grid"><label class="form-field">Placement region<select name="placementRegion" required><option value="">Choose region</option>${Object.keys(placementOptions).filter(region=>!flash||!flash.placements.length||flash.placements.includes('Anywhere')||flash.placements.includes(region)).map(region=>`<option value="${escape(region)}" ${values.placementRegion===region?'selected':''}>${escape(region)}</option>`).join('')}</select></label><label class="form-field" id="placement-area-field" hidden>Placement area<select name="placementArea"><option value="">General</option></select></label><label class="form-field">Approximate size (optional)<input name="size" maxlength="100" placeholder="e.g. 3 × 4 inches" value="${escape(values.size)}"></label></div><label class="trap" aria-hidden="true">Website<input name="website" tabindex="-1" autocomplete="off"></label>
473<p id="form-error" class="error" role="alert"></p><p class="note">Your contact information and request will be shared with ${escape(profile.name||profile.username)}. This is a request, not a confirmed appointment.</p><button class="primary full" type="submit">Review request</button></form>`);
474  const booking=document.querySelector('#booking-form'),region=booking.elements.placementRegion,area=booking.elements.placementArea;
475  setupBookingSocialFields(booking,document.querySelector('#social-username-field'));
476  const updateArea=(selected='')=>{
477    document.querySelector('#placement-area-field').hidden=!region.value;
478    const restricted=flash?.placementAreas && Object.hasOwn(flash.placementAreas,region.value);
479    area.required=Boolean(restricted);
480    area.innerHTML=(restricted?'<option value="">Choose area</option>':'<option value="">General</option>')+(restricted?flash.placementAreas[region.value]:(placementOptions[region.value]||[])).map(value=>`<option value="${escape(value)}" ${value===selected?'selected':''}>${escape(value)}</option>`).join('');
481  };
482  region.onchange=()=>updateArea();updateArea(values.placementArea);
483  const trap=document.querySelector('.trap');trap.insertAdjacentHTML('beforebegin',`${flash?`<label class="form-field">Notes / requests (optional)<textarea name="idea" maxlength="3000" placeholder="Tell your artist where you want this design and how it should fit near existing tattoos, scars, or other features.">${escape(values.idea)}</textarea></label>`:''}<label class="form-field">${flash?'Placement / reference photos (optional)':'Reference images (optional)'}<input name="images" type="file" accept="image/*" multiple><span class="meta">${flash?'Upload a photo of the body area showing where you want the design, including nearby tattoos or scars. ':''}Up to 3 images.${values.images?.length?` ${values.images.length} currently attached.`:''}</span></label>`);
484  const phoneInput=document.querySelector('#booking-form').elements.phone;
485  phoneInput.value=formatBookingPhone(phoneInput.value);
486  phoneInput.addEventListener('input',()=>formatBookingPhoneInput(phoneInput));
487  phoneInput.addEventListener('change',()=>formatBookingPhoneInput(phoneInput));
488  document.querySelector('#booking-form').onsubmit=async event=>{event.preventDefault();const form=event.currentTarget,error=document.querySelector('#form-error'),v=Object.fromEntries(new FormData(form));v.social=v.social||'';if(v.social.trim()&&!v.socialPlatform){error.textContent='Choose the social platform for your username or link.';return;}v.placement=v.placementRegion+(v.placementArea?' - '+v.placementArea:'');if(!v.email.trim()&&!v.phone.trim()&&!v.social.trim()){error.textContent='Add an email, phone number, or social handle.';return;}const files=[...form.elements.images.files];if(files.length>3){error.textContent='Attach up to 3 images.';return;}try{Object.assign(v,bookingSocial(v.social.trim(),v.socialPlatform));v.images=files.length?await Promise.all(files.map(bookingImage)):(values.images||[]);reviewBooking(slot,flash,{...v,requestId,slotId:slot.id,flashId:flash?.id??null});}catch(reason){error.textContent=reason.message||'The images could not be prepared.';}};
489}
490function reviewBooking(slot,flash,values){
491  showDialog(`<h2 id="dialog-title">Review your request</h2><dl class="review"><dt>Artist</dt><dd>${escape(profile.name||profile.username)}</dd><dt>Requested appointment</dt><dd>${escape(dateLabel(slot.start))}<br>${escape(dateLabel(slot.start,{hour:'numeric',minute:'2-digit'}))}</dd><dt>Your details</dt><dd>${escape(values.name)}<br>${[values.email,values.phone].filter(Boolean).map(escape).join('<br>')}${values.social?`<br>${values.socialURL?`<a href="${escape(values.socialURL)}" target="_blank" rel="noopener noreferrer">${escape(values.socialPlatform+': '+values.social)}</a>`:escape(values.social)}`:''}</dd><dt>${flash?'Flash':'Tattoo idea'}</dt><dd>${escape(flash?.title||values.idea)}</dd>${flash&&values.idea?.trim()?`<dt>Notes / requests</dt><dd style="white-space:pre-wrap">${escape(values.idea)}</dd>`:''}<dt>Placement and size</dt><dd>${escape(values.placement)}${values.size?` · ${escape(values.size)}`:''}</dd></dl><p class="note">Your artist will contact you after reviewing your request. No payment is collected here.</p><p id="send-error" class="error" role="alert"></p><div class="form-actions"><button class="secondary" id="edit-request">Edit</button><button class="primary" id="send-request" ${demo?'disabled':''}>${demo?'Preview only':'Send request'}</button></div>`);
492  if(values.images?.length)document.querySelector('.review').insertAdjacentHTML('afterend',`<div class="request-images">${values.images.map((image,index)=>`<img src="${image}" alt="Reference image ${index+1}">`).join('')}</div>`);
493  document.querySelector('#edit-request').onclick=()=>bookingForm(slot,flash,values);
494  document.querySelector('#send-request').onclick=async event=>{const button=event.currentTarget;button.disabled=true;button.textContent='Sending…';document.querySelector('#edit-request').disabled=true;try{await api(`/api/profiles/${encodeURIComponent(profile.username.toLowerCase())}/requests`,{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify(values)});showDialog(`<div class="success-mark" aria-hidden="true">✓</div><h2 id="dialog-title">Request sent</h2><p class="detail-copy">${escape(profile.name||profile.username)} will review your request and contact you using the details you provided.
494</p><p class="note">Your appointment is not confirmed yet.</p><button class="primary full" id="done">Done</button>`);document.querySelector('#done').onclick=closeDialogFromPointer;}catch(error){document.querySelector('#send-error').textContent=error.message;button.disabled=false;button.textContent='Try again';document.querySelector('#edit-request').disabled=false;}};
495}
496function demoProfile(){const start=new Date();start.setDate(start.getDate()+2);start.setHours(10,0,0,0);return {username:'yourusername',name:'Your artist profile',bio:'Your profile bio, portfolio, flash, and public contact details will appear here just as they do in TattSafe.',tabs:['flash','portfolio','contact','book'],image:null,banner:null,timezone:'America/Chicago',links:[],shop:null,portfolio:[],flash:[],slots:Array.from({length:8},(_,i)=>{const time=start.getTime()+i*86400000;return {id:`preview~${time}`,start:new Date(time).toISOString(),end:new Date(time+7200000).toISOString()};})};}
497let agentToolsRegistered=false;
498function registerAgentTools(){
499  if(profile.deferred)return;
500  if(agentToolsRegistered||!document.modelContext?.registerTool)return;
501  agentToolsRegistered=true;
502  const lifecycle=new AbortController();window.addEventListener('pagehide',()=>lifecycle.abort(),{once:true});
503  const tools=[{name:'read_artist_booking_options',description:'Read this artist’s public booking dates and flash options.',inputSchema:{type:'object',properties:{},additionalProperties:false},annotations:{readOnlyHint:true,untrustedContentHint:true},execute:()=>({username:profile.username,timezone:profile.timezone,slots:profile.slots,flash:profile.flash.map(({id,title,placements})=>({id,title,placements}))})},{name:'start_tattoo_booking_request',description:'Open the tattoo request form for a current slot. This does not submit a request; the client reviews and sends it in the page.',inputSchema:{type:'object',properties:{slotId:{type:'string'},flashId:{type:'string'}},required:['slotId'],additionalProperties:false},annotations:{readOnlyHint:false,untrustedContentHint:true},execute:input=>{const slot=profile.slots.find(s=>s.id===input?.slotId),flash=input?.flashId?profile.flash.find(f=>f.id===input.flashId):null;if(!slot||input?.flashId&&!flash||!flash&&!profile.tabs.includes('book'))throw new Error('Choose an available booking option.');bookingForm(slot,flash);return {opened:true,submitted:false};}}];
504  for(const tool of tools){try{Promise.resolve(document.modelContext.registerTool(tool,{signal:lifecycle.signal})).catch(()=>{});}catch{}}
505}
506// BEGIN CONFIRMATION RETURN NAVIGATION
507function confirmationPortalDestination(token,href){
508 const destination=new URL(href,location.href);
509 if(!/^[a-f0-9]{64}$/.test(token)||destination.origin!==location.origin)return href;
510 let reference=token;
511 try {
512  reference=crypto.randomUUID();
513  sessionStorage.setItem('tattsafe.confirmationReturn.'+reference,token);
514 } catch { reference=token; }
515 // The usual URL holds only a tab-local reference. Storage-restricted browsers
516 // keep the capability in the fragment, never in a server request or referrer.
517 destination.hash='appointment-return='+reference;
518 return destination.href;
519}
520function confirmationReturnToken(){
521 const reference=new URLSearchParams(location.hash.slice(1)).get('appointment-return');
522 if(!reference)return null;
523 if(/^[a-f0-9]{64}$/.test(reference))return reference;
524 if(!/^[a-f0-9-]{36}$/.test(reference))return null;
525 try {
526  const token=sessionStorage.getItem('tattsafe.confirmationReturn.'+reference);
527  return /^[a-f0-9]{64}$/.test(token||'')?token:null;
528 } catch { return null; }
529}
530function showConfirmationReturn(){
531 const token=confirmationReturnToken();
532 if(!token)return;
533 const bar=document.querySelector('.topbar');
534 if(!bar||bar.querySelector('.confirmation-return'))return;
535 const link=document.createElement('a');
536 link.className='confirmation-return';
537 link.href='/confirmation#'+token;
538 link.textContent='‹ Back to appointment';
539 bar.prepend(link);
540 bar.classList.add('has-confirmation-return');
541}
542// END CONFIRMATION RETURN NAVIGATION
543async function loadConfirmation(){
544 document.title='Your appointment · TattSafe';
545 const target=document.querySelector('#app');
546 const token=location.hash.slice(1);
547 let generation=0;
548 const render=async()=>{
549  const requestGeneration=++generation;
550  target.setAttribute('aria-busy','true');
551  try {
552   const result=await api('/api/confirmation',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({token})});
553   if(requestGeneration!==generation)return;
554   target.innerHTML=result.markup;
555   const artistLink=target.querySelector('a.confirmation-artist');
556   if(artistLink)artistLink.href=confirmationPortalDestination(token,artistLink.href);
557  } catch(error){if(requestGeneration!==generation)return;target.innerHTML='<div class="message"><h1>Confirmation unavailable</h1><p></p><button class="secondary">Try again</button></div>';target.querySelector('p').textContent=error.message;target.querySelector('button').onclick=render;}
558  target.setAttribute('aria-busy','false');
559 };
560 await render();
561 // Re-check after returning from a payment app; never retain a stale page from the back/forward cache.
562 window.addEventListener('pageshow',event=>{if(event.persisted)render();});
563 document.addEventListener('visibilitychange',()=>{if(document.visibilityState==='visible')render();});
564}
565if(location.pathname==='/confirmation')loadConfirmation();else {showConfirmationReturn();load();}
566
567// Placement summaries are display-only; booking retains the artist's exact allowed sides.
568function flashPlacementLabels(placements=[]){
569 const allowed=new Set(placements);
570 if(!allowed.size||allowed.has('Anywhere'))return ['Anywhere'];
571 const labels=[];
572 for(const region of allowed){
573  const match=/^(Arm|Leg|Hand|Foot) \((Left|Right)\)$/.exec(region);
574  let label=region;
575  if(match){
576   const part=match[1];
577   label=allowed.has(part+' (Left)')&&allowed.has(part+' (Right)')?'Either '+part.toLowerCase():match[2]+' '+part.toLowerCase();
578  }else if(region==='Torso (Front)')label='Front torso';
579  else if(region==='Torso (Back)')label='Back';
580  if(!labels.includes(label))labels.push(label);
581 }
582 return labels;
583}
584function flashPlacementSummary(flash){
585 return `<section class="flash-placement-summary">${flash.width&&flash.height?`<h3>Tattoo size</h3><p>${escape(flash.width)} × ${escape(flash.height)} inches</p>`:''}<h3>Where can this design go?</h3><ul class="flash-placement-chips">${flashPlacementLabels(flash.placements).map(label=>`<li>${escape(label)}</li>`).join('')}</ul><p class="note">Choose your preferred placement when booking.</p></section>`;
586}
587
588let flashScrollHintDismissed=false;
589function installFlashScrollHint(){
590 try{flashScrollHintDismissed ||= localStorage.getItem('flashScrollHintDismissed')==='true';}catch{}
591 if(flashScrollHintDismissed)return;
592 const hint=document.createElement('button');
593 hint.type='button';hint.className='flash-scroll-hint';hint.textContent='More details below ↓';
594 hint.setAttribute('aria-label','Scroll down for more tattoo details');
595 dialog.append(hint);
596 const startingScroll=dialog.scrollTop;
597 const dismissHint=()=>{
598  flashScrollHintDismissed=true;
599  try{localStorage.setItem('flashScrollHintDismissed','true');}catch{}
600  dialogScrollCleanup();
601 };
602 const update=()=>{
603  const atBottom=dialog.scrollHeight-dialog.clientHeight-dialog.scrollTop<=8;
604  hint.classList.toggle('is-hidden',atBottom);hint.disabled=atBottom;
605  hint.setAttribute('aria-hidden',String(atBottom));
606 };
607 const onScroll=()=>{if(Math.abs(dialog.scrollTop-startingScroll)>1)dismissHint();};
608 hint.onclick=()=>{
609  dismissHint();
610  dialog.scrollBy({top:Math.max(120,dialog.clientHeight*.65),behavior:matchMedia('(prefers-reduced-motion: reduce)').matches?'auto':'smooth'});
611 };
612 dialog.addEventListener('scroll',onScroll,{passive:true});
613 detail.addEventListener('load',update,true);
614 const observer=new ResizeObserver(update);observer.observe(detail);observer.observe(dialog);
615 dialogScrollCleanup=()=>{observer.disconnect();dialog.removeEventListener('scroll',onScroll);detail.removeEventListener('load',update,true);hint.remove();dialogScrollCleanup=()=>{};};
616 update();
617}
618dialog.addEventListener('close',()=>{if(!dialog.open)dialogScrollCleanup();});
619
620
621let portalInstallPrompt=null;
622let portalInstalled=false;
623const portalIsStandalone=()=>portalInstalled||matchMedia('(display-mode: standalone)').matches||navigator.standalone===true;
624window.addEventListener('beforeinstallprompt',event=>{
625 event.preventDefault();portalInstallPrompt=event;
626 const button=document.querySelector('.portal-install-guide #install-portal');if(button&&!portalIsStandalone())button.hidden=false;
627});
628window.addEventListener('appinstalled',()=>{
629 portalInstalled=true;portalInstallPrompt=null;
630 const button=document.querySelector('#install-portal');if(button)button.hidden=true;
631 const status=document.querySelector('#portal-share-status');if(status)status.textContent='Added to your Home Screen.';
632});
633async function addPortalToHomeScreen(button,status){
634 if(portalIsStandalone()){button.hidden=true;return;}
635 if(portalInstallPrompt){
636  const prompt=portalInstallPrompt;portalInstallPrompt=null;button.disabled=true;
637  try{
638   await prompt.prompt();const choice=await prompt.userChoice;
639   status.textContent=choice.outcome==='accepted'?'Installation requested. Check your Home Screen.':'You can add this portal later from your browser menu.';
640  }catch{status.textContent='Open your browser menu and choose Add to Home screen or Install app.';}
641  finally{button.disabled=false;}
642  return;
643 }
644 const apple=/iPhone|iPad|iPod/.test(navigator.userAgent)||(navigator.platform==='MacIntel'&&navigator.maxTouchPoints>1);
645 const android=/Android/i.test(navigator.userAgent);
646 status.textContent=apple?'In Safari, tap the browser’s Share button, then More or View More if needed, and Add to Home Screen. Keep Open as Web App enabled if shown, then tap Add. If you opened this link inside another app, open it in Safari first.':android?'Open your browser’s menu (⋮), then choose Add to Home screen or Install app and confirm. If you opened this link inside another app, open it in Chrome first.':'Open your browser’s menu and look for Install app or Add to Home Screen. This option depends on your browser.';
647 status.scrollIntoView({block:'nearest',behavior:'smooth'});
648}
649
650function showPortalInstallGuide(){
651 const apple=/iPhone|iPad|iPod/.test(navigator.userAgent)||(navigator.platform==='MacIntel'&&navigator.maxTouchPoints>1);
652 const android=/Android/i.test(navigator.userAgent);
653 const iosSteps=`<li>Open this portal in <strong>Safari</strong>. From Instagram or another app, use its menu to open the page in your browser.</li><li>Tap Safari’s <strong>Share</strong> button <svg class="install-share-symbol" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" role="img" aria-label="square with an upward arrow"><path d="M12 15V3m-4 4 4-4 4 4M8 10H5v11h14V10h-3"/></svg>. If you don’t see it, open the <strong>More (…)</strong> menu and look for <strong>Share</strong>. The menu may be at the bottom right; its location can vary on iPhone and iPad.</li><li>Choose <strong>Add to Home Screen</strong>. Tap <strong>More</strong> or <strong>View More</strong> first if needed.</li><li>Keep <strong>Open as Web App</strong> on if shown, then tap <strong>Add</strong>.</li>`;
654 const androidSteps=`<li>Open this portal in <strong>Chrome</strong> or <strong>Samsung Internet</strong>. If you’re inside another app, open the link in your browser first.</li><li>Tap the browser’s <strong>menu</strong> (⋮ or ☰).</li><li>Choose <strong>Add to Home screen</strong> or <strong>Install app</strong>.</li><li>Confirm <strong>Install</strong> or <strong>Add</strong>, then look for the artist’s icon on your Home Screen.</li>`;
655 const card=(title,steps)=>`<section class="install-guide-card"><h3>${title}</h3><ol>${steps}</ol></section>`;
656 // Reuse the already loaded profile photo; generating the install icon requires a separate server round trip.
657 const icon=document.querySelector('.identity .avatar')?.currentSrc||profile.image||'/apple-touch-icon.png';
658 showDialog(`<div class="portal-install-guide"><button class="install-back" id="install-back" aria-label="Back to QR actions"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 5-7 7 7 7"/></svg></button><div class="install-preview"><img src="${escape(icon)}" width="100" height="100" loading="eager" fetchpriority="high" alt="${escape(profile.username)} Home Screen icon"><p>${escape(profile.username)}</p></div><p class="install-eyebrow">YOUR ARTIST, ON YOUR HOME SCREEN</p><h2 id="dialog-title">Install your artist’s app</h2><p class="install-intro">Keep this portal one tap away. It’s free to add, with no app store download.</p><button class="primary full" id="install-portal"${!portalInstallPrompt||portalIsStandalone()?' hidden':''}>Install Your Artist’s App</button>
658<p id="portal-share-status" role="status"></p>${apple?card('Install on iPhone or iPad',iosSteps):android?card('Install on Android',androidSteps):card('Install on iPhone or iPad',iosSteps)+card('Install on Android',androidSteps)}<section class="install-guide-card install-explainer"><h3>What gets added?</h3><p>A shortcut to this artist’s live portal, with their photo and username. Supported browsers open it in its own app window.</p><ul><li>One-tap access to your artist</li><li>The latest portfolio, flash, and booking options your artist shares</li><li>Updates appear automatically when you open the portal</li></ul><p class="meta">An internet connection is required.</p></section><p class="install-footer">Already added? Open the artist’s icon from your Home Screen.</p></div>`);
659 const button=detail.querySelector('#install-portal'),status=detail.querySelector('#portal-share-status');
660 button.onclick=()=>addPortalToHomeScreen(button,status);
661 detail.querySelector('#install-back').onclick=showPortalShare;
662 detail.querySelector('.install-preview img').onerror=function(){this.onerror=null;this.src='/apple-touch-icon.png';};
663}
664
665function installPortalShare(){
666  const header=document.querySelector('.topbar');
667  if(!header||document.querySelector('#share-artist'))return;
668  const button=document.createElement('button');
669  button.id='share-artist';button.className='portal-share-button';button.setAttribute('aria-label','Share this artist');
670  button.innerHTML='<svg width="23" height="23" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" aria-hidden="true"><rect x="3" y="3" width="6" height="6" rx=".5"/><rect x="15" y="3" width="6" height="6" rx=".5"/><rect x="3" y="15" width="6" height="6" rx=".5"/><path d="M15 13v4h4v4h2M13 21h2M21 13v2M12 3v3M3 12h3m6-3v3h4"/></svg>';
671  button.onclick=showPortalShare;header.append(button);
672}
673async function showPortalShare(){
674  // Share only the public profile, never an appointment token or return reference.
675  const url=new URL('/'+encodeURIComponent(profile.username.toLowerCase()),location.origin).href;
676  showDialog(`<div class="portal-share-sheet">${profile.image?`<img class="share-avatar" src="${escape(profile.image)}" alt="">`:''}<h3 id="dialog-title">${escape(profile.name||profile.username)}</h3><p class="meta">@${escape(profile.username)}</p><div id="portal-qr"><p>Loading QR code…</p></div><a class="share-url" href="${escape(url)}">${escape(url)}</a><p>Scan to view this artist’s portal</p><button class="primary full" id="share-portal-link">Share link</button><button class="primary full" id="copy-portal-link">Copy link</button><button class="primary full" id="install-portal"${portalIsStandalone()?' hidden':''}>Install Your Artist’s App</button><p id="portal-share-status" role="status"></p></div>`);
677  const status=detail.querySelector('#portal-share-status');
678  const installButton=detail.querySelector('#install-portal');
679  installButton.onclick=showPortalInstallGuide;
680  const copy=async()=>{try{await navigator.clipboard.writeText(url);status.textContent='Link copied';}catch{status.textContent='Touch and hold the link beneath the QR code to copy it.';}};
681  detail.querySelector('#copy-portal-link').onclick=copy;
682  detail.querySelector('#share-portal-link').onclick=async()=>{
683    if(!navigator.share){await copy();return;}
684    try{await navigator.share({title:profile.username,url});}
685    catch(error){if(error.name!=='AbortError')status.textContent='Couldn’t share. Try Copy link instead.';}
686  };
687  const container=detail.querySelector('#portal-qr');
688  try{
689    const QR=PortalQR;
690    const canvas=document.createElement('canvas');
691    await QR.toCanvas(canvas,url,{width:320,margin:4,errorCorrectionLevel:'M',color:{dark:'#000000',light:'#ffffff'}});
692    canvas.style.removeProperty('width');canvas.style.removeProperty('height');
693    canvas.setAttribute('role','img');canvas.setAttribute('aria-label','QR code for the artist portal');container.replaceChildren(canvas);
694  }catch{container.textContent='QR code unavailable. You can still share or copy the portal link.';}
695}
696
697function eventCards(events){
698 return events.length?events.map(event=>`<a class="event-summary" href="#event/${encodeURIComponent(event.id)}" data-event-id="${escape(event.id)}">${event.coverImage?`<img class="event-summary-banner" src="${escape(event.coverImage)}" alt="" loading="lazy">`:''}<div class="event-summary-details"><div><h2>${escape(event.name)}</h2><p class="event-summary-date">
698${escape(new Date(event.startsAt).toLocaleString([], {timeZone:event.timezone||'UTC',dateStyle:'medium',timeStyle:'short'}))}</p><p class="event-summary-location">${escape(event.location)}</p></div><span class="event-summary-chevron" aria-hidden="true">›</span></div></a>`).join(''):'<p class="empty-state">No public events yet.</p>';
699}
700async function renderProfileEvents(content){
701 const id=profileEventID(location.hash);
702 content.dataset.eventID=id||'';
703 const request=String(Number(content.dataset.request||0)+1);content.dataset.request=request;
704 if(!id){
705  content.innerHTML=eventCards(profile.events||[]);content.dataset.ready='true';
706  content.querySelectorAll('[data-event-id]').forEach(link=>link.onclick=event=>{
707   if(event.metaKey||event.ctrlKey||event.shiftKey||event.altKey)return;
708   event.preventDefault();history.pushState(null,'',link.getAttribute('href'));
709   delete content.dataset.ready;renderProfileEvents(content);
710  });
711  return;
712 }
713 content.dataset.loading='true';content.innerHTML='<p class="message" role="status">Loading event…</p>';
714 try{
715  const event=await api(`/api/events/${encodeURIComponent(id)}`);
716  if(content.dataset.request!==request)return;
717  renderEventContent(event,content,true);content.dataset.ready='true';
718 }catch(error){
719  if(content.dataset.request!==request)return;
720  content.innerHTML=`<p class="message">${escape(error.message)}</p><button class="secondary">Try again</button>`;
721  content.querySelector('button').onclick=()=>renderProfileEvents(content);
722 }finally{if(content.dataset.request===request)delete content.dataset.loading;}
723}
724window.addEventListener('popstate',()=>{
725 if(!profile)return;
726 const tab=profileEventID(location.hash)?'event':location.hash.slice(1);
727 if(!profile.tabs.includes(tab))return;
728 activeTab=tab;
729 const panel=tabPanels.get('event');if(tab==='event'&&panel&&(panel.dataset.eventID||'')!==(profileEventID(location.hash)||'')){delete panel.dataset.ready;delete panel.dataset.loading;panel.dataset.request=String(Number(panel.dataset.request||0)+1);}
730 document.querySelectorAll('[data-tab]').forEach(b=>{b.setAttribute('aria-selected',String(b.dataset.tab===tab));b.tabIndex=b.dataset.tab===tab?0:-1;});
731 renderTab();
732});
733async function loadEventPage(id){
734 const initial=document.querySelector('#initial-event');
735 const event=initial?JSON.parse(initial.textContent):await api(`/api/events/${encodeURIComponent(id)}`);
736 const host=event.artists.find(a=>a.isOrganizer&&a.portalURL)||event.artists.find(a=>a.portalURL);
737 if(host){location.replace(`${host.portalURL}#event/${encodeURIComponent(id)}`);return;}
738 document.title=`${event.name} · TattSafe`;app.setAttribute('aria-busy','false');
739 renderEventContent(event,app,false);
740}
741function eventLocationMarkup(event){
742 const a=event.address||{};
743 const address=[a.street,a.city,[a.region,a.postalCode].filter(Boolean).join(' '),a.country].filter(Boolean).join(', ');
744 const query=address||event.location||(Number.isFinite(a.latitude)&&Number.isFinite(a.longitude)?`${a.latitude},${a.longitude}`:'');
745 if(!query)return '';
746 const title=a.venueName||event.venueName||(event.location&&event.location!==address?event.location:'Open in Maps');
747 return renderLocationMarkup({title,address:address||event.location||'',latitude:a.latitude,longitude:a.longitude},{label:'Tattoo Shop',query,showTitle:false});
748}
749function eventFlashPrice(flash){
750 return flash.isGuestSheet&&flash.maximumPriceCents!==flash.minimumPriceCents?`${money(flash.minimumPriceCents/100)} – ${money(flash.maximumPriceCents/100)}`:money(flash.priceCents/100);
751}
752function eventFlashDetailsMarkup(flash,event){
753 if(flash.isGuestSheet){
754  const artist=event.artists.find(a=>a.id===flash.artistID);
755  return `<section class="event-flash-detail"><h2 id="dialog-title">${escape(flash.title)}</h2><img class="event-flash-large" src="${escape(flash.image)}" alt="${escape(flash.title)}"><h3>${escape(eventFlashPrice(flash))}</h3><p>Prices vary by design. Confirm your design and final price with the guest artist at the event.</p>${artist?`<div class="event-artists">
755${eventArtistMarkup(artist,event.id)}</div>`:''}</section>`;
756 }
757
758 const eligible=event.artists.filter(a=>(!a.isGuest||flash.individualDesign===true)&&(flash.eligibleArtistIDs||[flash.artistID]).includes(a.id));
759 const original=Number.isSafeInteger(flash.originalPriceCents)?money(flash.originalPriceCents/100):'Not provided';
760 const discount=Number.isSafeInteger(flash.discountBasisPoints)?`${(flash.discountBasisPoints/100).toLocaleString(undefined,{maximumFractionDigits:2})}% off`:'Not provided';
761 const availability=eligible.length===1?'This design can be tattooed by the artist below.':eligible.length>1?'This design can be tattooed by any of the artists below.':'Ask the event organizer which artist can tattoo this design.';
762 return `<section class="event-flash-detail"><h2 id="dialog-title">${escape(flash.title)}</h2>${flash.image?`<img class="event-flash-large" src="${escape(flash.image)}" alt="${escape(flash.title)}">`:'<p class="empty-state">Image unavailable</p>'}<dl class="event-flash-pricing"><div><dt>Original price</dt><dd>${escape(original)}</dd></div><div><dt>Discount</dt><dd>${escape(discount)}</dd></div><div class="event-flash-total"><dt>Event total</dt><dd>${escape(money(flash.priceCents/100))}</dd></div></dl>${flash.detail?`<p>${escape(flash.detail)}</p>`:''}${flash.individualDesign?`<dl class="event-flash-pricing"><div><dt>Minimum size</dt><dd>${flash.width&&flash.height?`${escape(flash.width)} × ${escape(flash.height)} in`:'Discuss with artist'}</dd></div><div><dt>Duration</dt><dd>${escape(flash.duration)} hours</dd></div><div><dt>Deposit</dt><dd>${escape(money(flash.deposit))}</dd></div><div><dt>Quantity</dt><dd>${flash.count===-1?'Unlimited':escape(flash.count)}</dd></div></dl>`:''}<h3>Who can tattoo this?</h3><p>${escape(availability)}</p><div class="event-artists">${eligible.map(a=>eventArtistMarkup(a,event.id)).join('')}</div><p class="note">Check in at the event to join the queue. Viewing a design does not reserve it.</p></section>`;
763}
764function showEventFlash(flash,event){showDialog(eventFlashDetailsMarkup(flash,event));}
765function renderEventContent(event,target,embedded){
766 target.innerHTML=`<article class="event-page">${embedded?'<a class="event-back-link" href="#event" aria-label="Back to events"><svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 5-7 7 7 7"/></svg></a>':''}<header class="event-hero">${event.coverImage?`<img class="event-cover" src="${escape(event.coverImage)}" alt="${escape(event.name)}">`:""}${embedded?'':'<a href="/">TattSafe Events</a>'}<p class="event-kicker">Tattoo Flash Event</p><h1>${escape(event.name)}</h1><div class="event-dates"><p class="event-date"><strong>Start</strong><span>${escape(new Date(event.startsAt).toLocaleString([], {timeZone:event.timezone||'UTC',dateStyle:'full',timeStyle:'short'}).replace(/\s+(?=[AP]M\b)/g,'\u00a0'))}</span></p><p class="event-date"><strong>End</strong><span>${escape(new Date(event.endsAt).toLocaleString([], {timeZone:event.timezone||'UTC',dateStyle:'full',timeStyle:'short'}).replace(/\s+(?=[AP]M\b)/g,'\u00a0'))}</span></p></div>${eventLocationMarkup(event)}<p class="event-description">${escape(event.details)}</p>${event.admission?`<p class="event-admission">${escape(event.admission)}</p>`:''}<p class="event-walkin">Check in at the event. This page does not reserve a place in the queue.</p></header><section class="event-section"><h2>Meet the Artists</h2><div class="event-artists">${event.artists.map(a=>eventArtistMarkup(a,event.id)).join('')}</div></section>${event.showFlash===false?'':`<section class="event-section"><div class="event-section-heading"><h2>Event Flash</h2><label>Artist <select id="event-artist"><option value="">All Artists</option>${event.artists.map(a=>`<option value="${escape(a.id)}">${escape(a.name)}</option>`).join('')}</select></label><label>Sort <select id="event-sort"><option value="title">Title A–Z</option><option value="low">Price: Low to High</option><option value="high">Price: High to Low</option></select></label></div><div id="event-flash" class="grid"></div></section>`}${event.activities.length?`<section class="event-section"><h2>What Else Is Happening</h2><div class="event-activities">${event.activities.map(a=>`<article>${(a.images??(a.image?[a.image]:[])).length?`<div class="event-vendor-gallery">${(a.images??[a.image]).map(src=>`<img class="event-vendor-image" src="${escape(src)}" alt="${escape(a.name)}" loading="lazy">`).join('')}</div>`:""}<p class="event-kicker">${escape(a.kind)}${a.time?` · ${escape(a.time)}`:''}</p><h3>${escape(a.name)}</h3><p>${escape(a.details)}</p><div class="event-links">${a.links.map(l=>`<a href="${escape(l.url)}" target="_blank" rel="noopener noreferrer">${escape(l.label)} ↗</a>`).join('')}</div></article>`).join('')}</div></section>`:''}</article>`;
767 target.querySelector('.event-back-link')?.addEventListener('click',event=>{
768  if(event.metaKey||event.ctrlKey||event.shiftKey||event.altKey)return;
769  event.preventDefault();selectTab('event');
770 });
771 const render=()=>{
772  const artist=target.querySelector('#event-artist').value,sort=target.querySelector('#event-sort').value;
773  const items=event.flash.filter(f=>!artist||f.artistID===artist).sort((a,b)=>sort==='low'?a.priceCents-b.priceCents:sort==='high'?b.priceCents-a.priceCents:a.title.localeCompare(b.title));
774  target.querySelector('#event-flash').innerHTML=items.length?items.map(f=>`<button type="button" class="card event-flash-card" data-event-flash="${escape(f.id)}" aria-label="View ${escape(f.title)} details">${f.image?`<img src="${escape(f.image)}" alt="${escape(f.title)}" loading="lazy">`:'<div class="art-empty">Image unavailable</div>'}<div><h3>${escape(f.title)}</h3><p>
774${escape(eventFlashPrice(f))}</p><p>${escape(event.artists.find(a=>a.id===f.artistID)?.name||'')}</p></div></button>`).join(''):'<p class="empty-state">No event flash has been shared yet.</p>';
775  target.querySelectorAll('[data-event-flash]').forEach(button=>button.onclick=()=>{
776   const flash=items.find(f=>f.id===button.dataset.eventFlash);
777   if(flash)showEventFlash(flash,event);
778  });
779 };
780 if(event.showFlash!==false){target.querySelector('#event-artist').onchange=render;target.querySelector('#event-sort').onchange=render;render();}
781}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.