<!DOCTYPE html>
<!--
  NNwords. Free neon letters on Robinhood Chain: burn them into your own words, up to 256 letters.
  Every text exists once. One file, stored on Arbitrum One in a sealed gate contract, reading the chain itself.
-->
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'sha256-QE8s2USXo/54XMJSOaRDYJYVYH79kALrLW61PGL4LLI='; style-src 'sha256-LzL/m4w8nL8C0PVPcGOA0TklVTHopzt/7lxbHgTmfQ4='; img-src data:; connect-src https://rpc.mainnet.chain.robinhood.com; base-uri 'none'; form-action 'none'">
<meta name="referrer" content="no-referrer">
<title>NNwords: neon words on chain</title>
<style>:root{--bg: #0b0a0f;--wall: #121017;--ink: #ece9f2;--dim: #8d8999;--line: #2a2733;--pink: #ff4fb8;--cyan: #3fe9ff;--bad: #ff6a6a;--ok: #9bff4a}*{box-sizing:border-box}html{background:var(--bg)}body{margin:0;color:var(--ink);font:15px/1.5 Helvetica,Arial,sans-serif;background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='72' height='52'%3E%3Cpath d='M0 1H72M0 27H72M36 1V27M1 27V52M71 27V52' stroke='%23000' stroke-opacity='.42' stroke-width='2' fill='none'/%3E%3C/svg%3E") 0 0 / 72px 52px,radial-gradient(ellipse at 50% 20%,#1f1c27,var(--bg) 70%);background-attachment:fixed;min-height:100vh}a{color:var(--cyan)}button{font:600 12px/1 Helvetica,Arial,sans-serif;letter-spacing:2px;color:var(--ink);background:transparent;border:1px solid var(--pink);border-radius:999px;padding:11px 18px;cursor:pointer;box-shadow:0 0 10px #ff4fb859,inset 0 0 8px #ff4fb833}button:hover:not(:disabled){background:#ff4fb81f}button:disabled{opacity:.35;cursor:default;box-shadow:none}button.small{padding:7px 12px;font-size:11px}button.ghost{border-color:var(--line);box-shadow:none}button.big{width:100%;padding:16px;font-size:15px;letter-spacing:4px}input,textarea,select{font:15px Helvetica,Arial,sans-serif;color:var(--ink);background:#00000073;border:1px solid var(--line);border-radius:8px;padding:9px 11px}textarea{width:100%;resize:vertical;font-size:20px;letter-spacing:3px;text-transform:uppercase}input[type=number]{width:84px}h2{margin:0 0 14px;font-size:13px;letter-spacing:4px;font-weight:600;text-transform:uppercase;color:#fff;text-shadow:0 0 6px var(--pink),0 0 18px rgba(255,79,184,.6)}.top{max-width:1180px;margin:0 auto;padding:26px 28px 8px;display:grid;grid-template-columns:150px 1fr auto;gap:22px;align-items:center}#logo{width:150px;height:150px;border-radius:10px;display:block}.tag{font-size:18px;color:#d9d5e2;max-width:560px}.wallet{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}.stats{max-width:1180px;margin:10px auto 0;padding:0 28px;display:grid;grid-template-columns:1.2fr 1fr;gap:22px}.nums{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}.nums div{background:#0006;border:1px solid var(--line);border-radius:10px;padding:12px 14px;font-size:12px;color:var(--dim)}.nums b{display:block;font-size:22px;color:#fff;letter-spacing:1px}.bars{display:grid;gap:6px;align-content:center}.bar{display:grid;grid-template-columns:80px 1fr 84px;gap:10px;align-items:center;font-size:12px;color:var(--dim)}.bar i{display:block;height:6px;border-radius:3px;background:var(--cyan);box-shadow:0 0 8px var(--cyan);min-width:2px}.bar b{text-align:right;color:#fff;font-weight:400}.grid{max-width:1180px;margin:22px auto 0;padding:0 28px;display:grid;grid-template-columns:1.25fr 1fr;gap:22px;align-items:start}.card{background:#0a090ed1;border:1px solid var(--line);border-radius:14px;padding:22px;max-width:1180px}body>.card{margin:22px auto 0;width:calc(100% - 56px);max-width:1124px}.row{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:10px 0}.hint,.dim{color:var(--dim);font-size:13px}.chips{display:flex;flex-wrap:wrap;gap:6px;margin:10px 0}.chip{padding:6px 10px;font-size:10px;border-color:var(--line);box-shadow:none}.chip.on{border-color:currentColor;box-shadow:0 0 8px currentColor}.chip:first-child{color:#fff}.prism{background:linear-gradient(90deg,#ff4fb8,#ffb23f,#9bff4a,#3fe9ff,#a86bff);-webkit-background-clip:text;background-clip:text;color:transparent!important;border-color:#a86bff}.preview{position:relative;margin:12px 0}.preview img{width:100%;max-width:480px;margin:0 auto;aspect-ratio:1;display:block;border-radius:10px;cursor:pointer}.facts{display:flex;flex-wrap:wrap;gap:8px 18px;font-size:13px;color:var(--dim);margin:8px 0}.facts b{color:#fff}.need,.replace{font-size:14px;color:#d9d5e2;margin:10px 0}.bad{color:var(--bad)!important}.ok{color:var(--ok)}.msg{min-height:20px;font-size:13px;color:var(--cyan);margin-top:10px}.tubes{display:flex;flex-wrap:wrap;gap:6px;margin:14px 0;max-height:360px;overflow:auto}.tube{width:38px;height:46px;padding:0;border-radius:6px;border:1px solid var(--line);background:#0000008c;font:400 24px/44px Helvetica,Arial,sans-serif;letter-spacing:0;text-shadow:0 0 4px currentColor,0 0 12px currentColor;box-shadow:none}.tube.unlit{font-size:26px;color:#4a4654;text-shadow:none}.tube.ready{border-style:dashed;border-color:#5a5566}.tube.prism{text-shadow:none;filter:drop-shadow(0 0 4px #a86bff)}.signs{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:16px}.sign{margin:0}.sign img{width:100%;aspect-ratio:1;display:block;border-radius:8px;cursor:pointer}.sign figcaption{font-size:12px;color:var(--dim);margin-top:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sign figcaption span{color:#fff;margin-right:6px}.sign .row{margin:4px 0 0;justify-content:space-between}#more{margin-top:16px}.how p{color:#d9d5e2;margin:0 0 10px;max-width:900px}.scroll{overflow-x:auto;max-width:100%}.how table{border-collapse:collapse;font-size:13px;margin:6px 0 14px}.how td,.how th{border-bottom:1px solid var(--line);padding:6px 14px 6px 0;text-align:left}.how th{color:var(--dim);font-weight:400}footer{max-width:1180px;margin:22px auto 40px;padding:0 28px;font-size:12px;color:var(--dim)}.modal{position:fixed;inset:0;background:#000000d1;display:grid;place-items:center;z-index:9}.modal[hidden]{display:none}.modal .box{width:min(560px,92vw)}.modal img{width:100%;aspect-ratio:1;display:block;border-radius:10px}.modal .row{justify-content:space-between}#minfo{font-size:14px;color:#d9d5e2;word-break:break-word}@media(max-width:900px){.top{grid-template-columns:96px 1fr}#logo{width:96px;height:96px}.wallet{grid-column:1 / -1;justify-content:flex-start}.stats,.grid{grid-template-columns:1fr}.nums{grid-template-columns:repeat(2,1fr)}.top,.stats,.grid{padding:0 14px}.top{padding-top:18px}body>.card{width:calc(100% - 28px)}.card{padding:16px}.bar{grid-template-columns:64px 1fr 70px}textarea{font-size:17px}.how td,.how th{padding:6px 8px 6px 0;font-size:12px}}</style>
</head>
<body>
<header class="top">
  <img id="logo" alt="NNwords">
  <div class="tag">Free neon letters. Burn them into your own words, up to 256 letters. Every text exists once.</div>
  <div id="wallet" class="wallet"></div>
</header>
<section id="stats" class="stats"></section>
<main class="grid">
  <section class="card">
    <h2>Write a sign</h2>
    <textarea id="text" rows="2" spellcheck="false" autocomplete="off" placeholder="TYPE YOUR WORDS"></textarea>
    <div class="row"><label class="hint"><input type="checkbox" id="auto" checked> Line breaks by the site</label><span class="hint">or your own: / between words, | inside a word</span></div>
    <div id="chips" class="chips"></div>
    <div class="preview"><img id="pv" alt="the sign"></div>
    <div id="facts" class="facts"></div>
    <div id="need" class="need"></div>
    <div id="replace" class="replace"></div>
    <button id="light" class="big">LIGHT IT</button>
    <div id="lightmsg" class="msg"></div>
  </section>
  <section class="card">
    <h2>Your letters</h2>
    <div class="row"><button id="mint">GET 2 FREE LETTERS</button></div>
    <p class="hint">Every wallet gets two. The hash of the block of your mint picks the letter and its colour, so nobody can time a mint for a rare one; the next transaction anyone sends to NNwords writes it down for good.</p>
    <div id="tubes" class="tubes"></div>
    <div class="row"><span id="readynote" class="hint"></span><button id="writeit" class="small" hidden>WRITE THEM DOWN NOW</button></div>
    <div class="row"><span id="tubeholds" class="hint"></span><button id="claim" class="small">TAKE WHAT THEY HOLD</button></div>
    <div id="minemsg" class="msg"></div>
  </section>
</main>
<section class="card"><h2>Your signs</h2><div id="mysigns" class="signs"></div></section>
<section class="card"><h2>The wall</h2><div id="wall" class="signs"></div><button id="more" class="small ghost">OLDER SIGNS</button></section>
<section class="card how">
  <h2>How it works</h2>
  <p>Every wallet gets two free letters. Letters fall out the way English does: E is common, Q and Z are rare, two in a hundred glow gold and one in a hundred prism. The hash of the block of a mint picks its letters; the next transaction to NNwords writes them down for good. If nothing touches NNwords for the 11 hours the chain keeps block hashes, the letters of that last block become E in ICE.</p>
  <p>Burn your letters into a sign: any words, up to 256 letters, in any colours your letters have. Every text exists once. A sign costs by its size, three times more for each size up:</p>
  <div class="scroll"><table>
    <tr><th>letters up to</th><td>4</td><td>8</td><td>16</td><td>32</td><td>64</td><td>128</td><td>256</td></tr>
    <tr><th>ETH</th><td>0.0001</td><td>0.0003</td><td>0.0009</td><td>0.0027</td><td>0.0081</td><td>0.0243</td><td>0.0729</td></tr>
    <tr><th>places at once</th><td>any</td><td>any</td><td>4096</td><td>2048</td><td>1024</td><td>512</td><td>256</td></tr>
    <tr><th>share of the 70%</th><td>5%</td><td>5%</td><td>7%</td><td>10%</td><td>15%</td><td>23%</td><td>35%</td></tr>
  </table></div>
  <p>Every sign pays at once: 70% to the signs already standing, 10% to every letter not burned yet, 20% to the deployer. The 70% is shared out by size, as in the table, and inside a size equally among its signs: the bigger the sign, the bigger its share. A sign is named by that share and its words, like <b>5%: moon</b>. A size with no sign keeps its share waiting: its first sign takes it.</p>
  <p>What a token holds stays inside it and goes with it when it is sold. Take it any time.</p>
  <p>When a size is full, its places change hands: buy a sign of that size, and lighting your own puts it out and takes its place in the same transaction.</p>
</section>
<footer><span id="contracts"></span> No team, no pause, no keys over the money.</footer>
<div id="modal" class="modal" hidden>
  <div class="box">
    <img id="mimg" alt="">
    <div class="row"><span id="minfo"></span><span><button id="msound" class="small">SOUND</button> <button id="mclose" class="small ghost">CLOSE</button></span></div>
  </div>
</div>
<script id="app">(()=>{var I={fn:{stats:"d80528ae",standing:"e3a47b00",waiting:"b405c549",freeLeft:"eb28217e",holdingsOf:"85242fde",signOfText:"38683af9",mint:"a0712d68",light:"a2130a44",claim:"6ba4c138",unlight:"742112f0",glyphsOf:"6d6da361",latest:"3d0e6881",capture:"d4a3e9d7"},err:{d9d552c9:"ContractsCannotMint","414bfec4":"FreeMintUsed",b23bee05:"WrongPayment","5a2a093e":"BadText","3715f556":"NotYours",a1c0ce30:"NotALetter","62a9d693":"NotLitYet",a218e71d:"WrongLetter","31f8df64":"TextTaken","52e49721":"SizeFull",ab143c06:"Reentrancy",ceea21b6:"TokenDoesNotExist"},ev:{Transfer:"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"}};var O={chain:4663,name:"Robinhood Chain",rpc:"https://rpc.mainnet.chain.robinhood.com",explorer:"https://robinhoodchain.blockscout.com",opensea:"nnwords",nnwords:"0xc02e05677dba819e25119236df3752fba18e274a"};var J={A:"M5 80L30 0L55 80M15 50H45",B:"M8 80V0H33Q52 0 52 19Q52 38 33 38H8M33 38Q55 38 55 59Q55 80 33 80H8",C:"M54 14Q47 0 30 0Q6 0 6 40Q6 80 30 80Q47 80 54 66",D:"M8 0V80H27Q55 80 55 40Q55 0 27 0Z",E:"M52 0H8V80H52M8 40H42",F:"M52 0H8V80M8 40H42",G:"M54 14Q47 0 30 0Q6 0 6 40Q6 80 30 80Q54 80 54 54V44H34",H:"M7 0V80M53 0V80M7 40H53",I:"M30 0V80M18 0H42M18 80H42",J:"M48 0V58Q48 80 27 80Q10 80 8 64",K:"M8 0V80M52 0L8 50M24 34L54 80",L:"M9 0V80H52",M:"M5 80V0L30 46L55 0V80",N:"M7 80V0L53 80V0",O:"M30 0Q55 0 55 40Q55 80 30 80Q5 80 5 40Q5 0 30 0Z",P:"M8 80V0H33Q54 0 54 21Q54 42 33 42H8",Q:"M30 0Q55 0 55 40Q55 80 30 80Q5 80 5 40Q5 0 30 0ZM36 58L56 82",R:"M8 80V0H33Q54 0 54 21Q54 42 33 42H8M30 42L54 80",S:"M52 12Q46 0 30 0Q8 0 8 20Q8 38 30 40Q52 42 52 61Q52 80 30 80Q12 80 6 66",T:"M4 0H56M30 0V80",U:"M7 0V52Q7 80 30 80Q53 80 53 52V0",V:"M4 0L30 80L56 0",W:"M2 0L15 80L30 26L45 80L58 0",X:"M6 0L54 80M54 0L6 80",Y:"M4 0L30 42L56 0M30 42V80",Z:"M6 0H54L6 80H54"},v=Object.keys(J),xe={w:"M3 28L16 80L30 42L44 80L57 28",o:"M30 28Q54 28 54 54Q54 80 30 80Q6 80 6 54Q6 28 30 28Z",r:"M12 28V80M12 50Q14 28 36 28Q46 28 52 34",d:"M50 0V80M50 54Q50 28 29 28Q8 28 8 54Q8 80 29 80Q50 80 50 54",s:"M49 35Q44 28 30 28Q11 28 11 41Q11 52 30 54Q50 56 50 67Q50 80 30 80Q14 80 8 72"};var D=[["PINK","#FF4FB8"],["CYAN","#3FE9FF"],["LIME","#9BFF4A"],["AMBER","#FFB23F"],["VIOLET","#A86BFF"],["RED","#FF4A4A"],["ICE","#E8F1FF"],["GOLD","#FFD27A"],["PRISM","url(#p)"]],$e=8;var ft=234,lt=235,Dt=236;var ve=t=>t<ft,Tt=t=>t%26,it=t=>Math.floor(t/26);var P=[4,8,16,32,64,128,256],ut=[0,0,4096,2048,1024,512,256],ht=[5,5,7,10,15,23,35];function dt(t){let e=0;for(;P[e]<t;)e++;return e}var Me=t=>String(t).padStart(2,"0"),at=t=>`${Math.floor(t/100)}.${Me(t%100)}`,K=t=>`${Math.floor(t/10)}.${t%10}`,Yt='<filter id="a" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="9"/></filter><filter id="b" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="2.5"/></filter><filter id="c" x="-50%" y="-50%" width="200%" height="200%"><feGaussianBlur stdDeviation="4"/></filter><radialGradient id="v" cx=".5" cy=".45" r=".75"><stop offset="0" stop-color="#1F1C27"/><stop offset="1" stop-color="#08070B"/></radialGradient><linearGradient id="p" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#FF4FB8"/><stop offset=".3" stop-color="#FFB23F"/><stop offset=".55" stop-color="#9BFF4A"/><stop offset=".8" stop-color="#3FE9FF"/><stop offset="1" stop-color="#A86BFF"/></linearGradient>';function ke(t){let e=Math.max(t,160),n=o=>K(Math.floor(o*100/e));return`<style>.t use,.t rect{fill:none;stroke-linecap:round;stroke-linejoin:round}.s{stroke:#000;stroke-opacity:.45;stroke-width:${n(70)};filter:url(#c)}.u{stroke:currentColor;stroke-opacity:.2;stroke-width:${n(60)}}.a{stroke:currentColor;stroke-width:${n(180)};opacity:.45;filter:url(#a)}.b{stroke:currentColor;stroke-width:${n(100)};opacity:.85;filter:url(#b)}.g{stroke:currentColor;stroke-width:${n(60)}}.c{stroke:#fff;stroke-width:${n(24)};opacity:.85}`+zt}var zt=".r .a,.r .b,.r .g{stroke:url(#p)}.l{animation:n 2s linear both}.f{animation:n 2s linear both,f 7s linear 3s infinite}@keyframes n{0%{opacity:1}4%{opacity:.1}7%{opacity:.85}10%{opacity:.15}15%{opacity:1}19%{opacity:.4}23%,100%{opacity:1}}@keyframes f{0%,90%,100%{opacity:1}91%{opacity:.15}92%{opacity:1}94%{opacity:.25}96%{opacity:.9}97%{opacity:1}}</style>";function pt(){let t="";for(let e=0;e<16;e++){let n=e%2?0:36;for(let o=-1;o<6;o++)t+=`<rect x="${o*72+n}" y="${e*26}" width="72" height="26"/>`}return`<rect width="400" height="400" fill="url(#v)"/><g fill="none" stroke="#000" stroke-opacity=".38" stroke-width="2">${t}</g>`}var gt=(t,e)=>`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400" width="400" height="400"><defs>${Yt}${e}</defs>${ke(t)}`,Te=t=>t===$e?'class="r" color="#fff"':`color="${D[t][1]}"`;function G(t,e,n,o,r,s,i){let a=Math.max(r,160),l=K(Math.floor(4e3/a)),d=K(Math.floor(6e3/a)),p=`transform="translate(${K(Math.floor(n/10))} ${K(Math.floor(o/10))}) scale(${at(r)})"`,h=t[0]==="#",g=(b,T="")=>h?`<use href="${t}" class="${b}"${T}/>`:`<rect ${t} class="${b}"${T}/>`,$=h?` x="${l}" y="${d}"`:` transform="translate(${l} ${d})"`,w=i?`${at(s)}s,${at(s+300)}s`:`${at(s)}s`;return`<g ${p} ${Te(e)}>`+g("s",$)+g("u")+`<g class="${i?"f":"l"}" style="animation-delay:${w}">`+g("a")+g("b")+g("g")+g("c")+"</g></g>"}var Le=t=>Math.imul(t,1103515245)+12345&2147483647;function Ee(t){let e=7;for(let n=0;n<t.length;n++)e=e+t[n]*(n+1)&2147483647;return e}var Y=78,j=18,F=42,X=96,Wt=16;function Lt(t){let e=[[]];for(let i of t)i===lt||i===Dt?e.push([]):e[e.length-1].push(i);let n=e.map(i=>i.reduce((a,l)=>a+(l===ft?F:Y),0)-j),o=0;for(let i of n)i>o&&(o=i);let r=e.length*X-Wt,s=Math.min(Math.floor(3e4/o),Math.floor(3e4/r),300);return s<100&&(s=Math.min(Math.floor(35200/o),Math.floor(35200/r))),{lines:e,widths:n,W:o,H:r,S:s}}function Z(t){let{lines:e,widths:n,W:o,H:r,S:s}=Lt(t),i=t.filter(ve),a=i.length,l=[];for(let f of i)l.includes(Tt(f))||l.push(Tt(f));l.sort((f,y)=>f-y);let d=l.map(f=>`<path id="${v[f]}" d="${J[v[f]]}"/>`).join(""),p=gt(s,d)+pt()+'<g class="t">',h=Ee(t),g=h%7===0?(h>>3)%a:-1,$=a>1&&i.every(f=>it(f)===it(i[0])),w=Math.floor((4e4-r*s)/2);if($){let f=Math.floor(1600/s)+4,y=Math.floor((4e4-o*s)/2);p+=G(`x="-${f}" y="-${f}" width="${o+2*f}" height="${r+2*f}" rx="${f}"`,it(i[0]),y,w,s,10,!1)}let b=1;for(let f of t)(f===ft||f===lt)&&b++;let T=h,N=0,L=0,q=0,V=Math.floor((4e4-n[0]*s)/2),U=w;for(let f of t)if(f===ft)V+=F*s,N++;else if(f===lt||f===Dt)f===lt&&N++,q++,V=Math.floor((4e4-n[q]*s)/2),U+=X*s;else{T=Le(T);let y=20+Math.floor(N*160/b)+(T>>16)%24;p+=G(`#${v[Tt(f)]}`,it(f),V,U,s,y,L===g),V+=Y*s,L++}return p+"</g></svg>"}var ct=(t,e,n,o,r,s="start")=>`<text x="${t}" y="${e}" text-anchor="${s}" font-family="Helvetica, Arial, sans-serif" font-size="${o}" letter-spacing="2" fill="#fff" fill-opacity="${r}">${n}</text>`,Se=t=>{let e=BigInt(t),n=e/10n**18n,o=e%10n**18n/10n**12n;return`${n}.${String(o).padStart(6,"0")}`},Ae=t=>String(t).padStart(4,"0"),Ut=(t,e,n,o)=>ct(26,366,t,14,".9")+ct(26,386,e,11,".55")+ct(374,366,`NO ${Ae(n)}`,11,".55","end")+ct(374,386,`HOLDS ${Se(o)} ETH`,11,".55","end")+"</svg>";function Kt(t,e,n,o=0n){let r=v[t];return gt(300,`<path id="${r}" d="${J[r]}"/>`)+pt()+'<g class="t">'+G(`#${r}`,e,11e3,6e3,300,30,!1)+"</g>"+Ut(`LETTER ${r}`,D[e][0],n,o)}function Jt(t,e=0n){return gt(300,'<path id="t" d="M0 0L50 50"/>')+pt()+'<g class="t"><g transform="translate(125.0 95.0) scale(3.00)" color="#E8F1FF"><use href="#t" class="s" x="1.3" y="2.0"/><use href="#t" class="u"/></g></g><g transform="translate(125.0 95.0) scale(3.00)"><path d="M-5 -5L-1 -1M51 51L55 55" stroke="#2B2833" stroke-width="4" stroke-linecap="round"/></g>'+Ut("LETTER","LIGHTING UP",t,e)}function Xt(){let t=`<path id="N" d="${J.N}"/><path id="lw" d="${xe.w}"/>`,e=138,n=5096,o=14480,r=Y*e;return gt(e,t)+pt()+'<g class="t">'+G("#N",0,n,o,e,20,!1)+G("#N",0,n+r,o,e,34,!1)+G("#lw",0,n+2*r,o,e,48,!0)+"</g></svg>"}var Ce="var A,M,H,B,on=0;function G(){A=new(window.AudioContext||window.webkitAudioContext);M=A.createGain();M.gain.value=0;M.connect(A.destination);var o=A.createOscillator(),re=new Float32Array([0,1,.55,.32,.2,.12,.08]);o.setPeriodicWave(A.createPeriodicWave(re,new Float32Array(7)));o.frequency.value=120;H=A.createGain();H.gain.value=.5;o.connect(H).connect(M);o.start();var L=A.sampleRate*2,nb=A.createBuffer(1,L,A.sampleRate),d=nb.getChannelData(0);for(var i=0;i<L;i++)d[i]=Math.random()*2-1;var ns=A.createBufferSource();ns.buffer=nb;ns.loop=true;var bp=A.createBiquadFilter();bp.type='bandpass';bp.frequency.value=2600;bp.Q.value=.9;B=A.createGain();B.gain.value=0;var q=A.createOscillator();q.type='square';q.frequency.value=120;var qg=A.createGain();qg.gain.value=.12;q.connect(qg).connect(B.gain);ns.connect(bp).connect(B).connect(M);ns.start();q.start();N=nb}var N;function T(t,v){var s=A.createBufferSource();s.buffer=N;var h=A.createBiquadFilter();h.type='highpass';h.frequency.value=1800;var g=A.createGain();g.gain.setValueAtTime(v,t);g.gain.exponentialRampToValueAtTime(.001,t+.03);s.connect(h).connect(g).connect(M);s.start(t,Math.random(),.04);H.gain.setValueAtTime(.2,t);H.gain.setTargetAtTime(.5,t+.02,.03)}function D(e){var m=/animation-delay:([0-9.]+)s/.exec(e.getAttribute('style')||'');return m?+m[1]:0}function light(){var s=document.querySelector('svg'),c=s.cloneNode(true);s.parentNode.replaceChild(c,s);if(!on)return;var t0=A.currentTime+.05;M.gain.cancelScheduledValues(t0);M.gain.setValueAtTime(0,t0);M.gain.linearRampToValueAtTime(.14,t0+.3);c.querySelectorAll('.l,.f').forEach(function(e){var d=D(e);[.08,.2,.38].forEach(function(x,i){T(t0+d+x,.5-.12*i)})});var f=c.querySelector('.f');clearInterval(window.F);if(f){var k=0,b0=t0+D(f)+3,z=function(){var b=b0+7*k++;[6.37,6.58,6.72].forEach(function(x){T(b+x,.4)})};z();window.F=setInterval(z,7000)}}document.addEventListener('click',function(){if(!A)G();if(A.state!=='running')A.resume();on=!on;document.getElementById('o').textContent=on?'SOUND ON':'SOUND OFF';if(on)light();else M.gain.setTargetAtTime(0,A.currentTime,.05)});";var sn='<div id="o">CLICK FOR SOUND</div><script>'+Ce+"<\/script></body></html>";function Zt(t){let e=t.split(" ");if(e.length===1&&e[0].length===4)return`${e[0].slice(0,2)}|${e[0].slice(2)}`;let n=e.map(i=>i.length*Y-j),o=(i,a)=>{let l=Math.min(Math.floor(3e4/i),Math.floor(3e4/a),300);return l<100?Math.min(Math.floor(35200/i),Math.floor(35200/a)):l},r=null,s=new Set;for(let i=0;i<e.length;i++){let a=-F;for(let l=i;l<e.length;l++){a+=F+n[l]+j-(l===i?j:0);let d=l===i?n[i]:a;if(s.has(d))continue;s.add(d);let p=[[]],h=-1;for(let w=0;w<e.length;w++){let b=h<0?n[w]:h+F+j+n[w];h>=0&&b>d?(p.push([w]),h=n[w]):(p[p.length-1].push(w),h=b)}let g=0;for(let w of p){let b=w.reduce((T,N,L)=>T+n[N]+(L?F+j:0),0);b>g&&(g=b)}let $=o(g,p.length*X-Wt);(!r||$>r.S||$===r.S&&p.length<r.lines.length)&&(r={S:$,lines:p})}}return r.lines.map(i=>i.map(a=>e[a]).join(" ")).join("/")}var Ne=`function f(v){return Math.floor(v/10)+'.'+v%10}function e(v){var c=v%100;return Math.floor(v/100)+'.'+(c<10?'0':'')+c}function U(r,o,X,Y,S,d,q){var k=Math.max(S,160),dx=f(Math.floor(4000/k)),dy=f(Math.floor(6000/k)),y=r.charAt(0)=='#',l=function(c,x){return y?'<use href="'+r+'" class="'+c+'"'+(x||'')+'/>':'<rect '+r+' class="'+c+'"'+(x||'')+'/>'};return '<g transform="translate('+f(Math.floor(X/10))+' '+f(Math.floor(Y/10))+') scale('+e(S)+')" '+(o==8?'class="r" color="#fff"':'color="'+C[o]+'"')+'>'+l('s',y?' x="'+dx+'" y="'+dy+'"':' transform="translate('+dx+' '+dy+')"')+l('u')+'<g class="'+(q?'f':'l')+'" style="animation-delay:'+(q?e(d)+'s,'+e(d+300)+'s':e(d)+'s')+'">'+l('a')+l('b')+l('g')+l('c')+'</g></g>'}var g=[],i,b,n=0,u=[],cs=[],ws=[0],W=0,w=0,lines=1,words=1,seed=7;for(i=0;i<h.length;i+=2)g.push(parseInt(h.substr(i,2),16));for(i=0;i<g.length;i++){b=g[i];seed=(seed+b*(i+1))&0x7fffffff;if(b==235||b==236){ws[lines-1]=w-18;w=0;lines++;ws.push(0);if(b==235)words++}else if(b==234){w+=42;words++}else{w+=78;n++;u[b%26]=1;if(cs.indexOf(Math.floor(b/26))<0)cs.push(Math.floor(b/26))}}ws[lines-1]=w-18;for(i=0;i<lines;i++)if(ws[i]>W)W=ws[i];var H=lines*96-16,S=Math.min(Math.floor(30000/W),Math.floor(30000/H),300);if(S<100)S=Math.min(Math.floor(35200/W),Math.floor(35200/H));var k=Math.max(S,160),z=function(p){return f(Math.floor(p*100/k))},df='',wl='';for(i=0;i<26;i++)if(u[i])df+='<path id="'+String.fromCharCode(65+i)+'" d="'+P[i]+'"/>';for(var r=0;r<16;r++)for(var c=-1;c<6;c++)wl+='<rect x="'+(c*72+(r%2?0:36))+'" y="'+r*26+'" width="72" height="26"/>';var s='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400" width="400" height="400"><defs>'+D+df+'</defs><style>.t use,.t rect{fill:none;stroke-linecap:round;stroke-linejoin:round}.s{stroke:#000;stroke-opacity:.45;stroke-width:'+z(70)+';filter:url(#c)}.u{stroke:currentColor;stroke-opacity:.2;stroke-width:'+z(60)+'}.a{stroke:currentColor;stroke-width:'+z(180)+';opacity:.45;filter:url(#a)}.b{stroke:currentColor;stroke-width:'+z(100)+';opacity:.85;filter:url(#b)}.g{stroke:currentColor;stroke-width:'+z(60)+'}.c{stroke:#fff;stroke-width:'+z(24)+';opacity:.85}'+T+'<rect width="400" height="400" fill="url(#v)"/><g fill="none" stroke="#000" stroke-opacity=".38" stroke-width="2">'+wl+'</g><g class="t">',Y0=Math.floor((40000-H*S)/2);if(n>1&&cs.length==1){var p=Math.floor(1600/S)+4;s+=U('x="-'+p+'" y="-'+p+'" width="'+(W+2*p)+'" height="'+(H+2*p)+'" rx="'+p+'"',cs[0],Math.floor((40000-W*S)/2),Y0,S,10,0)}var q=seed%7==0?(seed>>3)%n:-1,R=seed,wd=0,j=0,li=0,x=Math.floor((40000-ws[0]*S)/2),y=Y0;for(i=0;i<g.length;i++){b=g[i];if(b==234){x+=42*S;wd++}else if(b==235||b==236){if(b==235)wd++;li++;x=Math.floor((40000-ws[li]*S)/2);y+=96*S}else{R=(Math.imul(R,1103515245)+12345)&0x7fffffff;s+=U('#'+String.fromCharCode(65+b%26),Math.floor(b/26),x,y,S,20+Math.floor(wd*160/words)+((R>>16)%24),j==q);x+=78*S;j++}}return s+'</g></svg>'`,an=`(function(h){var D='${Yt}',T='${zt}',P='${v.map(t=>J[t]).join(",")}'.split(','),C=[${D.slice(0,8).map(([,t])=>`'${t}'`).join(",")}];`+Ne+"})";var He=t=>new Promise(e=>setTimeout(e,t)),mt=class extends Error{constructor(e){super(e.message||"RPC error"),this.code=e.code,this.data=e.data}},wt=class{constructor(e){this.url=e,this.n=0,this.single=!1}async post(e,n=4){for(let o=0;;o++)try{let r=await fetch(this.url,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)});if(r.status===429||r.status>=500)throw new Error(`The network is busy (${r.status}).`);return await r.json()}catch(r){if(o>=n)throw r;await He(250*2**o)}}async send(e,n=[]){let o=await this.post({jsonrpc:"2.0",id:++this.n,method:e,params:n});if(!o||typeof o!="object")throw new Error("The network gave an empty answer.");if(o.error)throw new mt(o.error);return o.result}async batch(e,n=40){let o=[];for(let r=0;r<e.length;r+=n){let s=e.slice(r,r+n);o.push(...this.single||s.length===1?await this.each(s):await this.chunk(s))}return o}async chunk(e){let n=e.map(([i,a])=>({jsonrpc:"2.0",id:++this.n,method:i,params:a})),o=await this.post(n),r=Array.isArray(o)?o:[],s=new Map(r.filter(i=>i&&typeof i=="object").map(i=>[i.id,i]));return n.some(i=>s.has(i.id))?n.map(i=>{let a=s.get(i.id);return!a||a.error?{error:a?a.error:{message:"no answer"}}:a.result}):(this.single=!0,this.each(e))}async each(e,n=6){let o=new Array(e.length),r=0,s=async()=>{for(;r<e.length;){let i=r++;try{o[i]=await this.send(e[i][0],e[i][1])}catch(a){if(!(a instanceof mt))throw a;o[i]={error:{message:a.message,code:a.code,data:a.data}}}}};return await Promise.all(Array.from({length:Math.min(n,e.length)},s)),o}};var Et=t=>t?String(t).toLowerCase():null,St="nnwords.wallet",At={get(){try{return JSON.parse(localStorage.getItem(St)||"null")}catch{return null}},set(t){try{t?localStorage.setItem(St,JSON.stringify(t)):localStorage.removeItem(St)}catch{}}},yt=class{constructor(e,n){this.cfg=e,this.onChange=n,this.found=[],this.hooked=new WeakSet,this.provider=null,this.account=null,addEventListener("eip6963:announceProvider",o=>{let r=o.detail;r&&r.info&&r.provider&&!this.found.some(s=>s.info.uuid===r.info.uuid)&&(this.found.push(r),queueMicrotask(()=>this.onChange("found")))}),dispatchEvent(new Event("eip6963:requestProvider"))}list(){return this.found.length?this.found:window.ethereum?[{info:{uuid:"injected",name:"Browser wallet",icon:""},provider:window.ethereum}]:[]}attach(e,n){let o=e.provider;this.provider=o,this.account=n,At.set({rdns:e.info.rdns||"",name:e.info.name||""}),o.on&&!this.hooked.has(o)&&(this.hooked.add(o),o.on("accountsChanged",r=>{o===this.provider&&(this.account=Et(r&&r[0]),this.onChange("account"))}),o.on("chainChanged",()=>{o===this.provider&&this.onChange("chain")}))}async connect(e){let n=await e.provider.request({method:"eth_requestAccounts"}),o=Et(n&&n[0]);if(!o)throw new Error("The wallet did not share an account.");this.attach(e,o);let r=null;try{await this.chain()}catch(s){r=s}if(this.onChange("account"),r)throw Object.assign(new Error(r.message||"The wallet did not switch networks."),{code:r.code,data:r.data,connected:!0})}async restore(){let e=At.get();if(!e)return!1;let n=a=>e.rdns?a.info.rdns===e.rdns:a.info.name===e.name,o=null;for(let a=0;a<25&&!o&&!this.account;a++)o=this.list().find(n)||null,o||await new Promise(l=>setTimeout(l,100));if(!o||this.account)return!1;let r=null;try{r=await o.provider.request({method:"eth_accounts"})}catch{return!1}let s=Et(r&&r[0]);if(!s||this.account)return!1;this.attach(o,s);let i=!0;try{i=Number(await o.provider.request({method:"eth_chainId"}))===this.cfg.chain}catch{}return this.onChange("account"),i?!0:"chain"}disconnect(){At.set(null),this.provider=null,this.account=null,this.onChange("account")}async chain(){let e="0x"+this.cfg.chain.toString(16),n=async()=>Number(await this.provider.request({method:"eth_chainId"}))===this.cfg.chain;if(!await n())try{await this.provider.request({method:"wallet_switchEthereumChain",params:[{chainId:e}]})}catch(o){if(!((o&&(o.code??(o.data&&o.data.originalError&&o.data.originalError.code)))===4902||/unrecognized chain|wallet_addEthereumChain/i.test(String(o&&o.message))))throw o;let i={chainId:e,chainName:this.cfg.name,rpcUrls:[this.cfg.rpc],nativeCurrency:{name:"Ether",symbol:"ETH",decimals:18}};this.cfg.explorer&&(i.blockExplorerUrls=[this.cfg.explorer]),await this.provider.request({method:"wallet_addEthereumChain",params:[i]}),await n()||await this.provider.request({method:"wallet_switchEthereumChain",params:[{chainId:e}]})}}async send(e){return await this.chain(),this.provider.request({method:"eth_sendTransaction",params:[{from:this.account,...e}]})}};var Ie=(1n<<256n)-1n,bt=t=>t.startsWith("0x")?t.slice(2):t,Oe=t=>Array.from(t,e=>e.toString(16).padStart(2,"0")).join("");function ee(t){let e=bt(t),n=new Uint8Array(e.length>>1);for(let o=0;o<n.length;o++)n[o]=parseInt(e.substr(o*2,2),16);return n}var B=t=>(BigInt(t)&Ie).toString(16).padStart(64,"0"),Fe=t=>t+"0".repeat((64-t.length%64)%64);function te(t){let e=typeof t=="string"?bt(t):Oe(t);return B(e.length/2)+Fe(e)}function Be(t,e){if(t==="bytes")return te(e);if(t==="uint256[]")return B(e.length)+e.map(B).join("");if(t==="bytes[]"){let n=e.map(te),o=e.length*32,r=n.map(s=>{let i=o;return o+=s.length/2,B(i)});return B(e.length)+r.join("")+n.join("")}throw new Error(`type ${t}`)}function Re(t,e){let n=[],o=[],r=t.length*32;return t.forEach((s,i)=>{let a=e[i];if(s==="uint256")n.push(B(a));else if(s==="address")n.push(bt(a).toLowerCase().padStart(64,"0"));else if(s==="bool")n.push(B(a?1:0));else{let l=Be(s,a);n.push(B(r)),o.push(l),r+=l.length/2}}),n.join("")+o.join("")}var ne=(t,e=[],n=[])=>"0x"+t+Re(e,n),R=class{constructor(e){this.h=bt(e||"")}word(e){return this.h.slice(e*64,e*64+64)||"0"}uint(e){return BigInt("0x"+this.word(e))}num(e){return Number(this.uint(e))}addr(e){return"0x"+this.word(e).slice(24)}bool(e){return this.uint(e)!==0n}bytes(e){let n=this.num(e)*2,o=Number(BigInt("0x"+this.h.slice(n,n+64)))*2;return ee(this.h.slice(n+64,n+64+o))}};R.prototype.at=function(t){return this.num(t)*2};R.prototype.uints=function(t){let e=this.at(t),n=Number(BigInt("0x"+this.h.slice(e,e+64))),o=[];for(let r=0;r<n;r++)o.push(BigInt("0x"+this.h.slice(e+64+r*64,e+128+r*64)));return o};R.prototype.addrs=function(t){return this.uints(t).map(e=>"0x"+e.toString(16).padStart(40,"0"))};R.prototype.bytesList=function(t){let e=this.at(t),n=e+64,o=Number(BigInt("0x"+this.h.slice(e,e+64))),r=[];for(let s=0;s<o;s++){let i=n+Number(BigInt("0x"+this.h.slice(n+s*64,n+64+s*64)))*2,a=Number(BigInt("0x"+this.h.slice(i,i+64)))*2;r.push(ee(this.h.slice(i+64,i+64+a)))}return r};var oe=t=>Number(BigInt(t));var Qe=t=>new Promise(e=>setTimeout(e,t)),qe={ContractsCannotMint:"Free letters come only to a wallet sending its own transaction, not through a contract.",FreeMintUsed:"This wallet has taken its two free letters.",WrongPayment:"The price is not what was sent. Reload and try again.",BadText:"Letters A to Z, with one space or line break between them.",NotYours:"One of these letters or signs is not in this wallet any more. Reload.",NotALetter:"One of these tokens is a sign, not a letter. Reload.",NotLitYet:"A letter is still lighting up. Try again in a second.",WrongLetter:"A letter does not match its place. Reload.",TextTaken:"These words are lit already.",SizeFull:"Every place of this size is taken. Put out one of your signs of this size to take its place.",TokenDoesNotExist:"There is no such token."};function Pe(t){let e=new Set,n=o=>{if(!o||e.has(o))return null;if(typeof o=="string")return/^0x[0-9a-fA-F]{8}/.test(o)?o:null;if(typeof o!="object")return null;e.add(o);for(let r of["data","error","originalError","cause","info"]){let s=n(o[r]);if(s)return s}return null};return n(t)}function tt(t,e){if(t&&(t.code===4001||t.code==="ACTION_REJECTED"))return"Rejected in the wallet.";let n=Pe(t);if(n){let r=e.err[n.slice(2,10).toLowerCase()];if(r)return qe[r]||r}let o=String(t&&t.message||t||"Something went wrong.");return/user (rejected|denied)|rejected the request/i.test(o)?"Rejected in the wallet.":/insufficient funds/i.test(o)?"Not enough ETH in this wallet.":/nonce too (high|low)|invalid nonce/i.test(o)?"The wallet's transaction count does not match the chain. Reset the account's activity in the wallet and try again.":/failed to fetch|networkerror|load failed/i.test(o)?"The network does not answer.":o.length>160?o.slice(0,160):o}var xt=class{constructor(e,n,o,r){this.cfg=e,this.rpc=n,this.wallet=o,this.ABI=r,this.to=e.nnwords}data(e,n=[],o=[]){return ne(this.ABI.fn[e],n,o)}async read(e){return(await this.rpc.batch(e.map(([o,r,s])=>["eth_call",[{to:this.to,data:this.data(o,r,s)},"latest"]]))).map(o=>o&&o.error?null:new R(o))}async now(e){let n=await this.read(e);if(n.some(o=>!o))throw new Error("Could not read the chain. Try again.");return n}async overview(e){let n=[["stats"],["standing"],["waiting"]];e&&n.push(["freeLeft",["address"],[e]]);let[o,r,s,i]=await this.now(n),a=[0,1,2,3,4,5,6];return{tokens:o.num(0),live:o.num(1),signsEver:o.num(2),paid:o.uint(3),standing:a.map(l=>r.num(l)),waiting:a.map(l=>s.uint(l)),unwrittenFrom:o.num(5),freeLeft:i?i.num(0):null}}async holdings(e){let n=[],o=[];for(let r=0;;r+=500){let[s]=await this.now([["holdingsOf",["address","uint256","uint256"],[e,r,500]]]),i=s.uints(0),a=s.uints(1),l=s.uints(2);if(i.forEach((d,p)=>{let h=Number(a[p]);if(h&2048)o.push({id:Number(d),size:h>>12&7,holds:l[p]});else{let g=h>>9&3;n.push({id:Number(d),state:g,unlit:g===2,ready:g===1,letter:h&31,colour:h>>5&15,holds:l[p]})}}),i.length<500)break}if(o.length){let r=await this.now(o.map(s=>["glyphsOf",["uint256"],[s.id]]));o.forEach((s,i)=>s.glyphs=r[i].bytes(0))}return o.sort((r,s)=>s.id-r.id),{letters:n,signs:o}}async wall(e,n){let[o]=await this.now([["latest",["uint256","uint256"],[e,n]]]),r=o.uints(0).map(Number),s=o.bytesList(1),i=o.addrs(2);return{signs:r.map((a,l)=>({id:a,glyphs:s[l],owner:i[l]})),next:o.num(3)}}async signOfText(e){let[n]=await this.now([["signOfText",["bytes"],[new TextEncoder().encode(e)]]]);return n.num(0)}async write(e,n,o,r,s){let i=this.wallet.account,a=this.data(e,n,o),l="0x"+BigInt(r).toString(16);s("Checking the transaction."),await this.rpc.send("eth_call",[{from:i,to:this.to,data:a,value:l},"latest"]),s("Confirm in the wallet.");let d=String(await this.wallet.send({to:this.to,data:a,value:l})).toLowerCase();s(`Sent ${d.slice(0,10)}. Waiting for the block.`);let p=0;for(let h=0;h<300;h++){let g=null;try{g=await this.rpc.send("eth_getTransactionReceipt",[d]),p=0}catch{if(++p>5)throw new Error(`Sent ${d.slice(0,10)}, but the network stopped answering. Check the wallet.`)}if(g){if(g.status!=="0x1")throw new Error("The transaction failed on chain.");return g}await Qe(400)}throw new Error("No receipt after two minutes. Check the wallet.")}minted(e){return e.logs.filter(n=>n.address.toLowerCase()===this.to&&n.topics[0]===this.ABI.ev.Transfer&&n.topics[1]==="0x"+"0".repeat(64)).map(n=>oe(n.topics[3]))}};var m=null,S,et,$t,Ct=0;function _e(){m=new(window.AudioContext||window.webkitAudioContext),S=m.createGain(),S.gain.value=0,S.connect(m.destination);let t=m.createOscillator();t.setPeriodicWave(m.createPeriodicWave(new Float32Array([0,1,.55,.32,.2,.12,.08]),new Float32Array(7))),t.frequency.value=120,et=m.createGain(),et.gain.value=.5,t.connect(et).connect(S),t.start();let e=m.sampleRate*2;$t=m.createBuffer(1,e,m.sampleRate);let n=$t.getChannelData(0);for(let l=0;l<e;l++)n[l]=Math.random()*2-1;let o=m.createBufferSource();o.buffer=$t,o.loop=!0;let r=m.createBiquadFilter();r.type="bandpass",r.frequency.value=2600,r.Q.value=.9;let s=m.createGain();s.gain.value=0;let i=m.createOscillator();i.type="square",i.frequency.value=120;let a=m.createGain();a.gain.value=.12,i.connect(a).connect(s.gain),o.connect(r).connect(s).connect(S),o.start(),i.start()}function re(t,e){let n=m.createBufferSource();n.buffer=$t;let o=m.createBiquadFilter();o.type="highpass",o.frequency.value=1800;let r=m.createGain();r.gain.setValueAtTime(e,t),r.gain.exponentialRampToValueAtTime(.001,t+.03),n.connect(o).connect(r).connect(S),n.start(t,Math.random(),.04),et.gain.setValueAtTime(.2,t),et.gain.setTargetAtTime(.5,t+.02,.03)}function se(t){m||_e(),m.state!=="running"&&m.resume();let e=m.currentTime+.05;S.gain.cancelScheduledValues(e),S.gain.setValueAtTime(0,e),S.gain.linearRampToValueAtTime(.14,e+.3);let n=[...t.matchAll(/class="(l|f)" style="animation-delay:([0-9.]+)s/g)];for(let r of n)[.08,.2,.38].forEach((s,i)=>re(e+Number(r[2])+s,.5-.12*i));clearInterval(Ct);let o=n.find(r=>r[1]==="f");if(o){let r=0,s=e+Number(o[2])+3,i=()=>{let a=s+7*r++;[6.37,6.58,6.72].forEach(l=>re(a+l,.4))};i(),Ct=setInterval(i,7e3)}}function ie(){clearInterval(Ct),m&&S.gain.setTargetAtTime(0,m.currentTime,.05)}var x=O,rt=I;x.nnwords=x.nnwords.toLowerCase();var u=t=>document.getElementById(t),E=(t,e,n)=>{let o=document.createElement(t);return e&&(o.className=e),n!==void 0&&(o.innerHTML=n),o},ot=t=>String(t).replace(/[&<>"]/g,e=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"})[e]),Qt=t=>t.slice(0,6)+".."+t.slice(-4),A=(t,e=6)=>{let o=(BigInt(t)/10n**12n).toString().padStart(7,"0"),r=o.slice(0,-6),s=o.slice(-6).slice(0,e).replace(/0+$/,"");return s?`${r}.${s}`:r},z=t=>"data:image/svg+xml;base64,"+btoa(t),Ve=10n**14n,ce=t=>Ve*3n**BigInt(t),Mt=D.map(([t])=>t),le=D.map(([,t])=>t[0]==="#"?t:"#fff"),qt=t=>t>=7,kt=234,fe=235,Pt=236,vt=x.opensea?`https://opensea.io/collection/${x.opensea}`:"",je=new wt(x.rpc),c={account:null,over:null,letters:[],signs:[],wall:[],wallNext:0,colour:-1,picks:new Map,replace:0,busy:!1,taken:new Map},Q=new yt(x,t=>{if(t==="found")return Ot();t==="account"&&(c.account=Q.account,c.letters=[],c.signs=[],c.picks.clear(),Ot(),W())}),M=new xt(x,je,Q,rt);function Ge(t){let e=t.toUpperCase().replace(/\n/g,"/").replace(/[^A-Z /|]/g,"");return e=e.replace(/[ /|]+/g,n=>n.includes("/")?"/":n.includes("|")?"|":" "),e.replace(/^[ /|]+|[ /|]+$/g,"")}function _t(){let t=Ge(u("text").value);return t?u("auto").checked?Zt(t.replace(/\|/g,"").replace(/\//g," ").replace(/ +/g," ")):t:""}var Vt=t=>[...t].filter(e=>e>="A"&&e<="Z").map(e=>e.charCodeAt(0)-65),ue=t=>t.replace(/\|/g,"").replace(/\//g," ");function Ht(t,e){let n=[],o=0;for(let r of t)r===" "?n.push(kt):r==="/"?n.push(fe):r==="|"?n.push(Pt):n.push(r.charCodeAt(0)-65+26*e[o++%e.length]);return n}function he(t){let e="";for(let n of t)e+=n<kt?v[n%26]:n===Pt?"":" ";return e}function _(t){let e=he(t),n=Array.from(t).filter(r=>r<kt).length,o=e;if(e.length>48){let r=e.lastIndexOf(" ",48);o=r>0?e.slice(0,r):e.slice(0,48)}return`${ht[dt(n)]}%: ${o.toLowerCase()}`}function jt(t){let e=Vt(t),n=new Set,o=new Array(e.length).fill(null),r=c.letters.filter(a=>!a.unlit),s=a=>!n.has(a.id),i=(a,l)=>{n.add(l.id),o[a]={id:l.id,colour:l.colour}};return e.forEach((a,l)=>{let d=c.picks.get(l);if(d===void 0)return;let p=r.find(h=>h.id===d&&h.letter===a&&s(h));p&&i(l,p)}),e.forEach((a,l)=>{if(o[l])return;let d=r.filter(h=>h.letter===a&&s(h)),p=c.colour>=0?d.find(h=>h.colour===c.colour):d.find(h=>!qt(h.colour))||d[0];p&&i(l,p)}),{need:e,out:o}}function De(t,e){let n=Vt(t)[e],{out:o}=jt(t),r=new Set(o.filter((l,d)=>l&&d!==e).map(l=>l.id)),s=c.letters.filter(l=>!l.unlit&&l.letter===n&&!r.has(l.id)).sort((l,d)=>l.colour-d.colour||l.id-d.id);if(!s.length)return;let i=o[e]?o[e].id:-1,a=s.findIndex(l=>l.id===i);return s[(a+1)%s.length].id}function Ye(t){let e=Lt(t),n=e.S,o=Math.floor((4e4-e.H*n)/2),r=0,s=Math.floor((4e4-e.widths[0]*n)/2),i=o,a=[];for(let l of t)l===kt?s+=F*n:l===fe||l===Pt?(r++,s=Math.floor((4e4-e.widths[r]*n)/2),i+=X*n):(a.push([s/100,i/100,60*n/100,80*n/100]),s+=Y*n);return a}function ze(t,e,n){if(!e.length)return t;let o=t.indexOf('<g class="t">'),r=t.slice(o).split('<g transform="translate('),s=n?2:1;for(let i of e)r[i+s]&&(r[i+s]=r[i+s].replace('" ','" opacity=".16" '));return t.slice(0,o)+r.join('<g transform="translate(')}var It="",ae=0;function C(){let t=_t(),e=u("facts"),n=u("need"),o=u("replace"),r=u("light");if(!t){u("pv").src=z(Z(Ht("TYPE|YOUR/WORDS",[6]))),e.innerHTML="Up to 256 letters. Spaces are free.",n.innerHTML=o.innerHTML="",r.disabled=!0,r.textContent="LIGHT IT";return}let s=Vt(t),i=s.length;if(i>256){e.innerHTML=`<b class="bad">${i} letters: a sign holds 256 at most.</b>`,n.innerHTML=o.innerHTML="",r.disabled=!0;return}let a=dt(i),{out:l}=jt(t),d=c.colour<0?6:c.colour,p=l.map(f=>f?f.colour:d),h=Ht(t,p),g=l.map((f,y)=>f?-1:y).filter(f=>f>=0),$=i>1&&p.every(f=>f===p[0]);u("pv").src=z(ze(Z(h),g,$)),u("pv").dataset.boxes=JSON.stringify(Ye(h));let w=c.over,b=ut[a],T=w?w.standing[a]:0,N=b&&T>=b,L=ue(t),q=c.taken.get(L),V=w&&w.standing[a]===0&&w.waiting[a]>0n?`<span class="ok">first of its size: takes ${A(w.waiting[a])} ETH waiting</span>`:"";if(e.innerHTML=`<span>name <b>${ot(_(h))}</b></span><span><b>${i}</b> letter${i===1?"":"s"}</span><span>size <b>${P[a]}</b>, <b>${ht[a]}%</b> of the signs' share</span><span><b>${A(ce(a))}</b> ETH</span><span>${b?`<b>${Math.max(0,b-T)}</b> of ${b} places left`:"no limit of this size"}</span>`+V+(q?`<span class="bad">lit already: sign ${q}</span>`:q===0?'<span class="ok">free to light</span>':""),!c.account)n.innerHTML="Connect a wallet to light it with your letters.";else if(g.length){let f={};for(let H of g)f[v[s[H]]]=(f[v[s[H]]]||0)+1;let y=Object.keys(f).sort().map(H=>`<b>${H}</b>${f[H]>1?" x"+f[H]:""}`).join(", "),we=c.letters.some(H=>H.unlit);n.innerHTML=`You need ${g.length} more: ${y}${c.colour>=0?` in ${Mt[c.colour].toLowerCase()}`:""}. `+(we?"Some of your letters are still lighting up. ":"")+(vt?`Find them on the <a href="${vt}" target="_blank" rel="noopener noreferrer">market</a>, or ask a friend for their two free letters.`:"Find them on the market.")}else{let f=l.filter(y=>qt(y.colour)).length;n.innerHTML=`Your letters are enough${f?`, ${f} of them gold or prism`:""}. Click a letter in the picture to use another of yours.`}o.innerHTML="";let U=!N;if(N&&c.account){let f=c.signs.filter(y=>y.size===a);f.length?(f.some(y=>y.id===c.replace)||(c.replace=f[0].id),o.innerHTML=`Every place of size ${P[a]} is taken. Put out one of yours to take its place: <select id="rsel">`+f.map(y=>`<option value="${y.id}"${y.id===c.replace?" selected":""}>${ot(_(y.glyphs))} (holds ${A(y.holds)} ETH)</option>`).join("")+"</select>",U=!0):o.innerHTML=`Every place of size ${P[a]} is taken. Buy a sign of this size on the market, then come back: lighting puts it out and takes its place in one transaction.`}else c.replace=0;r.textContent=c.account?"LIGHT IT":"CONNECT TO LIGHT IT",r.disabled=c.account?g.length>0||!!q||!U||c.busy:!1,L!==It&&(It=L,clearTimeout(ae),c.taken.has(L)||(ae=setTimeout(async()=>{try{c.taken.set(L,await M.signOfText(L)),C()}catch{}},350)))}function Ot(){let t=u("wallet");if(t.innerHTML="",c.account){let n=E("button","small ghost",Qt(c.account)+" &times;");n.title="Disconnect",n.onclick=()=>Q.disconnect(),t.append(n);return}let e=Q.list();if(!e.length){t.innerHTML='<span class="dim">No wallet in this browser</span>';return}for(let n of e){let o=E("button","small","CONNECT"+(e.length>1?" "+ot(n.info.name||""):""));o.onclick=async()=>{try{await Q.connect(n)}catch(r){k("minemsg",tt(r,rt),!0)}},t.append(o)}}function de(){let t=c.over;if(!t)return;let e=t.standing.reduce((s,i)=>s+i,0),n=[2,3,4,5,6].map(s=>`<div class="bar"><span>size ${P[s]}, ${ht[s]}%</span><i data-k="${s}"></i><b>${t.standing[s]}/${ut[s]}</b></div>`).join(""),o=[0,1,2,3,4,5,6].filter(s=>t.standing[s]===0&&t.waiting[s]>0n);u("stats").innerHTML=`<div class="nums"><div><b>${t.live}</b>letters not burned</div><div><b>${e}</b>signs standing</div><div><b>${A(t.paid,4)}</b>ETH paid in, 80% to holders</div><div><b>${o.length?A(t.waiting[o[o.length-1]],4):"0"}</b>${o.length?`ETH waits for the first sign of ${P[o[o.length-1]]}`:"ETH waiting"}</div></div><div class="bars">${n}</div>`;for(let s of u("stats").querySelectorAll(".bar i"))s.style.width=Math.min(100,t.standing[s.dataset.k]*100/ut[s.dataset.k])+"%";let r=t.freeLeft;u("mint").disabled=c.busy||c.account&&r===0,u("mint").textContent=c.account?r===0?"YOUR 2 FREE LETTERS ARE TAKEN":`GET ${r} FREE LETTER${r>1?"S":""}`:"CONNECT TO GET 2 FREE LETTERS"}function We(){let t=u("tubes");if(t.innerHTML="",!c.account){t.innerHTML='<span class="dim">Your letters show here.</span>',u("tubeholds").textContent="",u("claim").disabled=!0;return}c.letters.length||(t.innerHTML='<span class="dim">No letters yet.</span>');let e=c.letters.filter(s=>s.ready).length;u("writeit").hidden=!e,u("readynote").textContent=e?`${e} of your letters ${e>1?"are":"is"} lit but not written down yet: the next transaction anyone sends to NNwords does it, and until then the market shows ${e>1?"them":"it"} unlit.`:"";let n=[...c.letters].sort((s,i)=>s.unlit-i.unlit||s.letter-i.letter||s.colour-i.colour||s.id-i.id);for(let s of n.slice(0,600)){let i=E("button","tube"+(s.unlit?" unlit":"")+(s.ready?" ready":""),s.unlit?"&#8725;":v[s.letter]);s.unlit||(i.style.color=le[s.colour]),s.colour===8&&!s.unlit&&i.classList.add("prism"),i.title=s.unlit?`letter ${s.id}, lighting up`:`letter ${v[s.letter]}, ${Mt[s.colour].toLowerCase()}, ${s.id}${s.ready?", not written down yet":""}`,i.onclick=()=>Ke(s),t.append(i)}n.length>600&&t.append(E("span","dim",` and ${n.length-600} more`));let o=c.letters.reduce((s,i)=>s+i.holds,0n),r=c.signs.reduce((s,i)=>s+i.holds,0n);u("tubeholds").innerHTML=`Your letters hold <b>${A(o)}</b> ETH, your signs <b>${A(r)}</b> ETH.`,u("claim").disabled=c.busy||o+r===0n}function pe(t,e){let n=E("figure","sign"),o=E("img");if(o.src=z(Z(Array.from(t.glyphs))),o.alt=he(t.glyphs),o.onclick=()=>me(t),n.append(o),n.append(E("figcaption","",`<span>${t.id}</span> ${ot(_(t.glyphs))}`)),e){let r=E("div","row");r.append(E("span","dim",`holds ${A(t.holds)} ETH`));let s=E("button","small ghost","PUT OUT");s.onclick=()=>en(t),r.append(s),n.append(r)}return n}function Ue(){let t=u("mysigns");if(t.innerHTML="",!c.account)return t.innerHTML='<span class="dim">Your signs show here.</span>';if(!c.signs.length)return t.innerHTML='<span class="dim">No signs yet. Write one above.</span>';for(let e of c.signs)t.append(pe(e,!0))}function ge(){let t=u("wall");t.innerHTML="",c.wall.length||(t.innerHTML='<span class="dim">The wall is dark. Light the first sign.</span>');for(let e of c.wall)t.append(pe(e,!1));u("more").hidden=!c.wallNext}var Ft="";function Bt(t,e){Ft=t,u("mimg").src=z(t),u("minfo").innerHTML=e,u("modal").hidden=!1,u("msound").textContent="SOUND"}function Nt(){ie(),u("modal").hidden=!0}var Rt=t=>x.explorer?` <a href="${x.explorer}/token/${x.nnwords}/instance/${t}" target="_blank" rel="noopener noreferrer">explorer</a>`:"";function Ke(t){if(t.unlit)return Bt(Jt(t.id,t.holds),`unlit letter ${t.id}: the hash of the block of its mint picks it as soon as that block is over.${Rt(t.id)}`);Bt(Kt(t.letter,t.colour,t.id,t.holds),`letter ${v[t.letter]}, ${Mt[t.colour].toLowerCase()}, ${t.id}${t.ready?", lit for good with the next transaction to NNwords":""}${Rt(t.id)}`)}function me(t){let e=t.owner?`, held by ${Qt(t.owner)}`:"";Bt(Z(Array.from(t.glyphs)),`<b>${ot(_(t.glyphs))}</b>, sign ${t.id}${e}${Rt(t.id)}`)}function k(t,e,n){let o=u(t);o.textContent=e,o.className="msg"+(n?" bad":"")}async function st(t,e){if(!c.busy){c.busy=!0,de(),C();try{await e(n=>k(t,n))}catch(n){k(t,tt(n,rt),!0)}finally{c.busy=!1,await W()}}}async function Gt(){if(c.account)return!0;let t=Q.list();if(!t.length)return k("minemsg","Install a wallet such as MetaMask or Rabby, then reload.",!0),!1;try{await Q.connect(t[0])}catch(e){k("minemsg",tt(e,rt),!0)}return!!c.account}async function Je(){if(!await Gt())return;let t=c.over&&c.over.freeLeft!==null?c.over.freeLeft:2;t&&await st("minemsg",async e=>{let n=await M.write("mint",["uint256"],[t],0n,e),o=M.minted(n);k("minemsg",`Minted ${o.length} letter${o.length>1?"s":""}. The hash of ${o.length>1?"their":"its"} block picks ${o.length>1?"them":"it"}: a moment.`),setTimeout(W,1500)})}async function Xe(){if(!await Gt())return;let t=_t(),{out:e}=jt(t);if(!t||e.some(s=>!s))return C();let n=e.map(s=>s.id),o=dt(n.length);if(c.replace){let s=c.signs.find(i=>i.id===c.replace);if(s&&!confirm(`Put out "${_(s.glyphs)}" for good? Its place goes to the new sign, and the ${A(s.holds)} ETH it holds comes to you.`))return}let r=e.filter(s=>qt(s.colour)).length;r&&!confirm(`This burns ${r} gold or prism letter${r>1?"s":""}. Light it anyway?`)||await st("lightmsg",async s=>{let i=await M.write("light",["bytes","uint256[]","uint256"],[new TextEncoder().encode(t),n,c.replace||0],ce(o),s),[a]=M.minted(i);c.picks.clear(),c.taken.delete(ue(t));let l=Ht(t,e.map(d=>d.colour));k("lightmsg",`Lit: ${_(l)}, sign ${a}.`),me({id:a,glyphs:l})})}async function Ze(){await Gt()&&await st("minemsg",async t=>{await M.write("capture",[],[],0n,t),k("minemsg","Written down: your letters are lit for good.")})}async function tn(){let t=[...c.letters,...c.signs].filter(n=>n.holds>0n).sort((n,o)=>o.holds>n.holds?1:o.holds<n.holds?-1:0),e=t.slice(0,300).map(n=>n.id);e.length&&await st("minemsg",async n=>{await M.write("claim",["uint256[]"],[e],0n,n),k("minemsg",t.length>300?`Taken from the 300 that held the most; press again for the other ${t.length-300}.`:"Taken. Your letters and signs keep earning.")})}async function en(t){confirm(`Put out "${_(t.glyphs)}"? It burns for good. Its place and its words are free again, and the ${A(t.holds)} ETH it holds comes to you.`)&&await st("minemsg",async e=>{await M.write("unlight",["uint256"],[t.id],0n,e),k("minemsg",`Sign ${t.id} is out.`)})}var nt=null;async function W(){if(nt)return nt;nt=(async()=>{try{let t=c.account,[e,n]=await Promise.all([M.overview(t),t?M.holdings(t):{letters:[],signs:[]}]);if(t!==c.account)return;let o=c.over?c.over.signsEver:-1;if(c.over=e,c.letters=n.letters,c.signs=n.signs,c.taken.clear(),It="",o!==e.signsEver||!c.wall.length){let r=await M.wall(0,24);c.wall=r.signs,c.wallNext=r.next}c.letters.some(r=>r.unlit)&&setTimeout(W,1200)}catch(t){k("minemsg",tt(t,rt),!0)}de(),We(),Ue(),ge(),C()})();try{await nt}finally{nt=null}}function nn(){u("logo").src=z(Xt());let t=u("chips"),e=(n,o)=>{let r=E("button","chip"+(n===c.colour?" on":""),o);n>=0&&(r.style.color=le[n]),n===8&&r.classList.add("prism"),r.onclick=()=>{c.colour=n,c.picks.clear();for(let s of t.children)s.classList.remove("on");r.classList.add("on"),C()},t.append(r)};e(-1,"ANY"),Mt.forEach((n,o)=>e(o,n)),u("text").addEventListener("input",()=>{c.picks.clear(),k("lightmsg",""),C()}),u("auto").addEventListener("change",()=>{c.picks.clear(),C()}),u("pv").addEventListener("click",n=>{let o=_t();if(!o||!c.account)return;let r=n.target.getBoundingClientRect(),s=(n.clientX-r.left)*400/r.width,i=(n.clientY-r.top)*400/r.height,l=JSON.parse(n.target.dataset.boxes||"[]").findIndex(([p,h,g,$])=>s>=p-4&&s<=p+g+4&&i>=h-4&&i<=h+$+4);if(l<0)return;let d=De(o,l);d!==void 0&&c.picks.set(l,d),C()}),u("light").onclick=Xe,u("mint").onclick=Je,u("replace").addEventListener("change",n=>{n.target.id==="rsel"&&(c.replace=Number(n.target.value))}),u("claim").onclick=tn,u("writeit").onclick=Ze,u("more").onclick=async()=>{let n=await M.wall(c.wallNext,24);c.wall.push(...n.signs),c.wallNext=n.next,ge()},u("mclose").onclick=Nt,u("modal").addEventListener("click",n=>{n.target.id==="modal"&&Nt()}),u("msound").onclick=()=>{u("mimg").src=z(Ft.replace("</svg>",`<!--${Date.now()}--></svg>`)),se(Ft),u("msound").textContent="AGAIN"},addEventListener("keydown",n=>{n.key==="Escape"&&Nt()}),u("contracts").innerHTML=`Robinhood Chain: <a href="${x.explorer}/address/${x.nnwords}" target="_blank" rel="noopener noreferrer">${Qt(x.nnwords)}</a>.`+(vt?` <a href="${vt}" target="_blank" rel="noopener noreferrer">NNwords on OpenSea</a>.`:""),Ot(),C(),W(),Q.restore().catch(()=>{}),setInterval(()=>{!c.busy&&document.visibilityState==="visible"&&W()},2e4)}nn();})();</script>
</body>
</html>
