@onceworlds/cli 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/cli.js +287 -83
- package/dist/emulator.js +1274 -333
- package/dist/sdk.js +3 -3
- package/package.json +1 -1
package/dist/emulator.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";(()=>{var He=["#f6dcc5","#ebc29f","#d4a07a","#b07a55","#875839","#5e3d29","#93c9bb","#a8c595","#94bcd3","#ab9bd9","#dca3ad","#b3bccb"],be=["#c95f56","#dc8a4f","#e2bd52","#9cc27a","#5a8a5e","#4f9a8e","#6fb7c8","#5b87c5","#465089","#8b68a8","#dc8fae","#f2eee6","#a9a8ad","#5d5c63","#2b2a30","#80604d"],Fe=["Happy","Grin","Shades","Wink","Surprised","Determined","Joyful","Shy"],qe=["None","Sprout","Cap","Beanie","Crown","Headphones","Horns","Antenna","Bow","Halo","Party hat","Cat ears","Short hair","Tuft","Bob","Spikes","Bun","Curls","Long","Mop"];var Ke=["Plain","Band","Spots","Stripes","Star"];var jo={skin:He.length,shirt:be.length,pants:be.length,face:Fe.length,hat:qe.length,top:Ke.length},Xt=[[5,6],[3,4],[6,7],[9,8],[10,0],[12,13]];function Ve(t){let e=2166136261;for(let c of t)e=Math.imul(e^c.charCodeAt(0),16777619)>>>0;let o=c=>(e=Math.imul(e^e>>>13,2654435761)>>>0,e%c),r=o(He.length),n=r>=6?Xt[r-6][o(2)]:o(be.length),a=o(2)===0?n:[8,13,14,15][o(4)],i=o(5)===0?1:12+o(qe.length-12),s=o(2)===0?0:o(Ke.length);return{skin:r,shirt:n,pants:a,face:o(Fe.length),hat:i,top:s}}var E={roomMaxPlayersDefault:16,roomMaxPlayersCap:30,teamsMax:8,messageBytes:16*1024,presenceBytes:1024,stateKeyLength:64,stateValueBytes:16*1024,stateKeys:256,privateKeys:16,privateValueBytes:4*1024,privateBytesPerPlayer:8*1024,messagesPerSecond:60,messagesPerSecondMin:10,roomBytesPerSecond:128*1024,roomBytesPerSecondMin:16*1024,presenceHz:20,presenceHzMin:5,roomMessagesPerSecond:900,roomBytesPerSecondTotal:2*1024*1024,matchCountdownMs:3e3,matchCountdownMaxMs:1e4,matchIdleMs:45e3,matchAbandonMs:12e4,idleAfterMs:3e4,idleAbandonMs:5*6e4,rankedPairMatchesPerDay:5,chatLength:200,chatIntervalMs:750,chatHistory:50,chatChannelsPerPlayer:10,saveValueBytes:64*1024,saveKeysPerGame:100,saveBytesPerGame:1024*1024,guestSaveBytesPerGame:128*1024,serverDataKeys:128,serverDataBytes:512*1024,serverDataServersPerGame:5e3,serverDataBytesPerGame:64*1024*1024,serverDataIdleDays:120,gameDataKeys:32,gameDataListMax:100,gameDataItemBytes:1024,gameDataValueBytes:8*1024,gameDataMapFields:1e3,gameDataMapPerPlayer:100,gameDataNumberMax:1e15,gameDataWritesPerMinute:30,deployFiles:2e3,deployFileBytes:25*1024*1024,deployHtmlBytes:10*1024*1024,deployPathLength:200,deployTotalBytes:100*1024*1024,envVars:50,envValueBytes:4*1024,envTotalBytes:16*1024,proxyRequestBytes:1024*1024,proxyTextRequestBytes:256*1024,proxySpeechRequestBytes:16*1024,proxyResponseBytes:10*1024*1024,proxyMaxOutputTokens:4096,proxyCallsPerDay:2e3,proxyCallsPerDayMax:1e5,proxyCallsPerPlayerPerDay:100,proxyCallsPerNetworkPerDay:1e3,proxyMediaCallsPerDay:100,proxyMediaCallsPerDayMax:1e4,proxyMediaCallsPerPlayerPerDay:20,proxyMediaCallsPerNetworkPerDay:25,proxyUnitsPerDay:2e6,proxyUnitsPerDayMax:1e8,proxyUnitsPerPlayerPerDay:25e4,proxyUnitsPerGuestPerDay:1e5,proxyUnitsPerNetworkPerDay:5e5,errorReportsPerPage:10,consoleLineLength:2e3,consoleLinesPerSecond:50,gameNameLength:60,gameDescriptionLength:1e3,galleryItems:5,mediaImageBytes:5*1024*1024,mediaVideoBytes:30*1024*1024,mediaGifBytes:1024*1024,mediaGifSide:512,mediaUploadsPerDay:200,mediaBytesPerDay:500*1024*1024,badgesPerGame:50,controlHints:12,controlHintKeys:4,controlKeyLength:12,controlActionLength:40,helpLength:400,badgeNameLength:50,badgeDescriptionLength:200,leaderboardsPerGame:25,leaderboardTop:100,gamesPerOwner:50,gamesCreatedPerCreatorPerDay:3,uploadAccountAgeMs:10080*6e4,deploysPerOwnerPerDay:100,draftsPerOwnerPerDay:1e3,draftsKeptPerGame:3,cliTokensPerAccount:10,cliDeviceCodeSeconds:600,deploymentsKeptPerGame:10,deployBytesPerOwnerPerDay:2*1024*1024*1024,deployEntriesPerOwnerPerDay:1e5,bioLength:500,exportRows:2e3,exportSaveChars:4*1024*1024,exportEveryMs:60*6e4,friendsMax:200,friendRequestsMax:100,friendRequestsIncomingMax:50,friendRequestsPerDay:20,friendRequestsPerNetworkPerDay:120,friendRequestPushesPerDay:5,passwordMinLength:8,passwordMaxLength:72,signupsPerNetworkPerDay:100,signupsPerWidePerDay:300,guestsPerNetworkPerDay:300,guestsPerWidePerDay:1500,visitsPerNetworkPerDay:10,visitSeconds:10,errorsPerDeployment:100,controlButtons:4,controlLabelLength:12,partySize:6,partyChatHistory:50,messageLength:500,messagesPerPage:50,groupChatMembers:20,groupChatNameLength:40,conversationsListed:50,notificationsListed:50,invitesPerRequest:10,inviteLiveMs:30*6e4,partyInviteMs:60*6e4};var Ye=/^[a-z0-9]{12}$/,Z=2;function we(t){return`${t.mode}.${t.max}.${t.teams}.${t.ranked?1:0}${t.min!==Z?`.${t.min}`:""}`}var Zt=/^pub:([a-z0-9-]+)\.(\d+)\.(\d)\.([01])(?:\.(\d+))?:(\d+)$/;function Je(t){let e=Zt.exec(t);if(!e)return null;let o={mode:e[1],max:Number(e[2]),teams:Number(e[3]),ranked:e[4]==="1",min:e[5]===void 0?Z:Number(e[5])};return{...o,name:we(o),n:Number(e[6])}}function Xe(t,e,o){let r=typeof t=="string"?Number(t):t;return typeof r!="number"||!Number.isInteger(r)?Math.min(o,e):Math.min(e,Math.max(1,r))}var We=t=>t.replace(/[\u0000-\u001f\u007f]/g," ").replace(/\s+/g," ").trim();var Qt=/^[a-z0-9][a-z0-9-]{0,19}$/;function Ze(t){if(!t||typeof t!="object")return null;let e=t,o=[];for(let n of Array.isArray(e.buttons)?e.buttons:[]){if(o.length>=E.controlButtons)break;let{id:a,label:i}=n??{};if(typeof a!="string"||!Qt.test(a)||o.some(c=>c.id===a))continue;let s=typeof i=="string"?i.replace(/[\u0000-\u001f\u007f]/g,"").replace(/\s+/g," ").trim().slice(0,E.controlLabelLength).trim():"";o.push({id:a,label:s||a})}let r=e.stick===!0;return r||o.length>0?{stick:r,zone:e.zone==="corner"?"corner":"wide",buttons:o}:null}var K="host:ow.settings",eo=/^[a-z][a-zA-Z0-9]{0,15}$/;function Qe(t){if(!Array.isArray(t))return[];let e=[];for(let o of t){if(e.length>=6)break;let{id:r,label:n,options:a,default:i}=o??{};if(typeof r!="string"||!eo.test(r)||e.some(d=>d.id===r)||!Array.isArray(a))continue;let s=[];for(let d of a){let p=typeof d=="object"&&d!==null?d.value:d;if(typeof p!="string"&&typeof p!="number"||typeof p=="number"&&!Number.isFinite(p)||s.length>=8||s.some(u=>u.value===p))continue;let m=typeof d=="object"&&d!==null&&typeof d.label=="string"?d.label:String(p);s.push({value:p,label:We(m).slice(0,20)||String(p)})}if(s.length<2)continue;let c=typeof n=="string"?We(n).slice(0,24):"";e.push({id:r,label:c||r,options:s,default:s.some(d=>d.value===i)?i:s[0].value})}return e}function et(t,e){let o=e!==null&&typeof e=="object"?e[t.id]:void 0;return t.options.some(r=>r.value===o)?o:t.default}var ve='{"t":"ping"}';var tt=4001,ot=4003,rt=4008,nt=4006;var at="onceworlds:hello",it="onceworlds:connect",to=/^[a-z0-9]{1,32}~(?:(?:0|[1-9]\d{0,3})\.(?:0|[1-9]\d{0,4})\.(?:0|[1-9]\d{0,5}))?~[0-9a-z]{1,11}~[lp]~[A-Za-z0-9_-]{43}$/;function st(t){let e=t!==null&&typeof t=="object"?t.build:void 0;return typeof e=="string"&&to.test(e)?e:null}var lt="onceworlds-console";var pt="allow-scripts allow-pointer-lock allow-forms allow-orientation-lock",dt=["autoplay","gamepad","screen-wake-lock","accelerometer","gyroscope"].map(t=>`${t} *`).join("; "),ct=100*1024*1024;var gt=new Set(["server","join","deploy","watch","player","embed","k","console","tester","live","demo",lt]);var ye="onceworlds:page",oo=["ran","blocked","failed","threw","loaded"];function ht(t){if(t===null||typeof t!="object")return null;let{what:e,detail:o}=t;return typeof e!="string"||!oo.includes(e)?null:{what:e,detail:typeof o=="string"?o.slice(0,200):""}}var ro=`(function(){var n=0,s=function(w,d){if(n++<12)try{parent.postMessage({type:${JSON.stringify(ye)},what:w,detail:String(d).slice(0,200)},"*")}catch(e){}};s("ran",document.readyState);addEventListener("securitypolicyviolation",function(e){s("blocked",e.effectiveDirective+" "+e.blockedURI)});addEventListener("error",function(e){var t=e.target;t&&t.tagName?s("failed",t.tagName+" "+(t.src||t.href)):s("threw",e.message+" "+e.filename+":"+e.lineno)},true);addEventListener("load",function(){s("loaded",typeof onceworlds)})})();`,Fo=`<script>${ro}<\/script>`;function ut(t){return t?.ownCountdown!==!0}var no=/^#(?:[0-9a-f]{3}){1,2}$/i,C={panel:"#111216",text:"#f7f7f8",accent:"#d33e00"},Se=4.5,ke=3,Q=["#4ade80","#15803d"];function xt(t){let e=[];if(t==null)return{look:null,notes:e};if(typeof t!="object")return{look:null,notes:["a look is { accent, panel, text } or null"]};let o=t,r=p=>{let m=o[p];return m==null?null:typeof m=="string"&&no.test(m)?ft(m):(e.push(`${p} is not #rgb or #rrggbb`),null)},n=r("panel"),a=r("text"),i=r("accent");if(n||a){let p=A(a??C.text,n??C.panel);p<Se&&(e.push(`text on panel is ${p.toFixed(1)}:1, under ${Se}:1: the platform's are used`),n=a=null)}let s=n??C.panel,c=a??C.text;if(i){let p=A(i,s);p<ke&&(e.push(`accent on panel is ${p.toFixed(1)}:1, under ${ke}:1: the platform's is used`),i=null)}if(!i&&n&&A(C.accent,n)<ke&&(i=c),!n&&!a&&!i)return{look:null,notes:e};let d=i?ao(i):null;return{look:{panel:n,text:a,muted:n||a?io(c,s):null,accent:i,accentHover:i?bt(i,d==="#ffffff"?"#000000":"#ffffff",.14):null,onAccent:d,ok:n?A(Q[0],n)>=A(Q[1],n)?Q[0]:Q[1]:null},notes:e}}function ft(t){let e=t.slice(1).toLowerCase();return`#${e.length===3?[...e].map(o=>o+o).join(""):e}`}function V(t){let e=ft(t);return[parseInt(e.slice(1,3),16),parseInt(e.slice(3,5),16),parseInt(e.slice(5,7),16)]}function mt(t){let[e,o,r]=V(t).map(n=>{let a=n/255;return a<=.04045?a/12.92:((a+.055)/1.055)**2.4});return .2126*e+.7152*o+.0722*r}function A(t,e){let[o,r]=[mt(t),mt(e)].sort((n,a)=>a-n);return(o+.05)/(r+.05)}function ao(t){return A(t,"#000000")>A(t,"#ffffff")?"#000000":"#ffffff"}function bt(t,e,o){let[r,n]=[V(t),V(e)];return`#${r.map((a,i)=>Math.round(a+(n[i]-a)*o).toString(16).padStart(2,"0")).join("")}`}function io(t,e){for(let o=.3;o>.001;o-=.05){let r=bt(t,e,o);if(A(r,e)>=Se)return r}return t}var ee=class{port=null;handlers;events;onConnect;solo;demo;onActivity;onPage;constructor(e,o,r,n,a={}){this.handlers=o,this.events=r,this.onConnect=n,this.solo=a.solo===!0,this.demo=a.demo===!0,this.onActivity=a.onActivity??null,this.onPage=a.onPage??null,window.addEventListener("message",i=>{if(!(i.source!==e.contentWindow||i.origin!=="null")&&(i.data?.type===at&&this.connect(i.source,st(i.data)),i.data?.type===ye)){let s=ht(i.data);s&&this.onPage?.(s)}})}activity(e,o){try{this.onActivity?.(e,o)}catch{}}emit(e,o){this.port?.postMessage({kind:"event",name:e,data:o})}connect(e,o){this.port?.close();let r=new MessageChannel,n=r.port1;this.port=n,n.onmessage=i=>this.receive(n,i.data);let a={type:it,...this.solo?{solo:!0}:{},...this.demo?{demo:!0}:{}};e.postMessage(a,"*",[r.port2]),this.onConnect(o)}async receive(e,o){if(!(e!==this.port||!o||typeof o!="object")){if(o.kind==="event"){Object.hasOwn(this.events,o.name)&&(this.events[o.name](o.data),this.activity(String(o.name),null));return}if(o.kind==="req")try{if(!Object.hasOwn(this.handlers,o.method))throw new Error(`Unknown method: ${String(o.method)}`);let r=this.handlers[o.method],n=await r(o.params);e.postMessage({kind:"res",id:o.id,ok:!0,result:n??null}),this.activity(String(o.method),null)}catch(r){let n=r instanceof Error?r.message:String(r);e.postMessage({kind:"res",id:o.id,ok:!1,error:n}),this.activity(String(o.method),n)}}}};var so="ow-game-storage",lo=256,wt="guest";function ze(t){let e=0,o=new Set,r=[t];for(;r.length;){let n=r.pop();if(typeof n=="string")e+=n.length*2;else if(typeof n!="object"||n===null)e+=8;else{if(o.has(n))continue;if(o.add(n),n instanceof ArrayBuffer)e+=n.byteLength;else if(ArrayBuffer.isView(n))e+=n.buffer.byteLength;else if(typeof Blob=="function"&&n instanceof Blob)e+=n.size;else if(n instanceof Map)for(let[a,i]of n)r.push(a,i);else if(n instanceof Set)for(let a of n)r.push(a);else if(Array.isArray(n))r.push(...n.slice(0,1e5),...n.length>1e5?[n.slice(1e5)]:[]);else for(let[a,i]of Object.entries(n))r.push(a,i)}}return e}function $(t){if(typeof t!="string"||t.length>lo)throw new Error("Bad name");return t}function vt(t){if(t===null)return null;if(typeof t=="string")return $(t);if(Array.isArray(t)&&t.length<=32)return t.map($);throw new Error("Bad key path")}function po(t){if(typeof t!="object"||t===null)throw new Error("Bad stores");let e=Object.keys(t);if(e.length>1e3)throw new Error("Too many stores");let o={};for(let r of e){let n=t[$(r)];if(typeof n!="object"||n===null||!Array.isArray(n.indexes)||n.indexes.length>1e3)throw new Error("Bad store");let a=Number(n.nextKey),i=n.indexes.map(s=>{let c=vt(s?.keyPath);if(c===null)throw new Error("Bad index");return{name:$(s.name),keyPath:c,unique:s.unique===!0,multiEntry:s.multiEntry===!0}});o[r]={keyPath:vt(n.keyPath),autoIncrement:n.autoIncrement===!0,nextKey:Number.isFinite(a)?a:1,indexes:i}}return o}function y(t){return new Promise((e,o)=>{t.onsuccess=()=>e(t.result),t.onerror=()=>o(t.error??new Error("Storage failed"))})}function Re(t){return new Promise((e,o)=>{t.oncomplete=()=>e(),t.onabort=t.onerror=()=>o(t.error??new Error("Storage failed"))})}var te=class{database=null;named=null;owner;factory;limit;constructor(e,o={}){this.owner=e,this.factory=o.factory??(()=>indexedDB),this.limit=o.limit??ct}open(){return this.database??=new Promise((e,o)=>{let r=this.factory().open(so,1);r.onupgradeneeded=()=>{r.result.createObjectStore("dbs",{keyPath:["owner","db"]}),r.result.createObjectStore("records")},r.onsuccess=()=>e(r.result),r.onerror=()=>o(r.error??new Error("No storage in this browser"))}),this.database}who(){return this.named??=this.owner().then(async({game:e,player:o})=>{let r=`${e}
|
|
2
|
-
${o??
|
|
3
|
-
${wt}`,r),r}),this.named}async adopt(e,o){let n=(await this.open()).transaction(["dbs","records"],"readwrite"),a=Re(n),i=n.objectStore("dbs"),s=n.objectStore("records"),c=await y(i.getAll(this.ownerRange(e)));for(let d of c){let p=this.dbRange(e,d.db);if(!await y(i.getKey([o,d.db]))){let m=await y(s.getAllKeys(p));for(let u of m){let R=await y(s.get(u));s.put(R,[o,...u.slice(1)])}i.put({...d,owner:o})}s.delete(p),i.delete([e,d.db])}await a}ownerRange(e){return IDBKeyRange.bound([e],[`${e}\0`],!1,!0)}dbRange(e,o){return IDBKeyRange.bound([e,o],[e,`${o}\0`],!1,!0)}storeRange(e,o,r){return IDBKeyRange.bound([e,o,r],[e,o,`${r}\0`],!1,!0)}async read({db:e}){$(e);let o=await this.who(),n=(await this.open()).transaction(["dbs","records"]),a=await y(n.objectStore("dbs").get([o,e]));if(!a)return null;let i=n.objectStore("records"),s=this.dbRange(o,e),[c,d]=await Promise.all([y(i.getAllKeys(s)),y(i.getAll(s))]);return{version:a.version,stores:a.stores,records:c.map((p,m)=>({store:p[2],key:p[3],value:d[m].value}))}}async commit(e){let o=$(e?.db),r=Number(e.version);if(!Number.isFinite(r)||r<0)throw new Error("Bad version");let n=e.ops;if(!Array.isArray(n))throw new Error("Bad changes");let a=e.stores===void 0?void 0:po(e.stores),i=await this.who(),c=(await this.open()).transaction(["dbs","records"],"readwrite"),d=Re(c),p=c.objectStore("dbs"),m=c.objectStore("records");try{let u=await y(p.getAll(this.ownerRange(i))),R=u.find(l=>l.db===o)??{owner:i,db:o,version:r,stores:{},bytes:0},q=u.reduce((l,x)=>l+(x===R?0:x.bytes),0),b=R.bytes;for(let l of n){let x=$(l?.store);if("clear"in l){b-=await this.sum(m,this.storeRange(i,o,x)),m.delete(this.storeRange(i,o,x));continue}let fe=[i,o,x,"put"in l?l.put:l.remove],Ge=await y(m.get(fe));if(Ge&&(b-=Ge.bytes),"put"in l){let Ue=ze(l.value)+ze(l.put)+64;b+=Ue,m.put({value:l.value,bytes:Ue},fe)}else m.delete(fe)}if(a)for(let l of Object.keys(R.stores))Object.hasOwn(a,l)||(b-=await this.sum(m,this.storeRange(i,o,l)),m.delete(this.storeRange(i,o,l)));if(q+=ze(a??R.stores),q+b>this.limit)throw new Error("QuotaExceededError");p.put({owner:i,db:o,version:r,stores:a??R.stores,bytes:Math.max(0,b)})}catch(u){try{c.abort()}catch{}throw d.catch(()=>{}),u}return await d,null}async sum(e,o){return(await y(e.getAll(o))).reduce((n,a)=>n+a.bytes,0)}async remove({db:e}){$(e);let o=await this.who(),n=(await this.open()).transaction(["dbs","records"],"readwrite"),a=Re(n);return n.objectStore("records").delete(this.dbRange(o,e)),n.objectStore("dbs").delete([o,e]),await a,null}async list(){let e=await this.who(),o=await this.open();return(await y(o.transaction("dbs").objectStore("dbs").getAll(this.ownerRange(e)))).map(n=>({name:n.db,version:n.version}))}};var oe=class{pressed=new Set;press(e){this.pressed.add(e)}take(e){let o=new Set(e),r=!1;for(let n of this.pressed)o.has(n)||(o.add(n),r=!0);return this.pressed.clear(),{buttons:[...o],owed:r}}};var yt=["--ow-panel","--ow-face-edge","--ow-hover","--ow-on-accent","--text","--muted","--line","--line-strong","--fill","--fill-strong","--ok","--accent-fill","--accent-fill-hover","--accent-hover"],kt=["--ow-ctl-edge","--ow-ctl-fill","--ow-ctl-stick","--ow-ctl-knob","--ow-ctl-label","--ow-ctl-shadow","--ow-ctl-held","--ow-ctl-main","--ow-ctl-main-edge","--ow-ctl-main-label","--ow-ctl-main-shadow","--ow-ctl-main-held"];function w(t,e){return`rgba(${V(t).join(", ")}, ${e})`}function St(t){let e={};if(!t)return e;if(t.panel&&(e["--ow-panel"]=t.panel,e["--ow-face-edge"]=t.panel),t.ok&&(e["--ok"]=t.ok),t.panel||t.text){let o=t.text??C.text;t.text&&(e["--text"]=t.text),t.muted&&(e["--muted"]=t.muted),e["--line"]=w(o,.09),e["--line-strong"]=w(o,.16),e["--fill"]=w(o,.06),e["--fill-strong"]=w(o,.1),e["--ow-hover"]=w(o,.16)}return t.accent&&t.accentHover&&t.onAccent&&(e["--accent-fill"]=t.accent,e["--accent-fill-hover"]=t.accentHover,e["--accent-hover"]=t.accent,e["--ow-on-accent"]=t.onAccent),e}function zt(t){let e={};return t&&(t.text&&(e["--ow-ctl-edge"]=w(t.text,.4),e["--ow-ctl-knob"]=w(t.text,.9),e["--ow-ctl-label"]=t.text,e["--ow-ctl-held"]=w(t.text,.35)),t.panel&&(e["--ow-ctl-fill"]=w(t.panel,.4),e["--ow-ctl-stick"]=w(t.panel,.3),e["--ow-ctl-shadow"]=w(t.panel,.5)),t.accent&&t.accentHover&&t.onAccent&&(e["--ow-ctl-main"]=w(t.accent,.85),e["--ow-ctl-main-edge"]=t.accent,e["--ow-ctl-main-label"]=t.onAccent,e["--ow-ctl-main-shadow"]="none",e["--ow-ctl-main-held"]=t.accentHover)),e}function re(t,e,o){for(let r of e)Object.hasOwn(o,r)?t.style.setProperty(r,o[r]):t.style.removeProperty(r);t.toggleAttribute("data-look",e.some(r=>Object.hasOwn(o,r)))}var L=52,Ee=.12,Pe=96,co=400,go=2e4,ne=class{parent;root;zone;base;knob;buttonBox;send;onLayout;layout=null;touch;blocked=!1;keyboard=!1;stickPointer=null;center={x:0,y:0};x=0;y=0;buttons=new Map;held=new Map;fingers=new Map;report=new oe;queued=0;sent="";placed={stick:null,buttons:null};constructor(e,o,r=()=>{}){this.send=o,this.onLayout=r,this.parent=e,this.touch=matchMedia("(pointer: coarse)").matches,this.root=T("div","ow-controls"),this.root.hidden=!0,this.zone=T("div","ow-stick-zone"),this.base=T("div","ow-stick"),this.knob=T("div","ow-stick-knob"),this.base.append(this.knob),this.zone.append(this.base),this.buttonBox=T("div","ow-control-buttons"),this.root.append(this.zone,this.buttonBox),e.append(this.root),this.zone.addEventListener("pointerdown",n=>this.stickDown(n)),this.zone.addEventListener("pointermove",n=>this.stickMove(n));for(let n of["pointerup","pointercancel","lostpointercapture"])this.zone.addEventListener(n,a=>this.stickUp(a));this.root.addEventListener("contextmenu",n=>n.preventDefault())}setLayout(e){this.layout=Ze(e);let o=this.buttons;this.buttons=new Map,(this.layout?.buttons??[]).forEach((r,n)=>{let a=o.get(r.id)??this.button(r.id);o.delete(r.id),a.className=`ow-control-btn ow-control-btn-${n}`,a.classList.toggle("ow-held",[...this.held.values()].includes(r.id)),a.textContent=r.label,a.isConnected||this.buttonBox.append(a),this.buttons.set(r.id,a)});for(let[r,n]of o){for(let[a,i]of this.held)i===r&&this.letGo(a);n.remove()}this.zone.hidden=!this.layout?.stick,this.zone.classList.toggle("ow-stick-corner",this.layout?.zone==="corner"),this.zone.hidden&&this.stickPointer!==null&&this.letGo(this.stickPointer),this.render(),this.onLayout()}setLook(e){re(this.root,kt,e)}reservedBoxes(){if(this.root.hidden)return this.blocked&&this.layout&&this.touch&&!this.keyboard?this.placed:{stick:null,buttons:null};let e=this.zone.hidden?null:Et(this.base),o=null;for(let r of this.buttons.values()){let n=Et(r);!n.width||!n.height||(o=o?uo(o,n):n)}return this.placed={stick:e,buttons:o},this.placed}setTouch(e){this.touch=e,this.render()}setKeyboard(e){this.keyboard=e,this.render()}setBlocked(e){this.blocked=e,this.render()}render(){let e=!!this.layout&&this.touch&&!this.blocked&&!this.keyboard;this.root.hidden!==!e&&(e||this.reset(),this.root.hidden=!e,this.onLayout())}reset(){for(let e of[...this.held.keys()])this.letGo(e);this.stickPointer!==null&&this.letGo(this.stickPointer),this.endStick()}letGo(e){e===this.stickPointer&&this.endStick();let o=this.held.get(e);this.held.delete(e),o!==void 0&&![...this.held.values()].includes(o)&&this.buttons.get(o)?.classList.remove("ow-held");let r=this.fingers.get(e);this.fingers.delete(e),r&&ho(this.parent,e,r),this.changed()}button(e){let o=T("button","ow-control-btn");o.type="button",o.tabIndex=-1,o.addEventListener("pointerdown",n=>{n.preventDefault(),Rt(o,n.pointerId),o.classList.add("ow-held"),this.held.set(n.pointerId,e),this.report.press(e),this.fingers.set(n.pointerId,{x:n.clientX,y:n.clientY}),this.changed()}),o.addEventListener("pointermove",n=>{this.held.get(n.pointerId)===e&&this.fingers.set(n.pointerId,{x:n.clientX,y:n.clientY})});let r=n=>{this.held.get(n.pointerId)===e&&(this.held.delete(n.pointerId),this.fingers.delete(n.pointerId),[...this.held.values()].includes(e)||o.classList.remove("ow-held"),this.changed())};for(let n of["pointerup","pointercancel","lostpointercapture"])o.addEventListener(n,a=>r(a));return o}stickDown(e){if(this.stickPointer!==null)return;e.preventDefault(),Rt(this.zone,e.pointerId),this.stickPointer=e.pointerId,this.fingers.set(e.pointerId,{x:e.clientX,y:e.clientY});let o=this.zone.getBoundingClientRect(),r=this.base.getBoundingClientRect(),n=L+8;this.center={x:Math.min(Math.max(e.clientX,o.left+n),o.right-n),y:Math.min(Math.max(e.clientY,o.top+n),o.bottom-n)},this.base.style.transform=`translate(${this.center.x-(r.left+r.width/2)}px, ${this.center.y-(r.top+r.height/2)}px)`,this.base.classList.add("ow-active"),this.stickMove(e)}stickMove(e){if(e.pointerId!==this.stickPointer)return;this.fingers.set(e.pointerId,{x:e.clientX,y:e.clientY});let o=e.clientX-this.center.x,r=e.clientY-this.center.y,n=Math.hypot(o,r);n>L&&(o=o/n*L,r=r/n*L),this.knob.style.transform=`translate(${o}px, ${r}px)`;let a=Math.min(n,L)/L,i=a<Ee?0:(a-Ee)/(1-Ee)/(a||1);this.x=Pt(o/L*i),this.y=Pt(r/L*i),this.changed()}stickUp(e){e.pointerId===this.stickPointer&&(this.fingers.delete(e.pointerId),this.endStick())}endStick(){this.stickPointer=null,this.x=0,this.y=0,this.base.classList.remove("ow-active"),this.base.style.transform="",this.knob.style.transform="",this.changed()}changed(){this.queued||(this.queued=requestAnimationFrame(()=>{this.queued=0;let{buttons:e,owed:o}=this.report.take(this.held.values()),r={x:this.x,y:this.y,buttons:e};o&&this.changed();let n=JSON.stringify(r);n!==this.sent&&(this.sent=n,this.send(r))}))}};function ho(t,e,o){let r=T("div","ow-tap-shield");r.style.left=`${o.x-Pe/2}px`,r.style.top=`${o.y-Pe/2}px`,r.style.width=r.style.height=`${Pe}px`,t.append(r);let n=setTimeout(()=>r.remove(),go),a=()=>{clearTimeout(n),n=setTimeout(()=>r.remove(),co)};for(let i of["pointerup","pointercancel","lostpointercapture"])r.addEventListener(i,s=>s.pointerId===e&&a());r.addEventListener("contextmenu",i=>i.preventDefault());try{r.setPointerCapture(e)}catch{a()}}function Rt(t,e){try{t.setPointerCapture(e)}catch{}}function Et(t){let e=t.getBoundingClientRect(),o=getComputedStyle(t).transform;if(!o||o==="none")return e;let r=new DOMMatrixReadOnly(o);if(r.b||r.c||!r.a||!r.d)return e;let n=e.width/Math.abs(r.a),a=e.height/Math.abs(r.d),i=e.left+e.width/2-r.e,s=e.top+e.height/2-r.f;return{left:i-n/2,top:s-a/2,width:n,height:a}}function uo(t,e){let o=Math.min(t.left,e.left),r=Math.min(t.top,e.top);return{left:o,top:r,width:Math.max(t.left+t.width,e.left+e.width)-o,height:Math.max(t.top+t.height,e.top+e.height)-r}}function Pt(t){return Math.round(t*1e3)/1e3}function T(t,e,o){let r=document.createElement(t);return r.className=e,o!==void 0&&(r.textContent=o),r}function mo(t,e){return t!=="lobby"?{surface:t,hidden:!1}:{surface:e?"none":"lobby",hidden:e}}var Me=t=>Math.max(0,Math.ceil(t/1e3)),Ae=t=>{let e=t.slice(0,2).map(o=>o.name);return t.length>2?`${e.join(", ")} +${t.length-2}`:e.join(", ")};function xo(t){let{you:e,host:o,kind:r,match:n,now:a}=t,i=[...t.players].sort((l,x)=>l.id===e?-1:x.id===e?1:l.id===o?-1:x.id===o?1:l.name.localeCompare(x.name)).map(l=>({id:l.id,name:l.name,ready:!!l.ready,host:l.id===o,you:l.id===e,away:l.connected===!1,idle:l.connected!==!1&&!!l.idle})),s=t.players.filter(l=>l.connected!==!1),c=t.players.find(l=>l.id===e),d=o===e&&n.phase==="lobby",p=t.schema.map(l=>({id:l.id,label:l.label,value:et(l,t.written),options:l.options,editable:d})),m={n:s.filter(l=>l.ready||r!=="public"&&l.id===o).length,of:s.length},u={surface:"none",rows:i,count:`${t.players.length} / ${t.max}`,ready:m,status:"",action:{kind:"none",label:"",disabled:!0},settings:p,seconds:null},R=n.participants?.includes(e)??!1,q=o===e&&r!=="public";if(n.phase==="starting"){if(!R)return{...u,surface:"watching",status:"Watching"};let l=q?{kind:"stop",label:"Stop",disabled:!1}:{kind:"unready",label:"Not ready",disabled:!1};return t.ownCountdown?{...u,surface:"countdown",action:l,seconds:null,status:"Get ready"}:{...u,surface:"countdown",action:l,seconds:Math.max(1,Me((n.startsAt??a)-a)),status:"Get ready"}}if(n.phase==="playing"){if(n.paused){let l=s.filter(x=>n.participants?.includes(x.id)).length;return n.paused.reason==="host"?{...u,surface:"paused",status:"Paused"}:{...u,surface:"paused",seconds:Me(n.paused.since+E.matchAbandonMs-a),status:`Waiting for players \xB7 ${l} / ${n.min}`}}return R?u:{...u,surface:"watching",status:"Watching"}}let b=s.filter(l=>!l.ready&&(r==="public"||l.id!==o));if(u.surface="lobby",q){let l=s.length<n.min;return u.action={kind:"start",label:"Start",disabled:l||b.length>0},u.status=l?`Need ${n.min} players`:b.length?`Waiting for ${Ae(b)}`:"",u}if(u.action={kind:c?.ready?"unready":"ready",label:c?.ready?"Not ready":"Ready",disabled:!1},r==="public")s.length<n.min?u.status=`Need ${n.min} players`:n.waitUntil!==void 0&&b.length?(u.seconds=Me(n.waitUntil-a),u.status=`${Ae(b)} \xB7 ${u.seconds}s`):u.status=`${s.length-b.length} / ${s.length} ready`;else{let l=b.filter(x=>x.id!==e);u.status=c?.ready?l.length?`Waiting for ${Ae(l)}`:`Waiting for ${t.players.find(x=>x.id===o)?.name??"the host"}`:""}return u}function h(t,e="",o){let r=document.createElement(t);return e&&(r.className=e),o!==void 0&&(r.textContent=o),r}var ae=class{mode=null;ownCountdown=!1;hiddenByGame=!1;state=null;schema=[];timer=0;opts;root;card;title;count;list;settingsBox;status;action;invite;bar;barFaces;barStatus;barAction;countdown;numeral;cancel;pause;pauseStatus;pauseTimer;chip;last=null;lastNumeral=-1;listSignature="";settingsSignature="";faceSignature="";constructor(e,o){this.opts=o,this.root=h("div","ow-lobby"),this.root.hidden=!0,this.card=h("section","ow-lobby-card"),this.card.setAttribute("aria-label","Lobby");let r=h("header","ow-lobby-head");this.title=h("h2","","Lobby"),this.count=h("span","ow-lobby-count"),r.append(this.title,this.count),this.list=h("ul","ow-lobby-players"),this.settingsBox=h("div","ow-lobby-settings"),this.status=h("p","ow-lobby-status"),this.status.setAttribute("role","status"),this.action=this.button("ow-btn ow-btn-primary ow-lobby-action",()=>this.press()),this.invite=this.button("ow-btn ow-lobby-invite",()=>this.opts.onInvite()),this.invite.textContent="Invite";let n=h("div","ow-lobby-actions");n.append(this.action,this.invite),this.card.append(r,this.list,this.settingsBox,this.status,n),this.bar=h("div","ow-lobby-bar"),this.barFaces=h("span","ow-lobby-faces"),this.barStatus=h("span","ow-lobby-bar-status"),this.barStatus.setAttribute("role","status"),this.barAction=this.button("ow-btn ow-btn-primary ow-lobby-action",()=>this.press()),this.bar.append(this.barFaces,this.barStatus,this.barAction),this.countdown=h("div","ow-lobby-countdown"),this.numeral=h("b"),this.numeral.setAttribute("aria-hidden","true");let a=h("span","","Get ready");a.setAttribute("aria-hidden","true"),this.cancel=this.button("ow-btn ow-lobby-cancel",()=>this.press()),this.countdown.append(this.numeral,a,this.cancel),this.pause=h("div","ow-lobby-pause");let i=h("div","ow-lobby-pause-box");this.pauseStatus=h("p","ow-lobby-pause-status"),this.pauseStatus.setAttribute("role","status"),this.pauseTimer=h("p","ow-lobby-pause-timer"),i.append(this.pauseStatus,this.pauseTimer),this.pause.append(i),this.chip=h("div","ow-lobby-chip"),this.chip.setAttribute("role","status"),this.root.append(this.card,this.bar,this.countdown,this.pause,this.chip),e.append(this.root)}setSchema(e){this.schema=e,this.render()}enable(e,o={}){this.mode=e,this.ownCountdown=o.ownCountdown===!0,this.root.dataset.mode=e??"",e||this.reset(),this.render()}setLook(e){re(this.root,yt,e)}reservedBox(){if(this.root.hidden)return null;let e=!this.countdown.hidden&&this.countdown.classList.contains("ow-lobby-countdown-bare"),o=this.bar.hidden?e&&!this.cancel.hidden?this.cancel:null:this.bar;return o?o.getBoundingClientRect():null}setHidden(e){this.hiddenByGame=e,this.render()}setRoom(e,o=0){if(!e)return this.reset();this.state={you:e.you,host:e.host,kind:e.room.startsWith("private:")?"private":e.room.startsWith("room:")?"named":"public",max:Math.max(o,e.players.length),players:e.players.map(r=>({...r})),match:e.match??{phase:"lobby",n:0,min:1},written:e.state?.[K]},this.render()}handle(e){let o=this.state;if(o){switch(e.t){case"join":o.players=[...o.players.filter(r=>r.id!==e.player.id),{...e.player}];break;case"leave":o.players=o.players.filter(r=>r.id!==e.id);break;case"away":o.players=o.players.map(r=>r.id===e.id?{...r,connected:!1}:r);break;case"back":o.players=o.players.map(r=>{if(r.id!==e.id)return r;let{connected:n,...a}=r;return a});break;case"ready":o.players=o.players.map(r=>{if(r.id!==e.id)return r;let{ready:n,...a}=r;return e.ready?{...a,ready:!0}:a});break;case"unready":o.players=o.players.map(({ready:r,...n})=>n);break;case"host":o.host=e.id;break;case"idle":o.players=o.players.map(r=>{if(r.id!==e.id)return r;let{idle:n,...a}=r;return e.idle?{...a,idle:!0}:a});break;case"name":o.players=o.players.map(r=>r.id===e.id?{...r,name:e.name}:r);break;case"match":o.match=e.match;break;case"state":if(e.k!==K)return;o.written=e.v;break;default:return}this.render()}}chooseSetting(e,o){let r=this.state,n=this.schema.find(i=>i.id===e);if(!r||!n||!n.options.some(i=>i.value===o))return null;let a={...r.written!==null&&typeof r.written=="object"?r.written:{},[e]:o};return r.written=a,this.render(),a}setReadyLocal(e){let o=this.state?.players.find(r=>r.id===this.state?.you);o&&(e?o.ready=!0:delete o.ready,this.render())}button(e,o){let r=h("button",e);return r.type="button",r.addEventListener("pointerdown",n=>n.preventDefault()),r.addEventListener("click",o),r}press(){let e=this.last?.action.kind;e==="start"?this.opts.onStart():e==="stop"?this.opts.onStop():e==="ready"?(this.setReadyLocal(!0),this.opts.onReady(!0)):e==="unready"&&(this.setReadyLocal(!1),this.opts.onReady(!1))}reset(){this.state=null,this.last=null,this.hiddenByGame=!1,window.clearInterval(this.timer),this.timer=0,this.root.hidden=!0,this.opts.onLayout?.()}render(){this.draw(),this.opts.onLayout?.()}draw(){if(!this.mode||!this.state){this.root.hidden=!0;return}let e=xo({...this.state,schema:this.schema,now:this.opts.now(),ownCountdown:this.ownCountdown});this.last=e;let o=mo(e.surface,this.hiddenByGame);this.hiddenByGame=o.hidden;let r=o.surface==="lobby";if(this.root.hidden=o.surface==="none",this.card.hidden=!(r&&this.mode==="card"),this.bar.hidden=!(r&&this.mode==="bar"),this.countdown.hidden=e.surface!=="countdown",this.countdown.classList.toggle("ow-lobby-countdown-bare",e.surface==="countdown"&&e.seconds===null),this.pause.hidden=e.surface!=="paused",this.chip.hidden=e.surface!=="watching",this.root.classList.toggle("ow-lobby-dim",r&&this.mode==="card"),r&&this.mode==="card"&&this.renderCard(e),r&&this.mode==="bar"&&this.renderBar(e),e.surface==="countdown"&&e.seconds!==null&&e.seconds!==this.lastNumeral&&(this.lastNumeral=e.seconds,this.numeral.textContent=String(e.seconds),this.numeral.style.animation="none",this.numeral.offsetWidth,this.numeral.style.animation=""),e.surface==="countdown"&&(this.cancel.textContent=e.action.label),e.surface!=="countdown"&&(this.lastNumeral=-1),e.surface==="paused"&&(this.pauseStatus.textContent=e.status,this.pauseTimer.textContent=e.seconds!==null?`Ends in ${fo(e.seconds)}`:""),e.surface==="watching"){let[a,...i]=e.status.split(" \xB7 "),s=h("span","ow-lobby-chip-more",i.length?` \xB7 ${i.join(" \xB7 ")}`:"");this.chip.replaceChildren(a,s)}let n=e.seconds!==null;n&&!this.timer?this.timer=window.setInterval(()=>this.render(),250):!n&&this.timer&&(window.clearInterval(this.timer),this.timer=0)}renderCard(e){this.count.textContent=e.count,this.settingsBox.hidden=e.settings.length===0,this.status.textContent=e.status,this.status.hidden=e.status==="",this.setAction(this.action,e);let o=JSON.stringify(e.settings);o!==this.settingsSignature&&(this.settingsSignature=o,this.settingsBox.replaceChildren(...e.settings.map(n=>this.settingRow(n))));let r=JSON.stringify(e.rows);r!==this.listSignature&&(this.listSignature=r,this.list.replaceChildren(...e.rows.map(n=>{let a=h("li",n.away||n.idle?"ow-lobby-away":n.ready?"ow-lobby-ready":""),i=h("img","ow-headshot");i.src=`/avatar/${encodeURIComponent(n.id)}/head.svg`,i.alt="";let s=h("span","ow-lobby-name",n.name),c=[n.away?"Reconnecting":n.idle?"Idle":"",n.you?"You":"",n.host?"Host":""].filter(Boolean).join(" \xB7 ");return a.append(i,s),c&&a.append(h("span","ow-player-notes",c)),a.append(h("span",`ow-lobby-check${n.ready?" ow-lobby-check-on":""}`,n.ready?"Ready":"")),a})))}settingRow(e){let o=h("div","ow-lobby-setting");if(o.append(h("span","ow-lobby-setting-label",e.label)),!e.editable)return o.append(h("span","ow-lobby-setting-value",e.options.find(n=>n.value===e.value)?.label??String(e.value))),o;let r=h("div","ow-segments");r.setAttribute("role","radiogroup"),r.setAttribute("aria-label",e.label);for(let n of e.options){let a=this.button(`ow-segment${n.value===e.value?" ow-segment-on":""}`,()=>this.opts.onSetting(e.id,n.value));a.textContent=n.label,a.setAttribute("role","radio"),a.setAttribute("aria-checked",String(n.value===e.value)),r.append(a)}return o.append(r),o}renderBar(e){this.barStatus.textContent=e.status||`${e.ready.n} / ${e.ready.of} ready`,this.setAction(this.barAction,e);let o=JSON.stringify(e.rows.slice(0,5).map(r=>[r.id,r.ready]));o!==this.faceSignature&&(this.faceSignature=o,this.barFaces.replaceChildren(...e.rows.slice(0,5).map(r=>{let n=h("img",`ow-headshot${r.ready?" ow-lobby-face-ready":""}`);return n.src=`/avatar/${encodeURIComponent(r.id)}/head.svg`,n.alt="",n})))}setAction(e,o){e.hidden=o.action.kind==="none",e.textContent=o.action.label,e.disabled=o.action.disabled,e.classList.toggle("ow-btn-primary",o.action.kind!=="unready")}};function fo(t){return`${Math.floor(t/60)}:${String(t%60).padStart(2,"0")}`}function Mt(t,e){let o=[];for(let{kind:r,box:n}of e){if(!n||!(n.width>0)||!(n.height>0))continue;let a=Math.max(0,n.left-t.left),i=Math.max(0,n.top-t.top),s=Math.min(t.width,n.left+n.width-t.left),c=Math.min(t.height,n.top+n.height-t.top);if(!(s-a>.01&&c-i>.01))continue;let d=Math.floor(a+.01),p=Math.floor(i+.01);o.push({kind:r,x:d,y:p,w:Math.ceil(s-.01)-d,h:Math.ceil(c-.01)-p})}return o}var ie=class{measure;send;nextFrame;queued=!1;sent=null;constructor(e,o,r=n=>requestAnimationFrame(n)){this.measure=e,this.send=o,this.nextFrame=r}changed(){this.queued||(this.queued=!0,this.nextFrame(()=>{this.queued=!1;let e=this.measure();if(!e)return;let o=JSON.stringify(e);o!==this.sent&&(this.sent=o,this.send(e))}))}resend(){this.sent=null,this.changed()}};var $e=t=>`ow:resume:${t}`;function _(t,e){try{e?sessionStorage.setItem($e(t),JSON.stringify({...e,at:Date.now()})):sessionStorage.removeItem($e(t))}catch{}}function At(t){try{let e=sessionStorage.getItem($e(t));if(!e)return null;let o=performance.getEntriesByType("navigation")[0];if(o&&o.type!=="reload"&&o.type!=="back_forward")return se(t);let r=JSON.parse(e);return typeof r.key!="string"||typeof r.rejoin!="string"||typeof r.at!="number"||Date.now()-r.at>18e4||Number(r.rejoin.split(".")[0])*1e3<Date.now()?se(t):{key:r.key,rejoin:r.rejoin}}catch{return null}}var bo=t=>`ow:own-server:${t}`;function $t(t,e){try{sessionStorage.setItem(bo(t),e)}catch{}}function se(t){return _(t,null),null}var le=class extends Error{constructor(o,r=0,n=0,a=""){super(o);this.status=r;this.retryAfterMs=n;this.code=a;this.name="RequestError"}status;retryAfterMs;code;get retryable(){return this.status===0||this.status===408||this.status===429||this.status>=500}};var pe=class{constructor(e=48*1024){this.max=e}max;used=0;async run(e,o){let r=new TextEncoder().encode(e).byteLength;if(this.used+r>this.max)throw new le("Progress is waiting to sync when you return to the game.");this.used+=r;try{return await o()}finally{this.used-=r}}};var Le=/^[2-9]$/.test(new URLSearchParams(location.search).get("player")??"")?new URLSearchParams(location.search).get("player"):null;var wo=null;function Lt(){return wo?.n??null}var yr=new pe;var Ct=[300,700,1500,3e3,5e3,8e3],vo=9e4,yo=1e4,Dt=()=>Array.from(crypto.getRandomValues(new Uint8Array(10)),t=>"abcdefghijklmnopqrstuvwxyz0123456789"[t%36]).join(""),Ot=Dt();function _t(){Ot=Dt()}var Tt=null;var It=!1;function jt(t){It=t}var ko=5e4,So=4e3,de=class{ws=null;key=null;rejoin=null;you="";closed=!1;attempt=0;droppedAt=0;sleeping=!1;lastHeard=0;heardCount=0;pingAt=0;hintedHidden=!1;pingTimer=0;watchTimer=0;retryTimer=0;page=Ot;slug;options;callbacks;onVisible=()=>{this.hint(),document.visibilityState==="visible"&&this.wake()};onOnline=()=>this.wake();onShow=e=>e.persisted&&this.wake();onHide=()=>this.hint();constructor(e,o,r){this.slug=e,this.options=o,this.callbacks=r,this.key=o.key??null,this.rejoin=o.rejoin??null,document.addEventListener("visibilitychange",this.onVisible),addEventListener("online",this.onOnline),addEventListener("pageshow",this.onShow),addEventListener("pagehide",this.onHide)}join(){return new Promise((e,o)=>this.open(e,o))}send(e){this.ws?.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify(e))}hint(){let e=document.visibilityState==="hidden";e===this.hintedHidden||this.ws?.readyState!==WebSocket.OPEN||(this.hintedHidden=e,this.send({t:"vis",hidden:e}))}ping(){let e=this.ws;e?.readyState===WebSocket.OPEN&&(this.pingAt&&Date.now()-this.pingAt<5e3||(this.pingAt=Date.now(),e.send(ve)))}close(){this.closed=!0,_(this.slug,null),this.dispose(),this.ws?.close(1e3)}reload(){return this.closed=!0,this.dispose(),this.ws?.close(nt,"Updating"),this.key?.startsWith("pub:")&&this.rejoin?{key:this.key,rejoin:this.rejoin}:null}open(e,o){this.retryTimer=0;let r=new URL(`/api/games/${this.slug}/rooms/connect`,location.href);r.protocol=location.protocol==="https:"?"wss:":"ws:",this.key?(r.searchParams.set("key",this.key),this.rejoin&&r.searchParams.set("rejoin",this.rejoin)):this.options.server?(r.searchParams.set("server",this.options.server),this.options.private&&r.searchParams.set("own","1")):this.options.name?r.searchParams.set("name",this.options.name):(this.options.mode&&r.searchParams.set("mode",this.options.mode),this.options.follow&&r.searchParams.set("follow",this.options.follow)),this.options.maxPlayers&&r.searchParams.set("max",String(this.options.maxPlayers)),this.options.minPlayers&&r.searchParams.set("min",String(this.options.minPlayers)),this.options.countdown!==void 0&&r.searchParams.set("countdown",String(this.options.countdown)),this.options.teams&&r.searchParams.set("teams",String(this.options.teams)),this.options.ranked&&r.searchParams.set("ranked","1"),Le&&r.searchParams.set("devplayer",Le);let n=Lt();n&&r.searchParams.set("tester",n),r.searchParams.set("page",this.page),this.options.build&&r.searchParams.set("build",this.options.build),Tt&&r.searchParams.set("pass",Tt),It&&r.searchParams.set("demo","1");let a=new WebSocket(r);this.ws=a,this.lastHeard=Date.now();let i=!1;a.onopen=()=>{this.lastHeard=Date.now(),window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer),this.pingTimer=window.setInterval(()=>a.readyState===WebSocket.OPEN&&this.ping(),yo),this.watchTimer=window.setInterval(()=>{a===this.ws&&a.readyState===WebSocket.OPEN&&Date.now()-this.lastHeard>ko&&this.lost(a)},5e3)},a.onmessage=d=>{this.lastHeard=Date.now(),this.heardCount++;let p;try{p=JSON.parse(d.data)}catch{return}if(p.t==="pong"){this.pingAt&&this.callbacks.onRtt?.(Date.now()-this.pingAt),this.pingAt=0;return}if(p.t==="welcome"&&(p.rejoin&&(this.rejoin=p.rejoin),delete p.rejoin,p.room.startsWith("pub:")&&this.rejoin&&_(this.slug,{key:p.room,rejoin:this.rejoin})),p.t==="leave"&&p.kicked&&p.id===this.you){this.close(),this.finish("kicked");return}if(p.t==="welcome"&&(this.hintedHidden=!1,this.hint()),p.t==="welcome"&&!i&&(i=!0,this.key=p.room,this.you=p.you,this.attempt=0,this.droppedAt&&(this.droppedAt=0,this.callbacks.onConnection?.(!0)),e)){let{t:m,...u}=p;e(u),e=void 0;return}this.callbacks.onMessage(p)};let s=!1,c=d=>{if(!s&&(s=!0,window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer),!(this.closed||a!==this.ws))){if(d.code===tt)return this.finish("replaced");if(d.code===rt&&i&&document.visibilityState==="hidden"){this.sleeping=!0,this.droppedAt||(this.droppedAt=Date.now(),this.callbacks.onConnection?.(!1));return}if(d.code===ot){if(i||!o)return this.finish("kicked");this.closed=!0,this.dispose(),_(this.slug,null),o(Object.assign(new Error("You were removed from this server."),{kicked:!0}));return}if(!i&&o){this.closed=!0,this.dispose(),o(new Error(this.options.name||this.options.server?"Could not join that server. It may be full.":"Could not join a server. Try again soon."));return}this.retry()}};a.onclose=c,a.onerror=()=>{window.setTimeout(()=>{a.readyState===WebSocket.CLOSED&&c({code:1006})},1e3)}}retry(){if(this.closed)return;let e=Date.now();if(this.droppedAt||(this.droppedAt=e,this.callbacks.onConnection?.(!1)),e-this.droppedAt>vo)return this.finish("disconnected");if(this.retryTimer)return;let o=Ct[Math.min(this.attempt++,Ct.length-1)]*(.5+Math.random());this.retryTimer=window.setTimeout(()=>{this.retryTimer=0,this.closed||this.open()},o)}lost(e){if(!(e!==this.ws||this.closed)){e.onopen=e.onmessage=e.onclose=e.onerror=null,window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer);try{e.close()}catch{}this.retry()}}wake(){if(this.closed)return;if(this.sleeping){this.sleeping=!1,this.droppedAt=Date.now(),this.attempt=0,this.open();return}let e=this.ws;if(!e||e.readyState===WebSocket.CLOSING||e.readyState===WebSocket.CLOSED){this.retryTimer&&(window.clearTimeout(this.retryTimer),this.retryTimer=0,this.open());return}if(e.readyState!==WebSocket.OPEN)return;let o=this.heardCount;try{e.send(ve)}catch{return this.lost(e)}window.setTimeout(()=>e===this.ws&&!this.closed&&this.heardCount===o&&this.lost(e),So)}dispose(){window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer),window.clearTimeout(this.retryTimer),this.retryTimer=0,document.removeEventListener("visibilitychange",this.onVisible),removeEventListener("online",this.onOnline),removeEventListener("pageshow",this.onShow),removeEventListener("pagehide",this.onHide)}finish(e){this.closed=!0,this.dispose(),_(this.slug,null),this.callbacks.onClose(e)}};var Bt=`:root {
|
|
1
|
+
"use strict";(()=>{var He=["#f6dcc5","#ebc29f","#d4a07a","#b07a55","#875839","#5e3d29","#93c9bb","#a8c595","#94bcd3","#ab9bd9","#dca3ad","#b3bccb"],ye=["#c95f56","#dc8a4f","#e2bd52","#9cc27a","#5a8a5e","#4f9a8e","#6fb7c8","#5b87c5","#465089","#8b68a8","#dc8fae","#f2eee6","#a9a8ad","#5d5c63","#2b2a30","#80604d"],Fe=["Happy","Grin","Shades","Wink","Surprised","Determined","Joyful","Shy"],qe=["None","Sprout","Cap","Beanie","Crown","Headphones","Horns","Antenna","Bow","Halo","Party hat","Cat ears","Short hair","Tuft","Bob","Spikes","Bun","Curls","Long","Mop"];var Ke=["Plain","Band","Spots","Stripes","Star"];var Ho={skin:He.length,shirt:ye.length,pants:ye.length,face:Fe.length,hat:qe.length,top:Ke.length},ro=[[5,6],[3,4],[6,7],[9,8],[10,0],[12,13]];function Ve(t){let e=2166136261;for(let d of t)e=Math.imul(e^d.charCodeAt(0),16777619)>>>0;let o=d=>(e=Math.imul(e^e>>>13,2654435761)>>>0,e%d),r=o(He.length),a=r>=6?ro[r-6][o(2)]:o(ye.length),n=o(2)===0?a:[8,13,14,15][o(4)],i=o(5)===0?1:12+o(qe.length-12),s=o(2)===0?0:o(Ke.length);return{skin:r,shirt:a,pants:n,face:o(Fe.length),hat:i,top:s}}var P={roomMaxPlayersDefault:16,roomMaxPlayersCap:30,teamsMax:8,messageBytes:16*1024,presenceBytes:1024,stateKeyLength:64,stateValueBytes:16*1024,stateKeys:256,privateKeys:16,privateValueBytes:4*1024,privateBytesPerPlayer:8*1024,messagesPerSecond:60,messagesPerSecondMin:10,roomBytesPerSecond:128*1024,roomBytesPerSecondMin:16*1024,presenceHz:20,presenceHzMin:5,roomMessagesPerSecond:900,roomBytesPerSecondTotal:2*1024*1024,matchCountdownMs:3e3,matchCountdownMaxMs:1e4,matchIdleMs:45e3,matchAbandonMs:12e4,idleAfterMs:3e4,idleAbandonMs:5*6e4,rankedPairMatchesPerDay:5,chatLength:200,chatIntervalMs:750,chatHistory:50,chatChannelsPerPlayer:10,saveValueBytes:64*1024,saveKeysPerGame:100,saveBytesPerGame:1024*1024,guestSaveBytesPerGame:128*1024,serverDataKeys:128,serverDataBytes:512*1024,serverDataServersPerGame:5e3,serverDataBytesPerGame:64*1024*1024,serverDataIdleDays:120,gameDataKeys:32,gameDataListMax:100,gameDataItemBytes:1024,gameDataValueBytes:8*1024,gameDataMapFields:1e3,gameDataMapPerPlayer:100,gameDataNumberMax:1e15,gameDataWritesPerMinute:30,deployFiles:2e3,deployFileBytes:25*1024*1024,deployHtmlBytes:10*1024*1024,deployPathLength:200,deployTotalBytes:100*1024*1024,envVars:50,envValueBytes:4*1024,envTotalBytes:16*1024,proxyRequestBytes:1024*1024,proxyTextRequestBytes:256*1024,proxySpeechRequestBytes:16*1024,proxyResponseBytes:10*1024*1024,proxyMaxOutputTokens:4096,proxyCallsPerDay:2e3,proxyCallsPerDayMax:1e5,proxyCallsPerPlayerPerDay:100,proxyCallsPerNetworkPerDay:1e3,proxyMediaCallsPerDay:100,proxyMediaCallsPerDayMax:1e4,proxyMediaCallsPerPlayerPerDay:20,proxyMediaCallsPerNetworkPerDay:25,proxyUnitsPerDay:2e6,proxyUnitsPerDayMax:1e8,proxyUnitsPerPlayerPerDay:25e4,proxyUnitsPerGuestPerDay:1e5,proxyUnitsPerNetworkPerDay:5e5,errorReportsPerPage:10,consoleLineLength:2e3,consoleLinesPerSecond:50,gameNameLength:60,gameDescriptionLength:1e3,galleryItems:5,mediaImageBytes:5*1024*1024,mediaVideoBytes:30*1024*1024,mediaGifBytes:1024*1024,mediaGifSide:512,mediaUploadsPerDay:200,mediaBytesPerDay:500*1024*1024,badgesPerGame:50,controlHints:12,controlHintKeys:4,controlKeyLength:12,controlActionLength:40,helpLength:400,badgeNameLength:50,badgeDescriptionLength:200,leaderboardsPerGame:25,leaderboardTop:100,gamesPerOwner:50,gamesCreatedPerCreatorPerDay:3,uploadAccountAgeMs:10080*6e4,deploysPerOwnerPerDay:100,draftsPerOwnerPerDay:1e3,draftsKeptPerGame:3,cliTokensPerAccount:10,cliDeviceCodeSeconds:600,deploymentsKeptPerGame:10,deployBytesPerOwnerPerDay:2*1024*1024*1024,deployEntriesPerOwnerPerDay:1e5,bioLength:500,exportRows:2e3,exportSaveChars:4*1024*1024,exportEveryMs:60*6e4,friendsMax:200,friendRequestsMax:100,friendRequestsIncomingMax:50,friendRequestsPerDay:20,friendRequestsPerNetworkPerDay:120,friendRequestPushesPerDay:5,passwordMinLength:8,passwordMaxLength:72,signupsPerNetworkPerDay:100,signupsPerWidePerDay:300,guestsPerNetworkPerDay:300,guestsPerWidePerDay:1500,visitsPerNetworkPerDay:10,visitSeconds:10,errorsPerDeployment:100,controlButtons:4,controlLabelLength:12,partySize:6,partyChatHistory:50,messageLength:500,messagesPerPage:50,groupChatMembers:20,groupChatNameLength:40,conversationsListed:50,notificationsListed:50,invitesPerRequest:10,inviteLiveMs:30*6e4,partyInviteMs:60*6e4};var Ye=/^[a-z0-9]{12}$/,ee=2;function ke(t){return`${t.mode}.${t.max}.${t.teams}.${t.ranked?1:0}${t.min!==ee?`.${t.min}`:""}`}var ao=/^pub:([a-z0-9-]+)\.(\d+)\.(\d)\.([01])(?:\.(\d+))?:(\d+)$/;function Je(t){let e=ao.exec(t);if(!e)return null;let o={mode:e[1],max:Number(e[2]),teams:Number(e[3]),ranked:e[4]==="1",min:e[5]===void 0?ee:Number(e[5])};return{...o,name:ke(o),n:Number(e[6])}}function Xe(t,e,o){let r=typeof t=="string"?Number(t):t;return typeof r!="number"||!Number.isInteger(r)?Math.min(o,e):Math.min(e,Math.max(1,r))}var We=t=>t.replace(/[\u0000-\u001f\u007f]/g," ").replace(/\s+/g," ").trim();var no=/^[a-z0-9][a-z0-9-]{0,19}$/;function Ze(t){if(!t||typeof t!="object")return null;let e=t,o=[];for(let a of Array.isArray(e.buttons)?e.buttons:[]){if(o.length>=P.controlButtons)break;let{id:n,label:i}=a??{};if(typeof n!="string"||!no.test(n)||o.some(d=>d.id===n))continue;let s=typeof i=="string"?i.replace(/[\u0000-\u001f\u007f]/g,"").replace(/\s+/g," ").trim().slice(0,P.controlLabelLength).trim():"";o.push({id:n,label:s||n})}let r=e.stick===!0;return r||o.length>0?{stick:r,zone:e.zone==="corner"?"corner":"wide",buttons:o}:null}var V="host:ow.settings",io=/^[a-z][a-zA-Z0-9]{0,15}$/;function Qe(t){if(!Array.isArray(t))return[];let e=[];for(let o of t){if(e.length>=6)break;let{id:r,label:a,options:n,default:i}=o??{};if(typeof r!="string"||!io.test(r)||e.some(c=>c.id===r)||!Array.isArray(n))continue;let s=[];for(let c of n){let p=typeof c=="object"&&c!==null?c.value:c;if(typeof p!="string"&&typeof p!="number"||typeof p=="number"&&!Number.isFinite(p)||s.length>=8||s.some(m=>m.value===p))continue;let x=typeof c=="object"&&c!==null&&typeof c.label=="string"?c.label:String(p);s.push({value:p,label:We(x).slice(0,20)||String(p)})}if(s.length<2)continue;let d=typeof a=="string"?We(a).slice(0,24):"";e.push({id:r,label:d||r,options:s,default:s.some(c=>c.value===i)?i:s[0].value})}return e}function et(t,e){let o=e!==null&&typeof e=="object"?e[t.id]:void 0;return t.options.some(r=>r.value===o)?o:t.default}var Se='{"t":"ping"}';var tt=4001,ot=4003,rt=4008,at=4006;var nt="onceworlds:hello",it="onceworlds:connect",so=/^[a-z0-9]{1,32}~(?:(?:0|[1-9]\d{0,3})\.(?:0|[1-9]\d{0,4})\.(?:0|[1-9]\d{0,5}))?~[0-9a-z]{1,11}~[lp]~[A-Za-z0-9_-]{43}$/;function st(t){let e=t!==null&&typeof t=="object"?t.build:void 0;return typeof e=="string"&&so.test(e)?e:null}var lt="onceworlds-console";var pt="allow-scripts allow-pointer-lock allow-forms allow-orientation-lock",dt=["autoplay","gamepad","screen-wake-lock","accelerometer","gyroscope"].map(t=>`${t} *`).join("; "),ct=100*1024*1024;var gt=new Set(["server","join","deploy","watch","player","embed","k","console","tester","live","demo",lt]);var ze="onceworlds:page",lo=["ran","blocked","failed","threw","loaded"];function ht(t){if(t===null||typeof t!="object")return null;let{what:e,detail:o}=t;return typeof e!="string"||!lo.includes(e)?null:{what:e,detail:typeof o=="string"?o.slice(0,200):""}}var po=`(function(){var n=0,s=function(w,d){if(n++<12)try{parent.postMessage({type:${JSON.stringify(ze)},what:w,detail:String(d).slice(0,200)},"*")}catch(e){}};s("ran",document.readyState);addEventListener("securitypolicyviolation",function(e){s("blocked",e.effectiveDirective+" "+e.blockedURI)});addEventListener("error",function(e){var t=e.target;t&&t.tagName?s("failed",t.tagName+" "+(t.src||t.href)):s("threw",e.message+" "+e.filename+":"+e.lineno)},true);addEventListener("load",function(){s("loaded",typeof onceworlds)})})();`,Yo=`<script>${po}<\/script>`;function mt(t){return t?.ownCountdown!==!0}function ut(t){let e=t?.lobby;return e==="card"||e==="bar"?e:e==="game"?null:typeof t?.minPlayers=="number"||typeof t?.minPlayersPrivate=="number"||typeof t?.countdown=="number"||Array.isArray(t?.settings)&&t.settings.length>0?"bar":null}function xt(t){return t.key==="Enter"&&!t.isComposing&&!t.ctrlKey&&!t.metaKey&&!t.altKey&&!t.shiftKey}var ft=400;var co=/^#(?:[0-9a-f]{3}){1,2}$/i,T={panel:"#111216",text:"#f7f7f8",accent:"#d33e00"},Ee=4.5,Re=3,te=["#4ade80","#15803d"];function wt(t){let e=[];if(t==null)return{look:null,notes:e};if(typeof t!="object")return{look:null,notes:["a look is { accent, panel, text } or null"]};let o=t,r=p=>{let x=o[p];return x==null?null:typeof x=="string"&&co.test(x)?vt(x):(e.push(`${p} is not #rgb or #rrggbb`),null)},a=r("panel"),n=r("text"),i=r("accent");if(a||n){let p=A(n??T.text,a??T.panel);p<Ee&&(e.push(`text on panel is ${p.toFixed(1)}:1, under ${Ee}:1: the platform's are used`),a=n=null)}let s=a??T.panel,d=n??T.text;if(i){let p=A(i,s);p<Re&&(e.push(`accent on panel is ${p.toFixed(1)}:1, under ${Re}:1: the platform's is used`),i=null)}if(!i&&a&&A(T.accent,a)<Re&&(i=d),!a&&!n&&!i)return{look:null,notes:e};let c=i?go(i):null;return{look:{panel:a,text:n,muted:a||n?ho(d,s):null,accent:i,accentHover:i?yt(i,c==="#ffffff"?"#000000":"#ffffff",.14):null,onAccent:c,ok:a?A(te[0],a)>=A(te[1],a)?te[0]:te[1]:null},notes:e}}function vt(t){let e=t.slice(1).toLowerCase();return`#${e.length===3?[...e].map(o=>o+o).join(""):e}`}function W(t){let e=vt(t);return[parseInt(e.slice(1,3),16),parseInt(e.slice(3,5),16),parseInt(e.slice(5,7),16)]}function bt(t){let[e,o,r]=W(t).map(a=>{let n=a/255;return n<=.04045?n/12.92:((n+.055)/1.055)**2.4});return .2126*e+.7152*o+.0722*r}function A(t,e){let[o,r]=[bt(t),bt(e)].sort((a,n)=>n-a);return(o+.05)/(r+.05)}function go(t){return A(t,"#000000")>A(t,"#ffffff")?"#000000":"#ffffff"}function yt(t,e,o){let[r,a]=[W(t),W(e)];return`#${r.map((n,i)=>Math.round(n+(a[i]-n)*o).toString(16).padStart(2,"0")).join("")}`}function ho(t,e){for(let o=.3;o>.001;o-=.05){let r=yt(t,e,o);if(A(r,e)>=Ee)return r}return t}var oe=class{port=null;handlers;events;onConnect;solo;demo;onActivity;onPage;constructor(e,o,r,a,n={}){this.handlers=o,this.events=r,this.onConnect=a,this.solo=n.solo===!0,this.demo=n.demo===!0,this.onActivity=n.onActivity??null,this.onPage=n.onPage??null,window.addEventListener("message",i=>{if(!(i.source!==e.contentWindow||i.origin!=="null")&&(i.data?.type===nt&&this.connect(i.source,st(i.data)),i.data?.type===ze)){let s=ht(i.data);s&&this.onPage?.(s)}})}activity(e,o){try{this.onActivity?.(e,o)}catch{}}emit(e,o){this.port?.postMessage({kind:"event",name:e,data:o})}connect(e,o){this.port?.close();let r=new MessageChannel,a=r.port1;this.port=a,a.onmessage=i=>this.receive(a,i.data);let n={type:it,...this.solo?{solo:!0}:{},...this.demo?{demo:!0}:{}};e.postMessage(n,"*",[r.port2]),this.onConnect(o)}async receive(e,o){if(!(e!==this.port||!o||typeof o!="object")){if(o.kind==="event"){Object.hasOwn(this.events,o.name)&&(this.events[o.name](o.data),this.activity(String(o.name),null));return}if(o.kind==="req")try{if(!Object.hasOwn(this.handlers,o.method))throw new Error(`Unknown method: ${String(o.method)}`);let r=this.handlers[o.method],a=await r(o.params);e.postMessage({kind:"res",id:o.id,ok:!0,result:a??null}),this.activity(String(o.method),null)}catch(r){let a=r instanceof Error?r.message:String(r);e.postMessage({kind:"res",id:o.id,ok:!1,error:a}),this.activity(String(o.method),a)}}}};var mo="ow-game-storage",uo=256,kt="guest";function Pe(t){let e=0,o=new Set,r=[t];for(;r.length;){let a=r.pop();if(typeof a=="string")e+=a.length*2;else if(typeof a!="object"||a===null)e+=8;else{if(o.has(a))continue;if(o.add(a),a instanceof ArrayBuffer)e+=a.byteLength;else if(ArrayBuffer.isView(a))e+=a.buffer.byteLength;else if(typeof Blob=="function"&&a instanceof Blob)e+=a.size;else if(a instanceof Map)for(let[n,i]of a)r.push(n,i);else if(a instanceof Set)for(let n of a)r.push(n);else if(Array.isArray(a))r.push(...a.slice(0,1e5),...a.length>1e5?[a.slice(1e5)]:[]);else for(let[n,i]of Object.entries(a))r.push(n,i)}}return e}function L(t){if(typeof t!="string"||t.length>uo)throw new Error("Bad name");return t}function St(t){if(t===null)return null;if(typeof t=="string")return L(t);if(Array.isArray(t)&&t.length<=32)return t.map(L);throw new Error("Bad key path")}function xo(t){if(typeof t!="object"||t===null)throw new Error("Bad stores");let e=Object.keys(t);if(e.length>1e3)throw new Error("Too many stores");let o={};for(let r of e){let a=t[L(r)];if(typeof a!="object"||a===null||!Array.isArray(a.indexes)||a.indexes.length>1e3)throw new Error("Bad store");let n=Number(a.nextKey),i=a.indexes.map(s=>{let d=St(s?.keyPath);if(d===null)throw new Error("Bad index");return{name:L(s.name),keyPath:d,unique:s.unique===!0,multiEntry:s.multiEntry===!0}});o[r]={keyPath:St(a.keyPath),autoIncrement:a.autoIncrement===!0,nextKey:Number.isFinite(n)?n:1,indexes:i}}return o}function k(t){return new Promise((e,o)=>{t.onsuccess=()=>e(t.result),t.onerror=()=>o(t.error??new Error("Storage failed"))})}function Me(t){return new Promise((e,o)=>{t.oncomplete=()=>e(),t.onabort=t.onerror=()=>o(t.error??new Error("Storage failed"))})}var re=class{database=null;named=null;owner;factory;limit;constructor(e,o={}){this.owner=e,this.factory=o.factory??(()=>indexedDB),this.limit=o.limit??ct}open(){return this.database??=new Promise((e,o)=>{let r=this.factory().open(mo,1);r.onupgradeneeded=()=>{r.result.createObjectStore("dbs",{keyPath:["owner","db"]}),r.result.createObjectStore("records")},r.onsuccess=()=>e(r.result),r.onerror=()=>o(r.error??new Error("No storage in this browser"))}),this.database}who(){return this.named??=this.owner().then(async({game:e,player:o})=>{let r=`${e}
|
|
2
|
+
${o??kt}`;return o!==null&&await this.adopt(`${e}
|
|
3
|
+
${kt}`,r),r}),this.named}async adopt(e,o){let a=(await this.open()).transaction(["dbs","records"],"readwrite"),n=Me(a),i=a.objectStore("dbs"),s=a.objectStore("records"),d=await k(i.getAll(this.ownerRange(e)));for(let c of d){let p=this.dbRange(e,c.db);if(!await k(i.getKey([o,c.db]))){let x=await k(s.getAllKeys(p));for(let m of x){let E=await k(s.get(m));s.put(E,[o,...m.slice(1)])}i.put({...c,owner:o})}s.delete(p),i.delete([e,c.db])}await n}ownerRange(e){return IDBKeyRange.bound([e],[`${e}\0`],!1,!0)}dbRange(e,o){return IDBKeyRange.bound([e,o],[e,`${o}\0`],!1,!0)}storeRange(e,o,r){return IDBKeyRange.bound([e,o,r],[e,o,`${r}\0`],!1,!0)}async read({db:e}){L(e);let o=await this.who(),a=(await this.open()).transaction(["dbs","records"]),n=await k(a.objectStore("dbs").get([o,e]));if(!n)return null;let i=a.objectStore("records"),s=this.dbRange(o,e),[d,c]=await Promise.all([k(i.getAllKeys(s)),k(i.getAll(s))]);return{version:n.version,stores:n.stores,records:d.map((p,x)=>({store:p[2],key:p[3],value:c[x].value}))}}async commit(e){let o=L(e?.db),r=Number(e.version);if(!Number.isFinite(r)||r<0)throw new Error("Bad version");let a=e.ops;if(!Array.isArray(a))throw new Error("Bad changes");let n=e.stores===void 0?void 0:xo(e.stores),i=await this.who(),d=(await this.open()).transaction(["dbs","records"],"readwrite"),c=Me(d),p=d.objectStore("dbs"),x=d.objectStore("records");try{let m=await k(p.getAll(this.ownerRange(i))),E=m.find(l=>l.db===o)??{owner:i,db:o,version:r,stores:{},bytes:0},K=m.reduce((l,f)=>l+(f===E?0:f.bytes),0),b=E.bytes;for(let l of a){let f=L(l?.store);if("clear"in l){b-=await this.sum(x,this.storeRange(i,o,f)),x.delete(this.storeRange(i,o,f));continue}let ve=[i,o,f,"put"in l?l.put:l.remove],Ge=await k(x.get(ve));if(Ge&&(b-=Ge.bytes),"put"in l){let Ue=Pe(l.value)+Pe(l.put)+64;b+=Ue,x.put({value:l.value,bytes:Ue},ve)}else x.delete(ve)}if(n)for(let l of Object.keys(E.stores))Object.hasOwn(n,l)||(b-=await this.sum(x,this.storeRange(i,o,l)),x.delete(this.storeRange(i,o,l)));if(K+=Pe(n??E.stores),K+b>this.limit)throw new Error("QuotaExceededError");p.put({owner:i,db:o,version:r,stores:n??E.stores,bytes:Math.max(0,b)})}catch(m){try{d.abort()}catch{}throw c.catch(()=>{}),m}return await c,null}async sum(e,o){return(await k(e.getAll(o))).reduce((a,n)=>a+n.bytes,0)}async remove({db:e}){L(e);let o=await this.who(),a=(await this.open()).transaction(["dbs","records"],"readwrite"),n=Me(a);return a.objectStore("records").delete(this.dbRange(o,e)),a.objectStore("dbs").delete([o,e]),await n,null}async list(){let e=await this.who(),o=await this.open();return(await k(o.transaction("dbs").objectStore("dbs").getAll(this.ownerRange(e)))).map(a=>({name:a.db,version:a.version}))}};var ae=class{pressed=new Set;press(e){this.pressed.add(e)}take(e){let o=new Set(e),r=!1;for(let a of this.pressed)o.has(a)||(o.add(a),r=!0);return this.pressed.clear(),{buttons:[...o],owed:r}}};var zt=["--ow-panel","--ow-face-edge","--ow-hover","--ow-on-accent","--text","--muted","--line","--line-strong","--fill","--fill-strong","--ok","--accent-fill","--accent-fill-hover","--accent-hover"],Rt=["--ow-ctl-edge","--ow-ctl-fill","--ow-ctl-stick","--ow-ctl-knob","--ow-ctl-label","--ow-ctl-shadow","--ow-ctl-held","--ow-ctl-main","--ow-ctl-main-edge","--ow-ctl-main-label","--ow-ctl-main-shadow","--ow-ctl-main-held"];function v(t,e){return`rgba(${W(t).join(", ")}, ${e})`}function Et(t){let e={};if(!t)return e;if(t.panel&&(e["--ow-panel"]=t.panel,e["--ow-face-edge"]=t.panel),t.ok&&(e["--ok"]=t.ok),t.panel||t.text){let o=t.text??T.text;t.text&&(e["--text"]=t.text),t.muted&&(e["--muted"]=t.muted),e["--line"]=v(o,.09),e["--line-strong"]=v(o,.16),e["--fill"]=v(o,.06),e["--fill-strong"]=v(o,.1),e["--ow-hover"]=v(o,.16)}return t.accent&&t.accentHover&&t.onAccent&&(e["--accent-fill"]=t.accent,e["--accent-fill-hover"]=t.accentHover,e["--accent-hover"]=t.accent,e["--ow-on-accent"]=t.onAccent),e}function Pt(t){let e={};return t&&(t.text&&(e["--ow-ctl-edge"]=v(t.text,.4),e["--ow-ctl-knob"]=v(t.text,.9),e["--ow-ctl-label"]=t.text,e["--ow-ctl-held"]=v(t.text,.35)),t.panel&&(e["--ow-ctl-fill"]=v(t.panel,.4),e["--ow-ctl-stick"]=v(t.panel,.3),e["--ow-ctl-shadow"]=v(t.panel,.5)),t.accent&&t.accentHover&&t.onAccent&&(e["--ow-ctl-main"]=v(t.accent,.85),e["--ow-ctl-main-edge"]=t.accent,e["--ow-ctl-main-label"]=t.onAccent,e["--ow-ctl-main-shadow"]="none",e["--ow-ctl-main-held"]=t.accentHover)),e}function ne(t,e,o){for(let r of e)Object.hasOwn(o,r)?t.style.setProperty(r,o[r]):t.style.removeProperty(r);t.toggleAttribute("data-look",e.some(r=>Object.hasOwn(o,r)))}var $=52,Ae=.12,Le=96,fo=400,bo=2e4,ie=class{parent;root;zone;base;knob;buttonBox;send;onLayout;layout=null;touch;blocked=!1;keyboard=!1;stickPointer=null;center={x:0,y:0};x=0;y=0;buttons=new Map;held=new Map;fingers=new Map;report=new ae;queued=0;sent="";placed={stick:null,buttons:null};constructor(e,o,r=()=>{}){this.send=o,this.onLayout=r,this.parent=e,this.touch=matchMedia("(pointer: coarse)").matches,this.root=D("div","ow-controls"),this.root.hidden=!0,this.zone=D("div","ow-stick-zone"),this.base=D("div","ow-stick"),this.knob=D("div","ow-stick-knob"),this.base.append(this.knob),this.zone.append(this.base),this.buttonBox=D("div","ow-control-buttons"),this.root.append(this.zone,this.buttonBox),e.append(this.root),this.zone.addEventListener("pointerdown",a=>this.stickDown(a)),this.zone.addEventListener("pointermove",a=>this.stickMove(a));for(let a of["pointerup","pointercancel","lostpointercapture"])this.zone.addEventListener(a,n=>this.stickUp(n));this.root.addEventListener("contextmenu",a=>a.preventDefault())}setLayout(e){this.layout=Ze(e);let o=this.buttons;this.buttons=new Map,(this.layout?.buttons??[]).forEach((r,a)=>{let n=o.get(r.id)??this.button(r.id);o.delete(r.id),n.className=`ow-control-btn ow-control-btn-${a}`,n.classList.toggle("ow-held",[...this.held.values()].includes(r.id)),n.textContent=r.label,n.isConnected||this.buttonBox.append(n),this.buttons.set(r.id,n)});for(let[r,a]of o){for(let[n,i]of this.held)i===r&&this.letGo(n);a.remove()}this.zone.hidden=!this.layout?.stick,this.zone.classList.toggle("ow-stick-corner",this.layout?.zone==="corner"),this.zone.hidden&&this.stickPointer!==null&&this.letGo(this.stickPointer),this.render(),this.onLayout()}setLook(e){ne(this.root,Rt,e)}reservedBoxes(){if(this.root.hidden)return this.blocked&&this.layout&&this.touch&&!this.keyboard?this.placed:{stick:null,buttons:null};let e=this.zone.hidden?null:At(this.base),o=null;for(let r of this.buttons.values()){let a=At(r);!a.width||!a.height||(o=o?vo(o,a):a)}return this.placed={stick:e,buttons:o},this.placed}setTouch(e){this.touch=e,this.render()}setKeyboard(e){this.keyboard=e,this.render()}setBlocked(e){this.blocked=e,this.render()}render(){let e=!!this.layout&&this.touch&&!this.blocked&&!this.keyboard;this.root.hidden!==!e&&(e||this.reset(),this.root.hidden=!e,this.onLayout())}reset(){for(let e of[...this.held.keys()])this.letGo(e);this.stickPointer!==null&&this.letGo(this.stickPointer),this.endStick()}letGo(e){e===this.stickPointer&&this.endStick();let o=this.held.get(e);this.held.delete(e),o!==void 0&&![...this.held.values()].includes(o)&&this.buttons.get(o)?.classList.remove("ow-held");let r=this.fingers.get(e);this.fingers.delete(e),r&&wo(this.parent,e,r),this.changed()}button(e){let o=D("button","ow-control-btn");o.type="button",o.tabIndex=-1,o.addEventListener("pointerdown",a=>{a.preventDefault(),Mt(o,a.pointerId),o.classList.add("ow-held"),this.held.set(a.pointerId,e),this.report.press(e),this.fingers.set(a.pointerId,{x:a.clientX,y:a.clientY}),this.changed()}),o.addEventListener("pointermove",a=>{this.held.get(a.pointerId)===e&&this.fingers.set(a.pointerId,{x:a.clientX,y:a.clientY})});let r=a=>{this.held.get(a.pointerId)===e&&(this.held.delete(a.pointerId),this.fingers.delete(a.pointerId),[...this.held.values()].includes(e)||o.classList.remove("ow-held"),this.changed())};for(let a of["pointerup","pointercancel","lostpointercapture"])o.addEventListener(a,n=>r(n));return o}stickDown(e){if(this.stickPointer!==null)return;e.preventDefault(),Mt(this.zone,e.pointerId),this.stickPointer=e.pointerId,this.fingers.set(e.pointerId,{x:e.clientX,y:e.clientY});let o=this.zone.getBoundingClientRect(),r=this.base.getBoundingClientRect(),a=$+8;this.center={x:Math.min(Math.max(e.clientX,o.left+a),o.right-a),y:Math.min(Math.max(e.clientY,o.top+a),o.bottom-a)},this.base.style.transform=`translate(${this.center.x-(r.left+r.width/2)}px, ${this.center.y-(r.top+r.height/2)}px)`,this.base.classList.add("ow-active"),this.stickMove(e)}stickMove(e){if(e.pointerId!==this.stickPointer)return;this.fingers.set(e.pointerId,{x:e.clientX,y:e.clientY});let o=e.clientX-this.center.x,r=e.clientY-this.center.y,a=Math.hypot(o,r);a>$&&(o=o/a*$,r=r/a*$),this.knob.style.transform=`translate(${o}px, ${r}px)`;let n=Math.min(a,$)/$,i=n<Ae?0:(n-Ae)/(1-Ae)/(n||1);this.x=Lt(o/$*i),this.y=Lt(r/$*i),this.changed()}stickUp(e){e.pointerId===this.stickPointer&&(this.fingers.delete(e.pointerId),this.endStick())}endStick(){this.stickPointer=null,this.x=0,this.y=0,this.base.classList.remove("ow-active"),this.base.style.transform="",this.knob.style.transform="",this.changed()}changed(){this.queued||(this.queued=requestAnimationFrame(()=>{this.queued=0;let{buttons:e,owed:o}=this.report.take(this.held.values()),r={x:this.x,y:this.y,buttons:e};o&&this.changed();let a=JSON.stringify(r);a!==this.sent&&(this.sent=a,this.send(r))}))}};function wo(t,e,o){let r=D("div","ow-tap-shield");r.style.left=`${o.x-Le/2}px`,r.style.top=`${o.y-Le/2}px`,r.style.width=r.style.height=`${Le}px`,t.append(r);let a=setTimeout(()=>r.remove(),bo),n=()=>{clearTimeout(a),a=setTimeout(()=>r.remove(),fo)};for(let i of["pointerup","pointercancel","lostpointercapture"])r.addEventListener(i,s=>s.pointerId===e&&n());r.addEventListener("contextmenu",i=>i.preventDefault());try{r.setPointerCapture(e)}catch{n()}}function Mt(t,e){try{t.setPointerCapture(e)}catch{}}function At(t){let e=t.getBoundingClientRect(),o=getComputedStyle(t).transform;if(!o||o==="none")return e;let r=new DOMMatrixReadOnly(o);if(r.b||r.c||!r.a||!r.d)return e;let a=e.width/Math.abs(r.a),n=e.height/Math.abs(r.d),i=e.left+e.width/2-r.e,s=e.top+e.height/2-r.f;return{left:i-a/2,top:s-n/2,width:a,height:n}}function vo(t,e){let o=Math.min(t.left,e.left),r=Math.min(t.top,e.top);return{left:o,top:r,width:Math.max(t.left+t.width,e.left+e.width)-o,height:Math.max(t.top+t.height,e.top+e.height)-r}}function Lt(t){return Math.round(t*1e3)/1e3}function D(t,e,o){let r=document.createElement(t);return r.className=e,o!==void 0&&(r.textContent=o),r}function Y(t,e){let o=[];for(let{kind:r,box:a}of e){if(!a||!(a.width>0)||!(a.height>0))continue;let n=Math.max(0,a.left-t.left),i=Math.max(0,a.top-t.top),s=Math.min(t.width,a.left+a.width-t.left),d=Math.min(t.height,a.top+a.height-t.top);if(!(s-n>.01&&d-i>.01))continue;let c=Math.floor(n+.01),p=Math.floor(i+.01);o.push({kind:r,x:c,y:p,w:Math.ceil(s-.01)-c,h:Math.ceil(d-.01)-p})}return o}var se=class{measure;send;nextFrame;queued=!1;sent=null;constructor(e,o,r=a=>requestAnimationFrame(a)){this.measure=e,this.send=o,this.nextFrame=r}changed(){this.queued||(this.queued=!0,this.nextFrame(()=>{this.queued=!1;let e=this.measure();if(!e)return;let o=JSON.stringify(e);o!==this.sent&&(this.sent=o,this.send(e))}))}resend(){this.sent=null,this.changed()}};var $t=t=>Math.max(0,Math.ceil(t/1e3)),$e=t=>{let e=t.slice(0,2).map(o=>o.name);return t.length>2?`${e.join(", ")} +${t.length-2}`:e.join(", ")};function yo(t){let{you:e,host:o,kind:r,match:a,now:n}=t,i=[...t.players].sort((l,f)=>l.id===e?-1:f.id===e?1:l.id===o?-1:f.id===o?1:l.name.localeCompare(f.name)).map(l=>({id:l.id,name:l.name,ready:!!l.ready,host:l.id===o,you:l.id===e,away:l.connected===!1,idle:l.connected!==!1&&!!l.idle})),s=t.players.filter(l=>l.connected!==!1),d=t.players.find(l=>l.id===e),c=o===e&&a.phase==="lobby",p=t.schema.map(l=>({id:l.id,label:l.label,value:et(l,t.written),options:l.options,editable:c})),x={n:s.filter(l=>l.ready||r!=="public"&&l.id===o).length,of:s.length},m={surface:"none",rows:i,count:`${t.players.length} / ${t.max}`,ready:x,status:"",action:{kind:"none",label:"",disabled:!0},settings:p,seconds:null},E=a.participants?.includes(e)??!1,K=o===e&&r!=="public";if(a.phase==="starting"){if(!E)return{...m,surface:"watching",status:"Watching"};let l=K?{kind:"stop",label:"Stop",disabled:!1}:{kind:"unready",label:"Not ready",disabled:!1};return t.ownCountdown?{...m,surface:"countdown",action:l,seconds:null,status:"Get ready"}:{...m,surface:"countdown",action:l,seconds:Math.max(1,$t((a.startsAt??n)-n)),status:"Get ready"}}if(a.phase==="playing"){if(a.paused){let l=s.filter(f=>a.participants?.includes(f.id)).length;return a.paused.reason==="host"?{...m,surface:"paused",status:"Paused"}:{...m,surface:"paused",seconds:$t(a.paused.since+P.matchAbandonMs-n),status:`Waiting for players \xB7 ${l} / ${a.min}`}}return E?m:{...m,surface:"watching",status:"Watching"}}let b=s.filter(l=>!l.ready&&(r==="public"||l.id!==o));if(m.surface="lobby",K){let l=s.length<a.min;return m.action={kind:"start",label:"Start",disabled:l||b.length>0},m.status=l?`Need ${a.min} players`:b.length?`Waiting for ${$e(b)}`:"",m}if(m.action={kind:d?.ready?"unready":"ready",label:d?.ready?"Not ready":"Ready",disabled:!1},r==="public")s.length<a.min?m.status=`Need ${a.min} players`:a.waitUntil!==void 0&&b.length?m.status=b.some(l=>l.id===e)?"Waiting for you":`Waiting for ${$e(b)}`:m.status=`${s.length-b.length} / ${s.length} ready`;else{let l=b.filter(f=>f.id!==e);m.status=d?.ready?l.length?`Waiting for ${$e(l)}`:`Waiting for ${t.players.find(f=>f.id===o)?.name??"the host"}`:""}return m}function h(t,e="",o){let r=document.createElement(t);return e&&(r.className=e),o!==void 0&&(r.textContent=o),r}var le=class{mode=null;ownCountdown=!1;targetOk=!1;targetTimer=0;lastKey=-1/0;state=null;schema=[];timer=0;opts;root;card;title;count;list;settingsBox;status;action;invite;bar;barFaces;barStatus;barAction;countdown;numeral;cancel;pause;pauseStatus;pauseTimer;chip;last=null;lastNumeral=-1;listSignature="";settingsSignature="";faceSignature="";constructor(e,o){this.opts=o,this.root=h("div","ow-lobby"),this.root.hidden=!0;for(let s of["pointerdown","mousedown"])this.root.addEventListener(s,d=>d.preventDefault());this.card=h("section","ow-lobby-card"),this.card.setAttribute("aria-label","Lobby");let r=h("header","ow-lobby-head");this.title=h("h2","","Lobby"),this.count=h("span","ow-lobby-count"),r.append(this.title,this.count),this.list=h("ul","ow-lobby-players"),this.settingsBox=h("div","ow-lobby-settings"),this.status=h("p","ow-lobby-status"),this.status.setAttribute("role","status"),this.action=this.button("ow-btn ow-btn-primary ow-lobby-action",()=>this.press()),this.invite=this.button("ow-btn ow-lobby-invite",()=>this.opts.onInvite()),this.invite.textContent="Invite";let a=h("div","ow-lobby-actions");a.append(this.action,this.invite),this.card.append(r,this.list,this.settingsBox,this.status,a),this.bar=h("div","ow-lobby-bar"),this.barFaces=h("span","ow-lobby-faces"),this.barStatus=h("span","ow-lobby-bar-status"),this.barStatus.setAttribute("role","status"),this.barAction=this.button("ow-btn ow-btn-primary ow-lobby-action",()=>this.press()),this.bar.append(this.barFaces,this.barStatus,this.barAction),this.countdown=h("div","ow-lobby-countdown"),this.numeral=h("b"),this.numeral.setAttribute("aria-hidden","true");let n=h("span","","Get ready");n.setAttribute("aria-hidden","true"),this.cancel=this.button("ow-btn ow-lobby-cancel",()=>this.press()),this.countdown.append(this.numeral,n,this.cancel),this.pause=h("div","ow-lobby-pause");let i=h("div","ow-lobby-pause-box");this.pauseStatus=h("p","ow-lobby-pause-status"),this.pauseStatus.setAttribute("role","status"),this.pauseTimer=h("p","ow-lobby-pause-timer"),i.append(this.pauseStatus,this.pauseTimer),this.pause.append(i),this.chip=h("div","ow-lobby-chip"),this.chip.setAttribute("role","status"),this.root.append(this.card,this.bar,this.countdown,this.pause,this.chip),e.append(this.root)}setSchema(e){this.schema=e,this.render()}enable(e,o={}){this.mode=e,this.ownCountdown=o.ownCountdown===!0,this.root.dataset.mode=e??"",e||this.reset(),this.render()}setLook(e){ne(this.root,zt,e)}reservedBox(){if(this.root.hidden)return null;let e=!this.countdown.hidden&&this.countdown.classList.contains("ow-lobby-countdown-bare"),o=this.bar.hidden?e&&!this.cancel.hidden?this.cancel:null:this.bar;return o?o.getBoundingClientRect():null}link(e){let o=!this.root.hidden&&(this.last?.surface==="lobby"||this.last?.surface==="countdown"),r=this.pressable()?.getBoundingClientRect()??null;if(!(r!==null&&r.left>=e.left&&r.top>=e.top&&r.left+r.width<=e.left+e.width&&r.top+r.height<=e.top+e.height))return{keys:o,button:null,cover:null};let[n]=Y(e,[{kind:"lobby",box:r}]),[i]=this.mode==="bar"?Y(e,[{kind:"lobby",box:this.bar.getBoundingClientRect()}]):[{x:0,y:0,w:e.width,h:e.height}];return!n||!i?{keys:o,button:null,cover:null}:{keys:o,button:{x:n.x,y:n.y,w:n.w,h:n.h},cover:{x:i.x,y:i.y,w:i.w,h:i.h}}}setTarget(e,o){window.clearTimeout(this.targetTimer),e&&(this.targetTimer=window.setTimeout(()=>this.setTarget(!1,!1),1600)),this.targetOk!==e&&(this.targetOk=e,this.applyTarget()),this.pressable()?.classList.toggle("ow-lobby-hover",e&&o)}pressKey(e=performance.now()){this.pressable()===null||e-this.lastKey<ft||(this.lastKey=e,this.press())}pressTarget(){this.pressable()&&this.press()}setKeyMark(e){this.root.classList.toggle("ow-lobby-keys",e)}pressable(){let e=this.last;return this.root.hidden||!e||e.surface!=="lobby"||e.action.kind==="none"||e.action.disabled?null:this.mode==="card"?this.action:this.barAction}applyTarget(){let e=this.targetOk&&this.pressable()!==null;if(this.root.classList.toggle("ow-lobby-through",e),!e)for(let o of[this.action,this.barAction])o.classList.remove("ow-lobby-hover")}setRoom(e,o=0){if(!e)return this.reset();this.state={you:e.you,host:e.host,kind:e.room.startsWith("private:")?"private":e.room.startsWith("room:")?"named":"public",max:Math.max(o,e.players.length),players:e.players.map(r=>({...r})),match:e.match??{phase:"lobby",n:0,min:1},written:e.state?.[V]},this.render()}handle(e){let o=this.state;if(o){switch(e.t){case"join":o.players=[...o.players.filter(r=>r.id!==e.player.id),{...e.player}];break;case"leave":o.players=o.players.filter(r=>r.id!==e.id);break;case"away":o.players=o.players.map(r=>r.id===e.id?{...r,connected:!1}:r);break;case"back":o.players=o.players.map(r=>{if(r.id!==e.id)return r;let{connected:a,...n}=r;return n});break;case"ready":o.players=o.players.map(r=>{if(r.id!==e.id)return r;let{ready:a,...n}=r;return e.ready?{...n,ready:!0}:n});break;case"unready":o.players=o.players.map(({ready:r,...a})=>a);break;case"host":o.host=e.id;break;case"idle":o.players=o.players.map(r=>{if(r.id!==e.id)return r;let{idle:a,...n}=r;return e.idle?{...n,idle:!0}:n});break;case"name":o.players=o.players.map(r=>r.id===e.id?{...r,name:e.name}:r);break;case"match":o.match=e.match;break;case"state":if(e.k!==V)return;o.written=e.v;break;default:return}this.render()}}chooseSetting(e,o){let r=this.state,a=this.schema.find(i=>i.id===e);if(!r||!a||!a.options.some(i=>i.value===o))return null;let n={...r.written!==null&&typeof r.written=="object"?r.written:{},[e]:o};return r.written=n,this.render(),n}setReadyLocal(e){let o=this.state?.players.find(r=>r.id===this.state?.you);o&&(e?o.ready=!0:delete o.ready,this.render())}button(e,o){let r=h("button",e);return r.type="button",r.addEventListener("pointerdown",a=>a.preventDefault()),r.addEventListener("click",o),r}press(){let e=this.last?.action.kind;e==="start"?this.opts.onStart():e==="stop"?this.opts.onStop():e==="ready"?(this.setReadyLocal(!0),this.opts.onReady(!0)):e==="unready"&&(this.setReadyLocal(!1),this.opts.onReady(!1)),this.opts.onPressed?.()}reset(){this.state=null,this.last=null,this.setTarget(!1,!1),window.clearInterval(this.timer),this.timer=0,this.root.hidden=!0,this.opts.onLayout?.()}render(){this.draw(),this.opts.onLayout?.()}draw(){if(!this.mode||!this.state){this.root.hidden=!0;return}let e=yo({...this.state,schema:this.schema,now:this.opts.now(),ownCountdown:this.ownCountdown});this.last=e;let o=e.surface==="lobby";if(this.root.hidden=e.surface==="none",this.card.hidden=!(o&&this.mode==="card"),this.bar.hidden=!(o&&this.mode==="bar"),this.countdown.hidden=e.surface!=="countdown",this.countdown.classList.toggle("ow-lobby-countdown-bare",e.surface==="countdown"&&e.seconds===null),this.pause.hidden=e.surface!=="paused",this.chip.hidden=e.surface!=="watching",this.root.classList.toggle("ow-lobby-dim",o&&this.mode==="card"),o&&this.mode==="card"&&this.renderCard(e),o&&this.mode==="bar"&&this.renderBar(e),this.applyTarget(),e.surface==="countdown"&&e.seconds!==null&&e.seconds!==this.lastNumeral&&(this.lastNumeral=e.seconds,this.numeral.textContent=String(e.seconds),this.numeral.style.animation="none",this.numeral.offsetWidth,this.numeral.style.animation=""),e.surface==="countdown"&&(this.cancel.textContent=e.action.label),e.surface!=="countdown"&&(this.lastNumeral=-1),e.surface==="paused"&&(this.pauseStatus.textContent=e.status,this.pauseTimer.textContent=e.seconds!==null?`Ends in ${ko(e.seconds)}`:""),e.surface==="watching"){let[a,...n]=e.status.split(" \xB7 "),i=h("span","ow-lobby-chip-more",n.length?` \xB7 ${n.join(" \xB7 ")}`:"");this.chip.replaceChildren(a,i)}let r=e.seconds!==null;r&&!this.timer?this.timer=window.setInterval(()=>this.render(),250):!r&&this.timer&&(window.clearInterval(this.timer),this.timer=0)}renderCard(e){this.count.textContent=e.count,this.settingsBox.hidden=e.settings.length===0,this.status.textContent=e.status,this.status.hidden=e.status==="",this.setAction(this.action,e);let o=JSON.stringify(e.settings);o!==this.settingsSignature&&(this.settingsSignature=o,this.settingsBox.replaceChildren(...e.settings.map(a=>this.settingRow(a))));let r=JSON.stringify(e.rows);r!==this.listSignature&&(this.listSignature=r,this.list.replaceChildren(...e.rows.map(a=>{let n=h("li",a.away||a.idle?"ow-lobby-away":a.ready?"ow-lobby-ready":""),i=h("img","ow-headshot");i.src=`/avatar/${encodeURIComponent(a.id)}/head.svg`,i.alt="";let s=h("span","ow-lobby-name",a.name),d=[a.away?"Reconnecting":a.idle?"Idle":"",a.you?"You":"",a.host?"Host":""].filter(Boolean).join(" \xB7 ");return n.append(i,s),d&&n.append(h("span","ow-player-notes",d)),n.append(h("span",`ow-lobby-check${a.ready?" ow-lobby-check-on":""}`,a.ready?"Ready":"")),n})))}settingRow(e){let o=h("div","ow-lobby-setting");if(o.append(h("span","ow-lobby-setting-label",e.label)),!e.editable)return o.append(h("span","ow-lobby-setting-value",e.options.find(a=>a.value===e.value)?.label??String(e.value))),o;let r=h("div","ow-segments");r.setAttribute("role","radiogroup"),r.setAttribute("aria-label",e.label);for(let a of e.options){let n=this.button(`ow-segment${a.value===e.value?" ow-segment-on":""}`,()=>this.opts.onSetting(e.id,a.value));n.textContent=a.label,n.setAttribute("role","radio"),n.setAttribute("aria-checked",String(a.value===e.value)),r.append(n)}return o.append(r),o}renderBar(e){this.barStatus.textContent=e.status||`${e.ready.n} / ${e.ready.of} ready`,this.setAction(this.barAction,e);let o=JSON.stringify(e.rows.slice(0,5).map(r=>[r.id,r.ready]));o!==this.faceSignature&&(this.faceSignature=o,this.barFaces.replaceChildren(...e.rows.slice(0,5).map(r=>{let a=h("img",`ow-headshot${r.ready?" ow-lobby-face-ready":""}`);return a.src=`/avatar/${encodeURIComponent(r.id)}/head.svg`,a.alt="",a})))}setAction(e,o){e.hidden=o.action.kind==="none",e.textContent=o.action.label,e.disabled=o.action.disabled,e.setAttribute("aria-keyshortcuts","Enter"),e.classList.toggle("ow-btn-primary",o.action.kind!=="unready")}};function ko(t){return`${Math.floor(t/60)}:${String(t%60).padStart(2,"0")}`}var Ce=t=>`ow:resume:${t}`;function j(t,e){try{e?sessionStorage.setItem(Ce(t),JSON.stringify({...e,at:Date.now()})):sessionStorage.removeItem(Ce(t))}catch{}}function Ct(t){try{let e=sessionStorage.getItem(Ce(t));if(!e)return null;let o=performance.getEntriesByType("navigation")[0];if(o&&o.type!=="reload"&&o.type!=="back_forward")return pe(t);let r=JSON.parse(e);return typeof r.key!="string"||typeof r.rejoin!="string"||typeof r.at!="number"||Date.now()-r.at>18e4||Number(r.rejoin.split(".")[0])*1e3<Date.now()?pe(t):{key:r.key,rejoin:r.rejoin}}catch{return null}}var So=t=>`ow:own-server:${t}`;function Tt(t,e){try{sessionStorage.setItem(So(t),e)}catch{}}function pe(t){return j(t,null),null}var de=class extends Error{constructor(o,r=0,a=0,n=""){super(o);this.status=r;this.retryAfterMs=a;this.code=n;this.name="RequestError"}status;retryAfterMs;code;get retryable(){return this.status===0||this.status===408||this.status===429||this.status>=500}};var ce=class{constructor(e=48*1024){this.max=e}max;used=0;async run(e,o){let r=new TextEncoder().encode(e).byteLength;if(this.used+r>this.max)throw new de("Progress is waiting to sync when you return to the game.");this.used+=r;try{return await o()}finally{this.used-=r}}};var Te=/^[2-9]$/.test(new URLSearchParams(location.search).get("player")??"")?new URLSearchParams(location.search).get("player"):null;var zo=null;function Dt(){return zo?.n??null}var Mr=new ce;var Ot=[300,700,1500,3e3,5e3,8e3],Ro=9e4,Eo=1e4,jt=()=>Array.from(crypto.getRandomValues(new Uint8Array(10)),t=>"abcdefghijklmnopqrstuvwxyz0123456789"[t%36]).join(""),It=jt();function Bt(){It=jt()}var _t=null;var Nt=!1;function Gt(t){Nt=t}var Po=5e4,Mo=4e3,ge=class{ws=null;key=null;rejoin=null;you="";closed=!1;attempt=0;droppedAt=0;sleeping=!1;lastHeard=0;heardCount=0;pingAt=0;hintedHidden=!1;pingTimer=0;watchTimer=0;retryTimer=0;page=It;slug;options;callbacks;onVisible=()=>{this.hint(),document.visibilityState==="visible"&&this.wake()};onOnline=()=>this.wake();onShow=e=>e.persisted&&this.wake();onHide=()=>this.hint();constructor(e,o,r){this.slug=e,this.options=o,this.callbacks=r,this.key=o.key??null,this.rejoin=o.rejoin??null,document.addEventListener("visibilitychange",this.onVisible),addEventListener("online",this.onOnline),addEventListener("pageshow",this.onShow),addEventListener("pagehide",this.onHide)}join(){return new Promise((e,o)=>this.open(e,o))}send(e){this.ws?.readyState===WebSocket.OPEN&&this.ws.send(JSON.stringify(e))}hint(){let e=document.visibilityState==="hidden";e===this.hintedHidden||this.ws?.readyState!==WebSocket.OPEN||(this.hintedHidden=e,this.send({t:"vis",hidden:e}))}ping(){let e=this.ws;e?.readyState===WebSocket.OPEN&&(this.pingAt&&Date.now()-this.pingAt<5e3||(this.pingAt=Date.now(),e.send(Se)))}close(){this.closed=!0,j(this.slug,null),this.dispose(),this.ws?.close(1e3)}reload(){return this.closed=!0,this.dispose(),this.ws?.close(at,"Updating"),this.key?.startsWith("pub:")&&this.rejoin?{key:this.key,rejoin:this.rejoin}:null}open(e,o){this.retryTimer=0;let r=new URL(`/api/games/${this.slug}/rooms/connect`,location.href);r.protocol=location.protocol==="https:"?"wss:":"ws:",this.key?(r.searchParams.set("key",this.key),this.rejoin&&r.searchParams.set("rejoin",this.rejoin)):this.options.server?(r.searchParams.set("server",this.options.server),this.options.private&&r.searchParams.set("own","1")):this.options.name?r.searchParams.set("name",this.options.name):(this.options.mode&&r.searchParams.set("mode",this.options.mode),this.options.follow&&r.searchParams.set("follow",this.options.follow)),this.options.maxPlayers&&r.searchParams.set("max",String(this.options.maxPlayers)),this.options.minPlayers&&r.searchParams.set("min",String(this.options.minPlayers)),this.options.countdown!==void 0&&r.searchParams.set("countdown",String(this.options.countdown)),this.options.teams&&r.searchParams.set("teams",String(this.options.teams)),this.options.ranked&&r.searchParams.set("ranked","1"),Te&&r.searchParams.set("devplayer",Te);let a=Dt();a&&r.searchParams.set("tester",a),r.searchParams.set("page",this.page),this.options.build&&r.searchParams.set("build",this.options.build),_t&&r.searchParams.set("pass",_t),Nt&&r.searchParams.set("demo","1");let n=new WebSocket(r);this.ws=n,this.lastHeard=Date.now();let i=!1;n.onopen=()=>{this.lastHeard=Date.now(),window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer),this.pingTimer=window.setInterval(()=>n.readyState===WebSocket.OPEN&&this.ping(),Eo),this.watchTimer=window.setInterval(()=>{n===this.ws&&n.readyState===WebSocket.OPEN&&Date.now()-this.lastHeard>Po&&this.lost(n)},5e3)},n.onmessage=c=>{this.lastHeard=Date.now(),this.heardCount++;let p;try{p=JSON.parse(c.data)}catch{return}if(p.t==="pong"){this.pingAt&&this.callbacks.onRtt?.(Date.now()-this.pingAt),this.pingAt=0;return}if(p.t==="welcome"&&(p.rejoin&&(this.rejoin=p.rejoin),delete p.rejoin,p.room.startsWith("pub:")&&this.rejoin&&j(this.slug,{key:p.room,rejoin:this.rejoin})),p.t==="leave"&&p.kicked&&p.id===this.you){this.close(),this.finish("kicked");return}if(p.t==="welcome"&&(this.hintedHidden=!1,this.hint()),p.t==="welcome"&&!i&&(i=!0,this.key=p.room,this.you=p.you,this.attempt=0,this.droppedAt&&(this.droppedAt=0,this.callbacks.onConnection?.(!0)),e)){let{t:x,...m}=p;e(m),e=void 0;return}this.callbacks.onMessage(p)};let s=!1,d=c=>{if(!s&&(s=!0,window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer),!(this.closed||n!==this.ws))){if(c.code===tt)return this.finish("replaced");if(c.code===rt&&i&&document.visibilityState==="hidden"){this.sleeping=!0,this.droppedAt||(this.droppedAt=Date.now(),this.callbacks.onConnection?.(!1));return}if(c.code===ot){if(i||!o)return this.finish("kicked");this.closed=!0,this.dispose(),j(this.slug,null),o(Object.assign(new Error("You were removed from this server."),{kicked:!0}));return}if(!i&&o){this.closed=!0,this.dispose(),o(new Error(this.options.name||this.options.server?"Could not join that server. It may be full.":"Could not join a server. Try again soon."));return}this.retry()}};n.onclose=d,n.onerror=()=>{window.setTimeout(()=>{n.readyState===WebSocket.CLOSED&&d({code:1006})},1e3)}}retry(){if(this.closed)return;let e=Date.now();if(this.droppedAt||(this.droppedAt=e,this.callbacks.onConnection?.(!1)),e-this.droppedAt>Ro)return this.finish("disconnected");if(this.retryTimer)return;let o=Ot[Math.min(this.attempt++,Ot.length-1)]*(.5+Math.random());this.retryTimer=window.setTimeout(()=>{this.retryTimer=0,this.closed||this.open()},o)}lost(e){if(!(e!==this.ws||this.closed)){e.onopen=e.onmessage=e.onclose=e.onerror=null,window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer);try{e.close()}catch{}this.retry()}}wake(){if(this.closed)return;if(this.sleeping){this.sleeping=!1,this.droppedAt=Date.now(),this.attempt=0,this.open();return}let e=this.ws;if(!e||e.readyState===WebSocket.CLOSING||e.readyState===WebSocket.CLOSED){this.retryTimer&&(window.clearTimeout(this.retryTimer),this.retryTimer=0,this.open());return}if(e.readyState!==WebSocket.OPEN)return;let o=this.heardCount;try{e.send(Se)}catch{return this.lost(e)}window.setTimeout(()=>e===this.ws&&!this.closed&&this.heardCount===o&&this.lost(e),Mo)}dispose(){window.clearInterval(this.pingTimer),window.clearInterval(this.watchTimer),window.clearTimeout(this.retryTimer),this.retryTimer=0,document.removeEventListener("visibilitychange",this.onVisible),removeEventListener("online",this.onOnline),removeEventListener("pageshow",this.onShow),removeEventListener("pagehide",this.onHide)}finish(e){this.closed=!0,this.dispose(),j(this.slug,null),this.callbacks.onClose(e)}};var Ut=`:root {
|
|
4
4
|
color-scheme: light;
|
|
5
5
|
/* Site pages: as wide as this at most, with gutters that grow with the window. */
|
|
6
6
|
--page: 1440px;
|
|
@@ -59,9 +59,8 @@ ${wt}`,r),r}),this.named}async adopt(e,o){let n=(await this.open()).transaction(
|
|
|
59
59
|
--play-fill-hover: #ff8366;
|
|
60
60
|
--play-ink: #121418;
|
|
61
61
|
--play-text: var(--ok);
|
|
62
|
-
/* Live: players in a game right now. The store's signal colour: a dot, a count
|
|
62
|
+
/* Live: players in a game right now. The store's signal colour: a dot, a count. */
|
|
63
63
|
--live: #3ddc84;
|
|
64
|
-
--live-ink: #0b2a17;
|
|
65
64
|
--live-text: #12813f;
|
|
66
65
|
/* The phone tab bar (and popups opened from it). */
|
|
67
66
|
--dock-bg: var(--bar);
|
|
@@ -74,9 +73,9 @@ ${wt}`,r),r}),this.named}async adopt(e,o){let n=(await this.open()).transaction(
|
|
|
74
73
|
/* The top bar's height (popups opened from it hang under it). */
|
|
75
74
|
--bar-h: 60px;
|
|
76
75
|
--radius: 8px;
|
|
77
|
-
/* Panels
|
|
76
|
+
/* Panels and sheets; every picture, game icon and video is --radius-art. */
|
|
78
77
|
--radius-widget: 12px;
|
|
79
|
-
--radius-art:
|
|
78
|
+
--radius-art: 2px;
|
|
80
79
|
--font: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
|
|
81
80
|
--font-display: var(--font);
|
|
82
81
|
--mono: ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
|
|
@@ -96,25 +95,25 @@ ${wt}`,r),r}),this.named}async adopt(e,o){let n=(await this.open()).transaction(
|
|
|
96
95
|
*/
|
|
97
96
|
:root[data-theme='dark'] {
|
|
98
97
|
color-scheme: dark;
|
|
99
|
-
--bg: #
|
|
100
|
-
--bg-soft: #
|
|
101
|
-
--bg-raised: #
|
|
102
|
-
--bg-card: #
|
|
103
|
-
--bg-hover: #
|
|
104
|
-
--bar: #
|
|
98
|
+
--bg: #121212;
|
|
99
|
+
--bg-soft: #1a1a1a;
|
|
100
|
+
--bg-raised: #1e1e1e;
|
|
101
|
+
--bg-card: #1e1e1e;
|
|
102
|
+
--bg-hover: #282828;
|
|
103
|
+
--bar: #0a0a0a;
|
|
105
104
|
--line: rgba(255, 255, 255, 0.07);
|
|
106
105
|
--line-strong: rgba(255, 255, 255, 0.14);
|
|
107
|
-
--text: #
|
|
108
|
-
--muted: #
|
|
106
|
+
--text: #ececec;
|
|
107
|
+
--muted: #9e9e9e;
|
|
109
108
|
--accent: #ff7a5c;
|
|
110
109
|
--accent-hover: #ff9177;
|
|
111
110
|
--accent-fill: #d23c1b;
|
|
112
111
|
--accent-fill-hover: #b93314;
|
|
113
112
|
--accent-soft: rgba(255, 122, 92, 0.16);
|
|
114
113
|
--accent-text: #ff9a80;
|
|
115
|
-
--ink: #
|
|
114
|
+
--ink: #ececec;
|
|
116
115
|
--ink-hover: #ffffff;
|
|
117
|
-
--ink-text: #
|
|
116
|
+
--ink-text: #121212;
|
|
118
117
|
--ok: #3ddc84;
|
|
119
118
|
--ok-soft: rgba(61, 220, 132, 0.14);
|
|
120
119
|
--online: #60a5fa;
|
|
@@ -130,12 +129,12 @@ ${wt}`,r),r}),this.named}async adopt(e,o){let n=(await this.open()).transaction(
|
|
|
130
129
|
--stat-play: #60a5fa;
|
|
131
130
|
--play-text: #5fe08f;
|
|
132
131
|
--live-text: #3ddc84;
|
|
133
|
-
--dock-bg: #
|
|
132
|
+
--dock-bg: #0a0a0a;
|
|
134
133
|
--dock-edge: rgba(255, 255, 255, 0.08);
|
|
135
|
-
--edit-page: #
|
|
136
|
-
--edit-bar: #
|
|
137
|
-
--edit-screen: #
|
|
138
|
-
--edit-field: #
|
|
134
|
+
--edit-page: #121212;
|
|
135
|
+
--edit-bar: #1a1a1a;
|
|
136
|
+
--edit-screen: #1e1e1e;
|
|
137
|
+
--edit-field: #222222;
|
|
139
138
|
--edit-line: rgba(255, 255, 255, 0.08);
|
|
140
139
|
--edit-line-strong: rgba(255, 255, 255, 0.15);
|
|
141
140
|
--edit-go: #d33e00;
|
|
@@ -144,25 +143,25 @@ ${wt}`,r),r}),this.named}async adopt(e,o){let n=(await this.open()).transaction(
|
|
|
144
143
|
@media (prefers-color-scheme: dark) {
|
|
145
144
|
:root:not([data-theme='light']) {
|
|
146
145
|
color-scheme: dark;
|
|
147
|
-
--bg: #
|
|
148
|
-
--bg-soft: #
|
|
149
|
-
--bg-raised: #
|
|
150
|
-
--bg-card: #
|
|
151
|
-
--bg-hover: #
|
|
152
|
-
--bar: #
|
|
146
|
+
--bg: #121212;
|
|
147
|
+
--bg-soft: #1a1a1a;
|
|
148
|
+
--bg-raised: #1e1e1e;
|
|
149
|
+
--bg-card: #1e1e1e;
|
|
150
|
+
--bg-hover: #282828;
|
|
151
|
+
--bar: #0a0a0a;
|
|
153
152
|
--line: rgba(255, 255, 255, 0.07);
|
|
154
153
|
--line-strong: rgba(255, 255, 255, 0.14);
|
|
155
|
-
--text: #
|
|
156
|
-
--muted: #
|
|
154
|
+
--text: #ececec;
|
|
155
|
+
--muted: #9e9e9e;
|
|
157
156
|
--accent: #ff7a5c;
|
|
158
157
|
--accent-hover: #ff9177;
|
|
159
158
|
--accent-fill: #d23c1b;
|
|
160
159
|
--accent-fill-hover: #b93314;
|
|
161
160
|
--accent-soft: rgba(255, 122, 92, 0.16);
|
|
162
161
|
--accent-text: #ff9a80;
|
|
163
|
-
--ink: #
|
|
162
|
+
--ink: #ececec;
|
|
164
163
|
--ink-hover: #ffffff;
|
|
165
|
-
--ink-text: #
|
|
164
|
+
--ink-text: #121212;
|
|
166
165
|
--ok: #3ddc84;
|
|
167
166
|
--ok-soft: rgba(61, 220, 132, 0.14);
|
|
168
167
|
--online: #60a5fa;
|
|
@@ -178,12 +177,12 @@ ${wt}`,r),r}),this.named}async adopt(e,o){let n=(await this.open()).transaction(
|
|
|
178
177
|
--stat-play: #60a5fa;
|
|
179
178
|
--play-text: #5fe08f;
|
|
180
179
|
--live-text: #3ddc84;
|
|
181
|
-
--dock-bg: #
|
|
180
|
+
--dock-bg: #0a0a0a;
|
|
182
181
|
--dock-edge: rgba(255, 255, 255, 0.08);
|
|
183
|
-
--edit-page: #
|
|
184
|
-
--edit-bar: #
|
|
185
|
-
--edit-screen: #
|
|
186
|
-
--edit-field: #
|
|
182
|
+
--edit-page: #121212;
|
|
183
|
+
--edit-bar: #1a1a1a;
|
|
184
|
+
--edit-screen: #1e1e1e;
|
|
185
|
+
--edit-field: #222222;
|
|
187
186
|
--edit-line: rgba(255, 255, 255, 0.08);
|
|
188
187
|
--edit-line-strong: rgba(255, 255, 255, 0.15);
|
|
189
188
|
--edit-go: #d33e00;
|
|
@@ -385,12 +384,33 @@ h3 {
|
|
|
385
384
|
color: var(--danger);
|
|
386
385
|
}
|
|
387
386
|
|
|
388
|
-
.
|
|
387
|
+
/* (A row's buttons are always this size: a list reads the same whatever its row can do.) */
|
|
388
|
+
.btn-small,
|
|
389
|
+
.row-actions .btn {
|
|
389
390
|
min-height: 32px;
|
|
390
391
|
padding: 0 12px;
|
|
391
392
|
font-size: 13px;
|
|
392
393
|
}
|
|
393
394
|
|
|
395
|
+
/* Fingers: small buttons and links stay easy to hit (padding on the links, which doesn't move anything around them). */
|
|
396
|
+
@media (pointer: coarse) {
|
|
397
|
+
.btn-small,
|
|
398
|
+
.row-actions .btn {
|
|
399
|
+
min-height: 40px;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.see-all,
|
|
403
|
+
.clear-search {
|
|
404
|
+
margin: -10px 0;
|
|
405
|
+
padding: 10px 0;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.label-row a,
|
|
409
|
+
.auth-switch a {
|
|
410
|
+
padding: 10px 4px;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
394
414
|
/* A plain file picker (a form that posts its file, like Upload files' Cover): its button is a small .btn. */
|
|
395
415
|
input[type='file'] {
|
|
396
416
|
max-width: 100%;
|
|
@@ -440,10 +460,14 @@ input[type='file']::file-selector-button:hover {
|
|
|
440
460
|
|
|
441
461
|
.link-btn {
|
|
442
462
|
padding: 6px 10px;
|
|
463
|
+
border: 0;
|
|
464
|
+
background: none;
|
|
443
465
|
color: var(--text);
|
|
466
|
+
font-family: inherit;
|
|
444
467
|
font-weight: 600;
|
|
445
468
|
font-size: 14px;
|
|
446
469
|
text-decoration: none;
|
|
470
|
+
cursor: pointer;
|
|
447
471
|
}
|
|
448
472
|
|
|
449
473
|
.link-btn:hover {
|
|
@@ -463,6 +487,7 @@ input[type='text'],
|
|
|
463
487
|
input[type='email'],
|
|
464
488
|
input[type='password'],
|
|
465
489
|
input[type='search'],
|
|
490
|
+
input[type='number'],
|
|
466
491
|
input:not([type]),
|
|
467
492
|
select,
|
|
468
493
|
textarea {
|
|
@@ -771,11 +796,10 @@ label.check input {
|
|
|
771
796
|
background: var(--bar);
|
|
772
797
|
}
|
|
773
798
|
|
|
799
|
+
/* Edge to edge at any width: the mark lines up with the sidebar's words, the account the same distance from the right. */
|
|
774
800
|
.topbar-inner {
|
|
775
|
-
max-width: var(--page);
|
|
776
|
-
margin: 0 auto;
|
|
777
801
|
height: var(--bar-h);
|
|
778
|
-
padding: 0
|
|
802
|
+
padding: 0 22px;
|
|
779
803
|
display: flex;
|
|
780
804
|
align-items: center;
|
|
781
805
|
gap: 8px;
|
|
@@ -1270,6 +1294,15 @@ button.icon-btn:hover {
|
|
|
1270
1294
|
background: var(--accent);
|
|
1271
1295
|
}
|
|
1272
1296
|
|
|
1297
|
+
/* The chat is open over the page: one tab is lit, Chat. */
|
|
1298
|
+
.tabbar:has(> button[aria-expanded='true']) > a[aria-current='page'] {
|
|
1299
|
+
color: var(--dock-muted);
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
.tabbar:has(> button[aria-expanded='true']) > a[aria-current='page']::before {
|
|
1303
|
+
content: none;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1273
1306
|
.tabbar > a:focus-visible,
|
|
1274
1307
|
.tabbar > button:focus-visible {
|
|
1275
1308
|
outline: 2px solid var(--accent);
|
|
@@ -1530,7 +1563,6 @@ body:has(.tabbar) .footer-inner {
|
|
|
1530
1563
|
color: var(--muted);
|
|
1531
1564
|
font-size: 14px;
|
|
1532
1565
|
font-weight: 600;
|
|
1533
|
-
font-variant-numeric: tabular-nums;
|
|
1534
1566
|
}
|
|
1535
1567
|
|
|
1536
1568
|
.see-all {
|
|
@@ -1773,6 +1805,21 @@ body:has(.tabbar) .footer-inner {
|
|
|
1773
1805
|
left: 0;
|
|
1774
1806
|
}
|
|
1775
1807
|
|
|
1808
|
+
@media (max-width: 560px) {
|
|
1809
|
+
.storenav {
|
|
1810
|
+
flex-wrap: wrap;
|
|
1811
|
+
height: auto;
|
|
1812
|
+
}
|
|
1813
|
+
.storenav-links {
|
|
1814
|
+
flex: 1 1 100%;
|
|
1815
|
+
height: 46px;
|
|
1816
|
+
}
|
|
1817
|
+
.storenav-filters,
|
|
1818
|
+
.storenav-random {
|
|
1819
|
+
height: 40px;
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1776
1823
|
.storenav-filters {
|
|
1777
1824
|
display: flex;
|
|
1778
1825
|
}
|
|
@@ -1940,6 +1987,34 @@ body:has(.tabbar) .footer-inner {
|
|
|
1940
1987
|
.store-shell > .page {
|
|
1941
1988
|
padding-bottom: 56px;
|
|
1942
1989
|
}
|
|
1990
|
+
|
|
1991
|
+
/* Home: Featured fills the column to the sidebar, the top bar and the window's edge; the rows under it keep the page's width. */
|
|
1992
|
+
.store-shell > .page.store:has(> .spotlight) {
|
|
1993
|
+
max-width: none;
|
|
1994
|
+
padding-top: 0;
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
.page.store:has(> .spotlight) > * {
|
|
1998
|
+
max-width: calc(1680px - 2 * clamp(20px, 2.6vw, 44px));
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
.page.store > .spotlight {
|
|
2002
|
+
max-width: none;
|
|
2003
|
+
margin-inline: calc(-1 * clamp(20px, 2.6vw, 44px));
|
|
2004
|
+
}
|
|
2005
|
+
|
|
2006
|
+
.page.store > .spotlight .spot-slide {
|
|
2007
|
+
border-radius: 0;
|
|
2008
|
+
}
|
|
2009
|
+
|
|
2010
|
+
/* Its words and dots line up with the rows under it. */
|
|
2011
|
+
.page.store > .spotlight .spot-info {
|
|
2012
|
+
padding-left: clamp(20px, 2.6vw, 44px);
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
.page.store > .spotlight .spot-dots {
|
|
2016
|
+
right: clamp(20px, 2.6vw, 44px);
|
|
2017
|
+
}
|
|
1943
2018
|
}
|
|
1944
2019
|
|
|
1945
2020
|
.store-side {
|
|
@@ -2063,8 +2138,8 @@ body:has(.tabbar) .footer-inner {
|
|
|
2063
2138
|
position: relative;
|
|
2064
2139
|
min-width: 0;
|
|
2065
2140
|
overflow: hidden;
|
|
2066
|
-
border-radius: var(--radius-
|
|
2067
|
-
background: #
|
|
2141
|
+
border-radius: var(--radius-art);
|
|
2142
|
+
background: #0a0a0a;
|
|
2068
2143
|
opacity: 0;
|
|
2069
2144
|
visibility: hidden;
|
|
2070
2145
|
transition: opacity 0.45s ease, visibility 0s linear 0.45s;
|
|
@@ -2425,17 +2500,6 @@ body:has(.tabbar) .footer-inner {
|
|
|
2425
2500
|
background: var(--live);
|
|
2426
2501
|
}
|
|
2427
2502
|
|
|
2428
|
-
.btn.btn-live {
|
|
2429
|
-
border-color: transparent;
|
|
2430
|
-
background: var(--live);
|
|
2431
|
-
color: var(--live-ink);
|
|
2432
|
-
font-weight: 700;
|
|
2433
|
-
}
|
|
2434
|
-
|
|
2435
|
-
.btn.btn-live:hover {
|
|
2436
|
-
background: color-mix(in srgb, var(--live) 85%, #fff);
|
|
2437
|
-
}
|
|
2438
|
-
|
|
2439
2503
|
/* Every game: its title (with See all on home, Clear on a search), the filters that are on, and the grid. */
|
|
2440
2504
|
.browse-head {
|
|
2441
2505
|
display: flex;
|
|
@@ -2665,7 +2729,7 @@ body:has(.tabbar) .footer-inner {
|
|
|
2665
2729
|
height: auto;
|
|
2666
2730
|
margin: auto;
|
|
2667
2731
|
aspect-ratio: 1;
|
|
2668
|
-
border-radius:
|
|
2732
|
+
border-radius: var(--radius-art);
|
|
2669
2733
|
}
|
|
2670
2734
|
|
|
2671
2735
|
.app-art:has(.app-img-icon) {
|
|
@@ -2900,6 +2964,14 @@ body:has(.tabbar) .footer-inner {
|
|
|
2900
2964
|
padding: 96px 16px;
|
|
2901
2965
|
}
|
|
2902
2966
|
|
|
2967
|
+
.lib-empty-actions {
|
|
2968
|
+
display: flex;
|
|
2969
|
+
flex-wrap: wrap;
|
|
2970
|
+
justify-content: center;
|
|
2971
|
+
gap: 10px;
|
|
2972
|
+
margin-top: 20px;
|
|
2973
|
+
}
|
|
2974
|
+
|
|
2903
2975
|
/* A repo whose first deploy failed, in the side: its square says so. */
|
|
2904
2976
|
.lib-icon.mine-failed {
|
|
2905
2977
|
color: var(--danger);
|
|
@@ -2950,13 +3022,17 @@ body:has(.tabbar) .footer-inner {
|
|
|
2950
3022
|
place-items: center;
|
|
2951
3023
|
width: clamp(22px, 10.4cqi, 36px);
|
|
2952
3024
|
height: clamp(22px, 10.4cqi, 36px);
|
|
2953
|
-
border-radius:
|
|
3025
|
+
border-radius: var(--radius-art);
|
|
2954
3026
|
object-fit: cover;
|
|
2955
|
-
background: var(--fill);
|
|
2956
3027
|
font-size: 12px;
|
|
2957
3028
|
font-weight: 800;
|
|
2958
3029
|
}
|
|
2959
3030
|
|
|
3031
|
+
/* (A letter's square keeps its game's colour.) */
|
|
3032
|
+
.lib-icon:not(.gcard-letter) {
|
|
3033
|
+
background: var(--fill);
|
|
3034
|
+
}
|
|
3035
|
+
|
|
2960
3036
|
@container side (min-width: 320px) {
|
|
2961
3037
|
.lib-list a {
|
|
2962
3038
|
min-height: 42px;
|
|
@@ -2964,7 +3040,6 @@ body:has(.tabbar) .footer-inner {
|
|
|
2964
3040
|
}
|
|
2965
3041
|
|
|
2966
3042
|
.lib-icon {
|
|
2967
|
-
border-radius: 7px;
|
|
2968
3043
|
font-size: 15px;
|
|
2969
3044
|
}
|
|
2970
3045
|
}
|
|
@@ -2993,7 +3068,7 @@ body:has(.tabbar) .footer-inner {
|
|
|
2993
3068
|
height: clamp(220px, 27vw, 440px);
|
|
2994
3069
|
aspect-ratio: auto;
|
|
2995
3070
|
overflow: hidden;
|
|
2996
|
-
border-radius: var(--radius-
|
|
3071
|
+
border-radius: var(--radius-art);
|
|
2997
3072
|
}
|
|
2998
3073
|
|
|
2999
3074
|
.lib-hero::after {
|
|
@@ -3639,7 +3714,7 @@ body:has(.tabbar) .footer-inner {
|
|
|
3639
3714
|
flex: none;
|
|
3640
3715
|
width: 60px;
|
|
3641
3716
|
height: 60px;
|
|
3642
|
-
border-radius:
|
|
3717
|
+
border-radius: var(--radius-art);
|
|
3643
3718
|
object-fit: cover;
|
|
3644
3719
|
box-shadow: var(--ring);
|
|
3645
3720
|
font-size: 28px;
|
|
@@ -3685,6 +3760,11 @@ body:has(.tabbar) .footer-inner {
|
|
|
3685
3760
|
align-items: start;
|
|
3686
3761
|
}
|
|
3687
3762
|
|
|
3763
|
+
/* A page with nothing else: More like this keeps the gap it has under the game's body. */
|
|
3764
|
+
.game-top + .section {
|
|
3765
|
+
margin-top: 44px;
|
|
3766
|
+
}
|
|
3767
|
+
|
|
3688
3768
|
/* One column: Play comes first in the panel, right under the gallery. */
|
|
3689
3769
|
@media (max-width: 1000px) {
|
|
3690
3770
|
.game-top {
|
|
@@ -3709,7 +3789,7 @@ body:has(.tabbar) .footer-inner {
|
|
|
3709
3789
|
overflow-x: auto;
|
|
3710
3790
|
scroll-snap-type: x mandatory;
|
|
3711
3791
|
scrollbar-width: none;
|
|
3712
|
-
border-radius: var(--radius-
|
|
3792
|
+
border-radius: var(--radius-art);
|
|
3713
3793
|
background: var(--bg-soft);
|
|
3714
3794
|
box-shadow: var(--ring);
|
|
3715
3795
|
aspect-ratio: 16 / 9;
|
|
@@ -3750,7 +3830,7 @@ body:has(.tabbar) .footer-inner {
|
|
|
3750
3830
|
width: 30%;
|
|
3751
3831
|
height: auto;
|
|
3752
3832
|
aspect-ratio: 1;
|
|
3753
|
-
border-radius:
|
|
3833
|
+
border-radius: var(--radius-art);
|
|
3754
3834
|
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.25);
|
|
3755
3835
|
}
|
|
3756
3836
|
|
|
@@ -3780,7 +3860,7 @@ body:has(.tabbar) .footer-inner {
|
|
|
3780
3860
|
place-items: center;
|
|
3781
3861
|
width: 100%;
|
|
3782
3862
|
aspect-ratio: 16 / 9;
|
|
3783
|
-
border-radius:
|
|
3863
|
+
border-radius: var(--radius-art);
|
|
3784
3864
|
color: var(--text);
|
|
3785
3865
|
text-decoration: none;
|
|
3786
3866
|
opacity: 0.55;
|
|
@@ -3981,6 +4061,12 @@ body:has(.tabbar) .footer-inner {
|
|
|
3981
4061
|
list-style: none;
|
|
3982
4062
|
}
|
|
3983
4063
|
|
|
4064
|
+
.play-pay > summary,
|
|
4065
|
+
a.play-pay {
|
|
4066
|
+
padding: 6px 0;
|
|
4067
|
+
text-decoration: underline;
|
|
4068
|
+
}
|
|
4069
|
+
|
|
3984
4070
|
.play-pay[open] > summary {
|
|
3985
4071
|
margin-bottom: 8px;
|
|
3986
4072
|
}
|
|
@@ -4367,9 +4453,11 @@ body:has(.tabbar) .footer-inner {
|
|
|
4367
4453
|
}
|
|
4368
4454
|
|
|
4369
4455
|
.fold-count {
|
|
4456
|
+
margin-left: 4px;
|
|
4370
4457
|
color: var(--muted);
|
|
4371
4458
|
font-size: 14px;
|
|
4372
4459
|
font-variant-numeric: tabular-nums;
|
|
4460
|
+
white-space: nowrap;
|
|
4373
4461
|
}
|
|
4374
4462
|
|
|
4375
4463
|
.fold-caret {
|
|
@@ -4549,6 +4637,11 @@ body:has(.tabbar) .footer-inner {
|
|
|
4549
4637
|
margin: 0 0 18px;
|
|
4550
4638
|
}
|
|
4551
4639
|
|
|
4640
|
+
/* An order: its Play or Open, then what was bought. */
|
|
4641
|
+
.market-order .form-row:has(+ .kv) {
|
|
4642
|
+
margin-bottom: 18px;
|
|
4643
|
+
}
|
|
4644
|
+
|
|
4552
4645
|
.kv dt {
|
|
4553
4646
|
color: var(--muted);
|
|
4554
4647
|
font-size: 12px;
|
|
@@ -4960,7 +5053,7 @@ body:has(.auth) .footer {
|
|
|
4960
5053
|
aspect-ratio: 16 / 9;
|
|
4961
5054
|
object-fit: cover;
|
|
4962
5055
|
border: 1px solid var(--line);
|
|
4963
|
-
border-radius:
|
|
5056
|
+
border-radius: var(--radius-art);
|
|
4964
5057
|
background: var(--bg-soft);
|
|
4965
5058
|
}
|
|
4966
5059
|
|
|
@@ -5728,7 +5821,7 @@ label.admin-changed > span::before {
|
|
|
5728
5821
|
.admin-game .dash-icon {
|
|
5729
5822
|
width: 36px;
|
|
5730
5823
|
height: 36px;
|
|
5731
|
-
border-radius:
|
|
5824
|
+
border-radius: var(--radius-art);
|
|
5732
5825
|
}
|
|
5733
5826
|
|
|
5734
5827
|
@media (max-width: 760px) {
|
|
@@ -5901,7 +5994,7 @@ label.admin-changed > span::before {
|
|
|
5901
5994
|
flex: none;
|
|
5902
5995
|
width: 44px;
|
|
5903
5996
|
height: 44px;
|
|
5904
|
-
border-radius:
|
|
5997
|
+
border-radius: var(--radius-art);
|
|
5905
5998
|
object-fit: cover;
|
|
5906
5999
|
display: grid;
|
|
5907
6000
|
place-items: center;
|
|
@@ -6415,7 +6508,7 @@ label.admin-changed > span::before {
|
|
|
6415
6508
|
flex: none;
|
|
6416
6509
|
width: 96px;
|
|
6417
6510
|
height: 96px;
|
|
6418
|
-
border-radius:
|
|
6511
|
+
border-radius: var(--radius-art);
|
|
6419
6512
|
object-fit: cover;
|
|
6420
6513
|
display: grid;
|
|
6421
6514
|
place-items: center;
|
|
@@ -6569,7 +6662,7 @@ label.admin-changed > span::before {
|
|
|
6569
6662
|
|
|
6570
6663
|
.dz-shot {
|
|
6571
6664
|
position: relative;
|
|
6572
|
-
border-radius:
|
|
6665
|
+
border-radius: var(--radius-art);
|
|
6573
6666
|
background: var(--bg-soft);
|
|
6574
6667
|
cursor: grab;
|
|
6575
6668
|
user-select: none;
|
|
@@ -6583,7 +6676,7 @@ label.admin-changed > span::before {
|
|
|
6583
6676
|
width: 100%;
|
|
6584
6677
|
aspect-ratio: 16 / 9;
|
|
6585
6678
|
object-fit: cover;
|
|
6586
|
-
border-radius:
|
|
6679
|
+
border-radius: var(--radius-art);
|
|
6587
6680
|
pointer-events: none;
|
|
6588
6681
|
}
|
|
6589
6682
|
|
|
@@ -6752,7 +6845,9 @@ label.admin-changed > span::before {
|
|
|
6752
6845
|
|
|
6753
6846
|
.sell-modes label {
|
|
6754
6847
|
display: inline-flex;
|
|
6848
|
+
flex-direction: row;
|
|
6755
6849
|
align-items: center;
|
|
6850
|
+
justify-content: center;
|
|
6756
6851
|
min-height: 32px;
|
|
6757
6852
|
padding: 0 14px;
|
|
6758
6853
|
border-radius: 999px;
|
|
@@ -6779,13 +6874,107 @@ label.admin-changed > span::before {
|
|
|
6779
6874
|
outline-offset: 1px;
|
|
6780
6875
|
}
|
|
6781
6876
|
|
|
6782
|
-
.sell-form:has(input[name='mode'][value='free']:checked) :is(.sell-fixed, .sell-pwyw),
|
|
6877
|
+
.sell-form:has(input[name='mode'][value='free']:checked) :is(.sell-fixed, .sell-pwyw, .sell-setup),
|
|
6783
6878
|
.sell-form:has(input[name='mode'][value='fixed']:checked) .sell-pwyw,
|
|
6784
6879
|
.sell-form:has(input[name='mode'][value='pwyw']:checked) .sell-fixed,
|
|
6785
6880
|
.sell-form:not(:has(select[name='license'] option[value='custom']:checked)) .sell-custom {
|
|
6786
6881
|
display: none;
|
|
6787
6882
|
}
|
|
6788
6883
|
|
|
6884
|
+
/* Sell: every card is its heading and then its contents, in the same two columns, so they all line up down the page. */
|
|
6885
|
+
.sell-card {
|
|
6886
|
+
display: grid;
|
|
6887
|
+
grid-template-columns: 160px minmax(0, 480px);
|
|
6888
|
+
gap: 12px 32px;
|
|
6889
|
+
align-items: start;
|
|
6890
|
+
}
|
|
6891
|
+
|
|
6892
|
+
.sell-card h2,
|
|
6893
|
+
.page .sell-card h2 {
|
|
6894
|
+
display: flex;
|
|
6895
|
+
flex-wrap: wrap;
|
|
6896
|
+
align-items: center;
|
|
6897
|
+
gap: 8px;
|
|
6898
|
+
margin: 0;
|
|
6899
|
+
line-height: 38px;
|
|
6900
|
+
}
|
|
6901
|
+
|
|
6902
|
+
.sell-body {
|
|
6903
|
+
min-width: 0;
|
|
6904
|
+
}
|
|
6905
|
+
|
|
6906
|
+
.sell-body > * {
|
|
6907
|
+
margin: 0;
|
|
6908
|
+
}
|
|
6909
|
+
|
|
6910
|
+
.sell-body > * + * {
|
|
6911
|
+
margin-top: 14px;
|
|
6912
|
+
}
|
|
6913
|
+
|
|
6914
|
+
.sell-body > p:first-child {
|
|
6915
|
+
line-height: 38px;
|
|
6916
|
+
}
|
|
6917
|
+
|
|
6918
|
+
.sell-body > .sell-fine {
|
|
6919
|
+
margin-top: 2px;
|
|
6920
|
+
font-size: 13px;
|
|
6921
|
+
}
|
|
6922
|
+
|
|
6923
|
+
.sell-body .stack-form {
|
|
6924
|
+
max-width: none;
|
|
6925
|
+
}
|
|
6926
|
+
|
|
6927
|
+
.sell-body :is(select, .inline-form input) {
|
|
6928
|
+
border-radius: 10px;
|
|
6929
|
+
background-color: var(--bg);
|
|
6930
|
+
}
|
|
6931
|
+
|
|
6932
|
+
.sell-body .inline-form label {
|
|
6933
|
+
color: var(--text);
|
|
6934
|
+
}
|
|
6935
|
+
|
|
6936
|
+
.sell-body .sell-modes {
|
|
6937
|
+
display: flex;
|
|
6938
|
+
align-self: stretch;
|
|
6939
|
+
}
|
|
6940
|
+
|
|
6941
|
+
.sell-body .sell-modes label {
|
|
6942
|
+
flex: 1 1 auto;
|
|
6943
|
+
}
|
|
6944
|
+
|
|
6945
|
+
.sell-actions,
|
|
6946
|
+
.sell-setup {
|
|
6947
|
+
display: flex;
|
|
6948
|
+
flex-wrap: wrap;
|
|
6949
|
+
align-items: center;
|
|
6950
|
+
gap: 8px;
|
|
6951
|
+
}
|
|
6952
|
+
|
|
6953
|
+
.sell-setup {
|
|
6954
|
+
gap: 8px 12px;
|
|
6955
|
+
}
|
|
6956
|
+
|
|
6957
|
+
.sell-actions form {
|
|
6958
|
+
margin: 0;
|
|
6959
|
+
}
|
|
6960
|
+
|
|
6961
|
+
.sell-body .inline-form {
|
|
6962
|
+
margin-bottom: 0;
|
|
6963
|
+
}
|
|
6964
|
+
|
|
6965
|
+
@media (max-width: 720px) {
|
|
6966
|
+
.sell-card {
|
|
6967
|
+
grid-template-columns: minmax(0, 1fr);
|
|
6968
|
+
gap: 8px;
|
|
6969
|
+
}
|
|
6970
|
+
|
|
6971
|
+
.sell-card h2,
|
|
6972
|
+
.page .sell-card h2,
|
|
6973
|
+
.sell-body > p:first-child {
|
|
6974
|
+
line-height: 1.4;
|
|
6975
|
+
}
|
|
6976
|
+
}
|
|
6977
|
+
|
|
6789
6978
|
.sell-now {
|
|
6790
6979
|
display: flex;
|
|
6791
6980
|
flex-wrap: wrap;
|
|
@@ -7213,8 +7402,7 @@ body.play {
|
|
|
7213
7402
|
body.play .ow-menu,
|
|
7214
7403
|
body.play .ow-social-body,
|
|
7215
7404
|
body.play .ow-chat-log,
|
|
7216
|
-
body.play .ow-players
|
|
7217
|
-
body.play .ow-badges {
|
|
7405
|
+
body.play .ow-players {
|
|
7218
7406
|
touch-action: pan-y;
|
|
7219
7407
|
}
|
|
7220
7408
|
|
|
@@ -7744,9 +7932,11 @@ body.play input {
|
|
|
7744
7932
|
padding-bottom: 16px;
|
|
7745
7933
|
}
|
|
7746
7934
|
|
|
7935
|
+
/* Its first line level with the head's buttons. */
|
|
7747
7936
|
.ow-menu-title {
|
|
7748
7937
|
flex: 1;
|
|
7749
7938
|
min-width: 0;
|
|
7939
|
+
padding-top: 4px;
|
|
7750
7940
|
}
|
|
7751
7941
|
|
|
7752
7942
|
.ow-menu-head h2 {
|
|
@@ -7799,8 +7989,7 @@ body.play input {
|
|
|
7799
7989
|
}
|
|
7800
7990
|
|
|
7801
7991
|
.ow-section[hidden],
|
|
7802
|
-
.ow-setting[hidden]
|
|
7803
|
-
.ow-guest[hidden] {
|
|
7992
|
+
.ow-setting[hidden] {
|
|
7804
7993
|
display: none;
|
|
7805
7994
|
}
|
|
7806
7995
|
|
|
@@ -7863,11 +8052,14 @@ body.play input {
|
|
|
7863
8052
|
overflow-y: auto;
|
|
7864
8053
|
}
|
|
7865
8054
|
|
|
8055
|
+
/* A row with more buttons than room takes a second line for them: the name stays readable. */
|
|
7866
8056
|
.ow-players li {
|
|
7867
8057
|
display: flex;
|
|
8058
|
+
flex-wrap: wrap;
|
|
7868
8059
|
align-items: center;
|
|
7869
|
-
gap: 10px;
|
|
8060
|
+
gap: 2px 10px;
|
|
7870
8061
|
min-height: 40px;
|
|
8062
|
+
padding: 2px 0;
|
|
7871
8063
|
font-size: 14px;
|
|
7872
8064
|
}
|
|
7873
8065
|
|
|
@@ -7903,8 +8095,10 @@ a.ow-player-name:focus-visible {
|
|
|
7903
8095
|
}
|
|
7904
8096
|
|
|
7905
8097
|
.ow-player-actions {
|
|
7906
|
-
flex:
|
|
8098
|
+
flex: 0 1 auto;
|
|
7907
8099
|
display: flex;
|
|
8100
|
+
flex-wrap: wrap;
|
|
8101
|
+
justify-content: flex-end;
|
|
7908
8102
|
gap: 6px;
|
|
7909
8103
|
margin-left: auto;
|
|
7910
8104
|
}
|
|
@@ -8046,17 +8240,6 @@ a.ow-player-name:focus-visible {
|
|
|
8046
8240
|
white-space: nowrap;
|
|
8047
8241
|
}
|
|
8048
8242
|
|
|
8049
|
-
.ow-server {
|
|
8050
|
-
display: flex;
|
|
8051
|
-
flex-wrap: wrap;
|
|
8052
|
-
align-items: center;
|
|
8053
|
-
justify-content: space-between;
|
|
8054
|
-
gap: 4px 12px;
|
|
8055
|
-
margin-top: 6px;
|
|
8056
|
-
color: var(--muted);
|
|
8057
|
-
font-size: 13px;
|
|
8058
|
-
}
|
|
8059
|
-
|
|
8060
8243
|
.ow-text-btn {
|
|
8061
8244
|
padding: 0;
|
|
8062
8245
|
border: 0;
|
|
@@ -8120,24 +8303,6 @@ button.ow-setting-icon:hover {
|
|
|
8120
8303
|
outline-offset: 2px;
|
|
8121
8304
|
}
|
|
8122
8305
|
|
|
8123
|
-
.ow-guest {
|
|
8124
|
-
margin: 0;
|
|
8125
|
-
padding: 12px 0;
|
|
8126
|
-
border-top: 1px solid var(--line);
|
|
8127
|
-
color: var(--muted);
|
|
8128
|
-
font-size: 13px;
|
|
8129
|
-
}
|
|
8130
|
-
|
|
8131
|
-
.ow-guest a {
|
|
8132
|
-
color: var(--accent-text);
|
|
8133
|
-
font-weight: 600;
|
|
8134
|
-
text-decoration: none;
|
|
8135
|
-
}
|
|
8136
|
-
|
|
8137
|
-
.ow-guest a:hover {
|
|
8138
|
-
text-decoration: underline;
|
|
8139
|
-
}
|
|
8140
|
-
|
|
8141
8306
|
.ow-menu-foot {
|
|
8142
8307
|
display: flex;
|
|
8143
8308
|
gap: 8px;
|
|
@@ -8307,113 +8472,47 @@ button.ow-setting-icon:hover {
|
|
|
8307
8472
|
letter-spacing: 0.06em;
|
|
8308
8473
|
}
|
|
8309
8474
|
|
|
8310
|
-
.ow-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
gap: 8px;
|
|
8475
|
+
.ow-toast .ow-badge-blank {
|
|
8476
|
+
display: grid;
|
|
8477
|
+
place-items: center;
|
|
8478
|
+
background: var(--accent-soft);
|
|
8479
|
+
color: var(--accent-hover);
|
|
8480
|
+
font-size: 20px;
|
|
8317
8481
|
}
|
|
8318
8482
|
|
|
8319
|
-
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
|
|
8325
|
-
|
|
8326
|
-
|
|
8327
|
-
|
|
8328
|
-
|
|
8483
|
+
/* loading card shown until the game's page has loaded */
|
|
8484
|
+
.ow-loading {
|
|
8485
|
+
position: fixed;
|
|
8486
|
+
inset: var(--ow-vv-top, 0px) 0 var(--ow-vv-bottom, 0px);
|
|
8487
|
+
z-index: 15;
|
|
8488
|
+
display: grid;
|
|
8489
|
+
place-items: center;
|
|
8490
|
+
overflow: hidden;
|
|
8491
|
+
/* Always dark, whatever the theme: the game's cover is darkened behind it. */
|
|
8492
|
+
background: #0e0f12;
|
|
8493
|
+
color: #fff;
|
|
8494
|
+
transition: opacity 0.35s ease;
|
|
8329
8495
|
}
|
|
8330
8496
|
|
|
8331
|
-
|
|
8332
|
-
|
|
8497
|
+
/* Gone once faded, not just see-through: Chrome (GPU) left most of the game's frame unpainted under the invisible card and
|
|
8498
|
+
its blurred cover, the top strip alone showing until a reload. */
|
|
8499
|
+
.ow-loading.ow-hidden {
|
|
8500
|
+
opacity: 0;
|
|
8501
|
+
visibility: hidden;
|
|
8502
|
+
pointer-events: none;
|
|
8503
|
+
transition: opacity 0.35s ease, visibility 0s linear 0.35s;
|
|
8333
8504
|
}
|
|
8334
8505
|
|
|
8335
|
-
.
|
|
8336
|
-
|
|
8337
|
-
|
|
8506
|
+
/* A page that never ran: what's in the frame (a device's filter page, an error) stays in view and can be tapped, the card below it. */
|
|
8507
|
+
.ow-loading.ow-loading-clear {
|
|
8508
|
+
align-items: end;
|
|
8509
|
+
background: none;
|
|
8510
|
+
pointer-events: none;
|
|
8338
8511
|
}
|
|
8339
8512
|
|
|
8340
|
-
.ow-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
}
|
|
8344
|
-
|
|
8345
|
-
.ow-badge-icon {
|
|
8346
|
-
display: block;
|
|
8347
|
-
width: 40px;
|
|
8348
|
-
height: 40px;
|
|
8349
|
-
border-radius: 50%;
|
|
8350
|
-
object-fit: cover;
|
|
8351
|
-
}
|
|
8352
|
-
|
|
8353
|
-
.ow-badge-blank {
|
|
8354
|
-
display: grid;
|
|
8355
|
-
place-items: center;
|
|
8356
|
-
background: var(--fill-strong);
|
|
8357
|
-
color: var(--text);
|
|
8358
|
-
font-size: 18px;
|
|
8359
|
-
}
|
|
8360
|
-
|
|
8361
|
-
.ow-earned .ow-badge-blank,
|
|
8362
|
-
.ow-toast .ow-badge-blank {
|
|
8363
|
-
background: var(--accent-soft);
|
|
8364
|
-
color: var(--accent-hover);
|
|
8365
|
-
}
|
|
8366
|
-
|
|
8367
|
-
.ow-toast .ow-badge-blank {
|
|
8368
|
-
font-size: 20px;
|
|
8369
|
-
}
|
|
8370
|
-
|
|
8371
|
-
.ow-badge-caption {
|
|
8372
|
-
margin: 10px 0 0;
|
|
8373
|
-
color: var(--muted);
|
|
8374
|
-
font-size: 13px;
|
|
8375
|
-
line-height: 1.45;
|
|
8376
|
-
}
|
|
8377
|
-
|
|
8378
|
-
.ow-badge-caption b {
|
|
8379
|
-
margin-right: 2px;
|
|
8380
|
-
color: var(--text);
|
|
8381
|
-
font-weight: 600;
|
|
8382
|
-
}
|
|
8383
|
-
|
|
8384
|
-
/* loading card shown until the game's page has loaded */
|
|
8385
|
-
.ow-loading {
|
|
8386
|
-
position: fixed;
|
|
8387
|
-
inset: var(--ow-vv-top, 0px) 0 var(--ow-vv-bottom, 0px);
|
|
8388
|
-
z-index: 15;
|
|
8389
|
-
display: grid;
|
|
8390
|
-
place-items: center;
|
|
8391
|
-
overflow: hidden;
|
|
8392
|
-
/* Always dark, whatever the theme: the game's cover is darkened behind it. */
|
|
8393
|
-
background: #0e0f12;
|
|
8394
|
-
color: #fff;
|
|
8395
|
-
transition: opacity 0.35s ease;
|
|
8396
|
-
}
|
|
8397
|
-
|
|
8398
|
-
/* Gone once faded, not just see-through: Chrome (GPU) left most of the game's frame unpainted under the invisible card and
|
|
8399
|
-
its blurred cover, the top strip alone showing until a reload. */
|
|
8400
|
-
.ow-loading.ow-hidden {
|
|
8401
|
-
opacity: 0;
|
|
8402
|
-
visibility: hidden;
|
|
8403
|
-
pointer-events: none;
|
|
8404
|
-
transition: opacity 0.35s ease, visibility 0s linear 0.35s;
|
|
8405
|
-
}
|
|
8406
|
-
|
|
8407
|
-
/* A page that never ran: what's in the frame (a device's filter page, an error) stays in view and can be tapped, the card below it. */
|
|
8408
|
-
.ow-loading.ow-loading-clear {
|
|
8409
|
-
align-items: end;
|
|
8410
|
-
background: none;
|
|
8411
|
-
pointer-events: none;
|
|
8412
|
-
}
|
|
8413
|
-
|
|
8414
|
-
.ow-loading-clear .ow-loading-cover,
|
|
8415
|
-
.ow-loading-clear .ow-loading-icon {
|
|
8416
|
-
display: none;
|
|
8513
|
+
.ow-loading-clear .ow-loading-cover,
|
|
8514
|
+
.ow-loading-clear .ow-loading-icon {
|
|
8515
|
+
display: none;
|
|
8417
8516
|
}
|
|
8418
8517
|
|
|
8419
8518
|
.ow-loading-clear .ow-loading-inner {
|
|
@@ -8469,7 +8568,7 @@ button.ow-setting-icon:hover {
|
|
|
8469
8568
|
.ow-loading-icon {
|
|
8470
8569
|
width: 120px;
|
|
8471
8570
|
height: 120px;
|
|
8472
|
-
border-radius:
|
|
8571
|
+
border-radius: var(--radius-art);
|
|
8473
8572
|
object-fit: cover;
|
|
8474
8573
|
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.12), 0 24px 60px rgba(0, 0, 0, 0.6);
|
|
8475
8574
|
}
|
|
@@ -8611,6 +8710,26 @@ button.ow-setting-icon:hover {
|
|
|
8611
8710
|
.ow-menu {
|
|
8612
8711
|
padding: 16px;
|
|
8613
8712
|
}
|
|
8713
|
+
.ow-menu-title {
|
|
8714
|
+
padding-top: 8px;
|
|
8715
|
+
}
|
|
8716
|
+
}
|
|
8717
|
+
|
|
8718
|
+
/* The narrowest phones: rows wrap instead of pushing the menu sideways. */
|
|
8719
|
+
@media (max-width: 360px) {
|
|
8720
|
+
.ow-menu {
|
|
8721
|
+
padding: 12px;
|
|
8722
|
+
overflow-x: hidden;
|
|
8723
|
+
}
|
|
8724
|
+
.ow-menu-foot {
|
|
8725
|
+
flex-wrap: wrap;
|
|
8726
|
+
}
|
|
8727
|
+
.ow-menu-foot .ow-btn {
|
|
8728
|
+
flex: 1 1 100%;
|
|
8729
|
+
}
|
|
8730
|
+
.ow-section-head {
|
|
8731
|
+
flex-wrap: wrap;
|
|
8732
|
+
}
|
|
8614
8733
|
}
|
|
8615
8734
|
|
|
8616
8735
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -8654,7 +8773,7 @@ button.ow-setting-icon:hover {
|
|
|
8654
8773
|
place-items: center;
|
|
8655
8774
|
width: 44px;
|
|
8656
8775
|
height: 44px;
|
|
8657
|
-
border-radius:
|
|
8776
|
+
border-radius: var(--radius-art);
|
|
8658
8777
|
object-fit: cover;
|
|
8659
8778
|
color: #fff;
|
|
8660
8779
|
font-size: 18px;
|
|
@@ -8996,7 +9115,7 @@ a.pager-btn:hover {
|
|
|
8996
9115
|
place-items: center;
|
|
8997
9116
|
width: 44px;
|
|
8998
9117
|
height: 44px;
|
|
8999
|
-
border-radius:
|
|
9118
|
+
border-radius: var(--radius-art);
|
|
9000
9119
|
object-fit: cover;
|
|
9001
9120
|
color: #fff;
|
|
9002
9121
|
font-size: 18px;
|
|
@@ -10437,6 +10556,38 @@ body.play .ow-card {
|
|
|
10437
10556
|
border-radius: 999px;
|
|
10438
10557
|
}
|
|
10439
10558
|
|
|
10559
|
+
/* Enter presses the button: one small mark, for keyboards. */
|
|
10560
|
+
.ow-lobby-keys .ow-lobby-action:not(:disabled)::after {
|
|
10561
|
+
content: '\\21B5' / '';
|
|
10562
|
+
margin-left: 8px;
|
|
10563
|
+
font-size: 0.85em;
|
|
10564
|
+
font-weight: 400;
|
|
10565
|
+
opacity: 0.65;
|
|
10566
|
+
}
|
|
10567
|
+
|
|
10568
|
+
/* A press goes through to the target under the button, inside the game's frame (shell/lobby.ts, link): it is then the player's gesture
|
|
10569
|
+
there. The strip goes through whole, and the card's own parts stay on this page. */
|
|
10570
|
+
.ow-lobby.ow-lobby-through,
|
|
10571
|
+
.ow-lobby-through > .ow-lobby-card,
|
|
10572
|
+
.ow-lobby-through > .ow-lobby-bar,
|
|
10573
|
+
.ow-lobby-through .ow-lobby-actions,
|
|
10574
|
+
.ow-lobby-through .ow-lobby-action {
|
|
10575
|
+
pointer-events: none;
|
|
10576
|
+
}
|
|
10577
|
+
|
|
10578
|
+
.ow-lobby-through > .ow-lobby-card > :not(.ow-lobby-actions),
|
|
10579
|
+
.ow-lobby-through .ow-lobby-invite {
|
|
10580
|
+
pointer-events: auto;
|
|
10581
|
+
}
|
|
10582
|
+
|
|
10583
|
+
.ow-lobby-hover.ow-btn {
|
|
10584
|
+
background: rgba(255, 255, 255, 0.16);
|
|
10585
|
+
}
|
|
10586
|
+
|
|
10587
|
+
.ow-lobby-hover.ow-btn-primary {
|
|
10588
|
+
background: var(--accent-fill-hover);
|
|
10589
|
+
}
|
|
10590
|
+
|
|
10440
10591
|
/* 3, 2, 1. */
|
|
10441
10592
|
.ow-lobby-countdown {
|
|
10442
10593
|
position: fixed;
|
|
@@ -10846,6 +10997,32 @@ body.ow-calm .ow-fold-caret {
|
|
|
10846
10997
|
overflow-wrap: anywhere;
|
|
10847
10998
|
}
|
|
10848
10999
|
|
|
11000
|
+
.upload-kinds dl {
|
|
11001
|
+
margin: 0;
|
|
11002
|
+
font-size: 14px;
|
|
11003
|
+
}
|
|
11004
|
+
|
|
11005
|
+
.upload-kinds dl > div {
|
|
11006
|
+
display: grid;
|
|
11007
|
+
grid-template-columns: 7.5em minmax(0, 1fr);
|
|
11008
|
+
gap: 12px;
|
|
11009
|
+
padding: 7px 0;
|
|
11010
|
+
border-top: 1px solid var(--line);
|
|
11011
|
+
}
|
|
11012
|
+
|
|
11013
|
+
.upload-kinds dt {
|
|
11014
|
+
font-weight: 600;
|
|
11015
|
+
}
|
|
11016
|
+
|
|
11017
|
+
.upload-kinds dd {
|
|
11018
|
+
margin: 0;
|
|
11019
|
+
color: var(--muted);
|
|
11020
|
+
}
|
|
11021
|
+
|
|
11022
|
+
.upload-kinds .fine {
|
|
11023
|
+
margin: 7px 0 12px;
|
|
11024
|
+
}
|
|
11025
|
+
|
|
10849
11026
|
.upload-form .flash {
|
|
10850
11027
|
margin: 0;
|
|
10851
11028
|
}
|
|
@@ -11363,53 +11540,164 @@ body.ow-calm .ow-fold-caret {
|
|
|
11363
11540
|
|
|
11364
11541
|
/* ------------------------------------------------------------ Create: describe a game, your games, Developers (create.ts) */
|
|
11365
11542
|
|
|
11366
|
-
/*
|
|
11367
|
-
.
|
|
11368
|
-
|
|
11369
|
-
|
|
11543
|
+
/*
|
|
11544
|
+
* Create is a workbench in Edit's shape: the game's screen with the box under it (what Edit opens to), beside the games to start from.
|
|
11545
|
+
* The screen stays 16:9 and shrinks with a short window, so the box never falls below the fold; the rail is as tall as the screen and
|
|
11546
|
+
* box, and scrolls. On phones the rail is a strip under the box.
|
|
11547
|
+
*/
|
|
11548
|
+
.make.page {
|
|
11549
|
+
padding-top: clamp(14px, 2.4vh, 28px);
|
|
11550
|
+
}
|
|
11551
|
+
|
|
11552
|
+
.make-head {
|
|
11553
|
+
display: flex;
|
|
11554
|
+
flex-wrap: wrap;
|
|
11370
11555
|
align-items: center;
|
|
11371
|
-
|
|
11372
|
-
|
|
11556
|
+
justify-content: space-between;
|
|
11557
|
+
gap: 10px 24px;
|
|
11558
|
+
margin-bottom: clamp(14px, 2vh, 22px);
|
|
11373
11559
|
}
|
|
11374
11560
|
|
|
11375
|
-
.
|
|
11376
|
-
margin: 0
|
|
11377
|
-
font-size: clamp(
|
|
11561
|
+
.page .make-head h1 {
|
|
11562
|
+
margin: 0;
|
|
11563
|
+
font-size: clamp(30px, 3.9vw, 56px);
|
|
11378
11564
|
font-weight: 700;
|
|
11379
|
-
line-height:
|
|
11565
|
+
line-height: 1;
|
|
11380
11566
|
letter-spacing: -0.045em;
|
|
11381
11567
|
}
|
|
11382
11568
|
|
|
11383
|
-
.
|
|
11384
|
-
|
|
11569
|
+
.make-head h1 span {
|
|
11570
|
+
margin-left: 0.24em;
|
|
11385
11571
|
color: var(--accent-text);
|
|
11386
11572
|
}
|
|
11387
11573
|
|
|
11388
|
-
.
|
|
11574
|
+
.make-bench {
|
|
11575
|
+
display: grid;
|
|
11576
|
+
grid-template-columns: minmax(0, min(62%, max(520px, calc((100svh - 330px) * 16 / 9)))) minmax(0, 1fr);
|
|
11577
|
+
gap: clamp(16px, 1.8vw, 26px);
|
|
11578
|
+
}
|
|
11579
|
+
|
|
11580
|
+
.make-screen {
|
|
11581
|
+
position: relative;
|
|
11389
11582
|
overflow: hidden;
|
|
11390
11583
|
aspect-ratio: 16 / 9;
|
|
11391
|
-
border
|
|
11392
|
-
|
|
11393
|
-
|
|
11584
|
+
border: 1px solid var(--line);
|
|
11585
|
+
border-radius: var(--radius-art);
|
|
11586
|
+
background: var(--edit-screen);
|
|
11587
|
+
}
|
|
11588
|
+
|
|
11589
|
+
/* The new game's empty place, as in Edit's first frame. */
|
|
11590
|
+
.make-empty {
|
|
11591
|
+
position: absolute;
|
|
11592
|
+
inset: 0;
|
|
11593
|
+
display: flex;
|
|
11594
|
+
flex-direction: column;
|
|
11595
|
+
align-items: center;
|
|
11596
|
+
justify-content: center;
|
|
11597
|
+
gap: 16px;
|
|
11598
|
+
color: var(--muted);
|
|
11599
|
+
}
|
|
11600
|
+
|
|
11601
|
+
.make-slot {
|
|
11602
|
+
display: grid;
|
|
11603
|
+
place-items: center;
|
|
11604
|
+
width: 84px;
|
|
11605
|
+
height: 84px;
|
|
11606
|
+
box-sizing: border-box;
|
|
11607
|
+
border: 2px dashed var(--edit-line-strong);
|
|
11608
|
+
border-radius: var(--radius-art);
|
|
11609
|
+
}
|
|
11610
|
+
|
|
11611
|
+
.make-slot svg {
|
|
11612
|
+
width: 30px;
|
|
11613
|
+
height: 30px;
|
|
11614
|
+
}
|
|
11615
|
+
|
|
11616
|
+
.make-empty strong {
|
|
11617
|
+
font-size: clamp(18px, 2vw, 26px);
|
|
11618
|
+
font-weight: 650;
|
|
11619
|
+
letter-spacing: -0.02em;
|
|
11394
11620
|
}
|
|
11395
11621
|
|
|
11396
|
-
.
|
|
11397
|
-
|
|
11622
|
+
.make-shot {
|
|
11623
|
+
position: absolute;
|
|
11624
|
+
inset: 0;
|
|
11398
11625
|
display: block;
|
|
11399
11626
|
width: 100%;
|
|
11400
11627
|
height: 100%;
|
|
11401
11628
|
object-fit: cover;
|
|
11402
11629
|
}
|
|
11403
11630
|
|
|
11404
|
-
|
|
11405
|
-
|
|
11406
|
-
|
|
11407
|
-
|
|
11631
|
+
.make-shot[hidden],
|
|
11632
|
+
.make-picked[hidden] {
|
|
11633
|
+
display: none;
|
|
11634
|
+
}
|
|
11635
|
+
|
|
11636
|
+
.make-picked {
|
|
11637
|
+
position: absolute;
|
|
11638
|
+
inset: auto 0 0;
|
|
11639
|
+
display: flex;
|
|
11640
|
+
align-items: center;
|
|
11641
|
+
gap: 12px;
|
|
11642
|
+
margin: 0;
|
|
11643
|
+
padding: 56px 18px 16px;
|
|
11644
|
+
background: linear-gradient(transparent, rgba(0, 0, 0, 0.82));
|
|
11645
|
+
color: #fff;
|
|
11646
|
+
}
|
|
11647
|
+
|
|
11648
|
+
.make-picked strong {
|
|
11649
|
+
overflow: hidden;
|
|
11650
|
+
min-width: 0;
|
|
11651
|
+
font-size: clamp(18px, 2.1vw, 30px);
|
|
11652
|
+
font-weight: 700;
|
|
11653
|
+
letter-spacing: -0.03em;
|
|
11654
|
+
text-overflow: ellipsis;
|
|
11655
|
+
white-space: nowrap;
|
|
11656
|
+
}
|
|
11657
|
+
|
|
11658
|
+
.make-remix-mark {
|
|
11659
|
+
display: inline-flex;
|
|
11660
|
+
flex: none;
|
|
11661
|
+
align-items: center;
|
|
11662
|
+
gap: 5px;
|
|
11663
|
+
padding: 4px 10px 4px 7px;
|
|
11664
|
+
border-radius: 999px;
|
|
11665
|
+
background: var(--play-fill);
|
|
11666
|
+
color: var(--play-ink);
|
|
11667
|
+
font-size: 13px;
|
|
11668
|
+
font-weight: 700;
|
|
11669
|
+
}
|
|
11670
|
+
|
|
11671
|
+
.make-remix-mark svg {
|
|
11672
|
+
width: 15px;
|
|
11673
|
+
height: 15px;
|
|
11674
|
+
}
|
|
11675
|
+
|
|
11676
|
+
.make-picked .btn {
|
|
11677
|
+
flex: none;
|
|
11678
|
+
margin-left: auto;
|
|
11679
|
+
border-color: rgba(255, 255, 255, 0.34);
|
|
11680
|
+
background: rgba(0, 0, 0, 0.35);
|
|
11681
|
+
color: #fff;
|
|
11408
11682
|
}
|
|
11409
11683
|
|
|
11410
|
-
|
|
11684
|
+
.make-picked .btn:hover {
|
|
11685
|
+
background: rgba(0, 0, 0, 0.6);
|
|
11686
|
+
}
|
|
11687
|
+
|
|
11688
|
+
.make-problem {
|
|
11689
|
+
margin: 10px 0 0;
|
|
11690
|
+
}
|
|
11691
|
+
|
|
11692
|
+
/* The box: under the game, the one thing to do here. */
|
|
11411
11693
|
.create-box {
|
|
11694
|
+
display: grid;
|
|
11695
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
11696
|
+
align-items: end;
|
|
11697
|
+
gap: 8px;
|
|
11412
11698
|
width: 100%;
|
|
11699
|
+
margin-top: 10px;
|
|
11700
|
+
padding: 8px;
|
|
11413
11701
|
border: 1px solid var(--line);
|
|
11414
11702
|
border-radius: var(--radius-widget);
|
|
11415
11703
|
background: var(--bg-raised);
|
|
@@ -11426,14 +11714,13 @@ body.ow-calm .ow-fold-caret {
|
|
|
11426
11714
|
.create-box textarea {
|
|
11427
11715
|
display: block;
|
|
11428
11716
|
width: 100%;
|
|
11429
|
-
min-height:
|
|
11430
|
-
max-height:
|
|
11431
|
-
padding:
|
|
11717
|
+
min-height: 56px;
|
|
11718
|
+
max-height: 24vh;
|
|
11719
|
+
padding: 8px 10px;
|
|
11432
11720
|
border: 0;
|
|
11433
|
-
border-radius: var(--radius-widget);
|
|
11434
11721
|
background: none;
|
|
11435
11722
|
color: var(--text);
|
|
11436
|
-
font: 500 clamp(
|
|
11723
|
+
font: 500 clamp(16px, 1.3vw, 18px) / 1.4 var(--font);
|
|
11437
11724
|
resize: none;
|
|
11438
11725
|
}
|
|
11439
11726
|
|
|
@@ -11446,22 +11733,16 @@ body.ow-calm .ow-fold-caret {
|
|
|
11446
11733
|
opacity: 1;
|
|
11447
11734
|
}
|
|
11448
11735
|
|
|
11449
|
-
.create-box-foot {
|
|
11450
|
-
display: flex;
|
|
11451
|
-
justify-content: flex-end;
|
|
11452
|
-
padding: 0 14px 14px;
|
|
11453
|
-
}
|
|
11454
|
-
|
|
11455
11736
|
.btn.create-go {
|
|
11456
|
-
gap:
|
|
11457
|
-
min-width:
|
|
11458
|
-
min-height:
|
|
11459
|
-
padding: 0
|
|
11737
|
+
gap: 8px;
|
|
11738
|
+
min-width: 132px;
|
|
11739
|
+
min-height: 52px;
|
|
11740
|
+
padding: 0 20px;
|
|
11460
11741
|
border: 0;
|
|
11461
|
-
border-radius:
|
|
11742
|
+
border-radius: 10px;
|
|
11462
11743
|
background: var(--play-fill);
|
|
11463
11744
|
color: var(--play-ink);
|
|
11464
|
-
font-size:
|
|
11745
|
+
font-size: 17px;
|
|
11465
11746
|
font-weight: 700;
|
|
11466
11747
|
}
|
|
11467
11748
|
|
|
@@ -11485,25 +11766,175 @@ body.ow-calm .ow-fold-caret {
|
|
|
11485
11766
|
flex-wrap: wrap;
|
|
11486
11767
|
align-items: center;
|
|
11487
11768
|
gap: 12px;
|
|
11488
|
-
margin:
|
|
11769
|
+
margin: 0;
|
|
11489
11770
|
color: var(--muted);
|
|
11490
11771
|
font-size: 14px;
|
|
11491
11772
|
}
|
|
11492
11773
|
|
|
11493
|
-
/*
|
|
11494
|
-
.
|
|
11495
|
-
|
|
11496
|
-
|
|
11497
|
-
|
|
11498
|
-
|
|
11499
|
-
width: 100%;
|
|
11500
|
-
max-width: var(--page);
|
|
11501
|
-
margin: 0 auto;
|
|
11502
|
-
padding: 0 var(--gutter) 56px;
|
|
11774
|
+
/* The games to start from: as tall as the screen and box, however many there are. */
|
|
11775
|
+
.make-rail {
|
|
11776
|
+
display: flex;
|
|
11777
|
+
flex-direction: column;
|
|
11778
|
+
min-width: 0;
|
|
11779
|
+
contain: size;
|
|
11503
11780
|
}
|
|
11504
11781
|
|
|
11505
|
-
.
|
|
11506
|
-
|
|
11782
|
+
.make-rail-head {
|
|
11783
|
+
display: flex;
|
|
11784
|
+
flex: none;
|
|
11785
|
+
align-items: center;
|
|
11786
|
+
justify-content: space-between;
|
|
11787
|
+
gap: 12px;
|
|
11788
|
+
margin-bottom: 12px;
|
|
11789
|
+
}
|
|
11790
|
+
|
|
11791
|
+
.make-rail-head h2 {
|
|
11792
|
+
flex: none;
|
|
11793
|
+
margin: 0;
|
|
11794
|
+
font-size: 18px;
|
|
11795
|
+
font-weight: 700;
|
|
11796
|
+
letter-spacing: -0.02em;
|
|
11797
|
+
}
|
|
11798
|
+
|
|
11799
|
+
.make-rail-head input {
|
|
11800
|
+
flex: 0 1 200px;
|
|
11801
|
+
min-width: 0;
|
|
11802
|
+
height: 34px;
|
|
11803
|
+
padding: 0 12px;
|
|
11804
|
+
border: 1px solid var(--line);
|
|
11805
|
+
border-radius: 999px;
|
|
11806
|
+
background: var(--bg-raised);
|
|
11807
|
+
color: var(--text);
|
|
11808
|
+
font: 500 14px var(--font);
|
|
11809
|
+
}
|
|
11810
|
+
|
|
11811
|
+
.make-rail-head input[hidden] {
|
|
11812
|
+
display: none;
|
|
11813
|
+
}
|
|
11814
|
+
|
|
11815
|
+
.make-tiles {
|
|
11816
|
+
display: grid;
|
|
11817
|
+
flex: 1;
|
|
11818
|
+
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
|
11819
|
+
align-content: start;
|
|
11820
|
+
gap: 14px 12px;
|
|
11821
|
+
min-height: 0;
|
|
11822
|
+
margin: 0;
|
|
11823
|
+
padding: 3px 6px 3px 3px;
|
|
11824
|
+
overflow-y: auto;
|
|
11825
|
+
list-style: none;
|
|
11826
|
+
scrollbar-width: thin;
|
|
11827
|
+
}
|
|
11828
|
+
|
|
11829
|
+
.make-tiles li[hidden] {
|
|
11830
|
+
display: none;
|
|
11831
|
+
}
|
|
11832
|
+
|
|
11833
|
+
.make-tile {
|
|
11834
|
+
display: block;
|
|
11835
|
+
color: var(--muted);
|
|
11836
|
+
font-size: 13px;
|
|
11837
|
+
font-weight: 600;
|
|
11838
|
+
text-decoration: none;
|
|
11839
|
+
}
|
|
11840
|
+
|
|
11841
|
+
.make-tile > span:last-child {
|
|
11842
|
+
display: block;
|
|
11843
|
+
overflow: hidden;
|
|
11844
|
+
margin-top: 6px;
|
|
11845
|
+
text-overflow: ellipsis;
|
|
11846
|
+
white-space: nowrap;
|
|
11847
|
+
}
|
|
11848
|
+
|
|
11849
|
+
.make-tile-art {
|
|
11850
|
+
display: grid;
|
|
11851
|
+
place-items: center;
|
|
11852
|
+
overflow: hidden;
|
|
11853
|
+
aspect-ratio: 16 / 9;
|
|
11854
|
+
border-radius: var(--radius-art);
|
|
11855
|
+
background: var(--edit-screen);
|
|
11856
|
+
transition: box-shadow 0.12s ease;
|
|
11857
|
+
}
|
|
11858
|
+
|
|
11859
|
+
.make-tile-art img {
|
|
11860
|
+
display: block;
|
|
11861
|
+
width: 100%;
|
|
11862
|
+
height: 100%;
|
|
11863
|
+
object-fit: cover;
|
|
11864
|
+
}
|
|
11865
|
+
|
|
11866
|
+
.make-tile-blank {
|
|
11867
|
+
box-sizing: border-box;
|
|
11868
|
+
border: 1.5px dashed var(--edit-line-strong);
|
|
11869
|
+
color: var(--muted);
|
|
11870
|
+
}
|
|
11871
|
+
|
|
11872
|
+
.make-tile-blank svg {
|
|
11873
|
+
width: 26px;
|
|
11874
|
+
height: 26px;
|
|
11875
|
+
}
|
|
11876
|
+
|
|
11877
|
+
.make-tile:hover {
|
|
11878
|
+
color: var(--text);
|
|
11879
|
+
}
|
|
11880
|
+
|
|
11881
|
+
.make-tile:hover .make-tile-art {
|
|
11882
|
+
box-shadow: 0 0 0 2px var(--text);
|
|
11883
|
+
}
|
|
11884
|
+
|
|
11885
|
+
.make-tile[aria-current] {
|
|
11886
|
+
color: var(--text);
|
|
11887
|
+
}
|
|
11888
|
+
|
|
11889
|
+
.make-tile[aria-current] .make-tile-art {
|
|
11890
|
+
box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent);
|
|
11891
|
+
}
|
|
11892
|
+
|
|
11893
|
+
@media (max-width: 900px) {
|
|
11894
|
+
.make-head h1 span {
|
|
11895
|
+
display: block;
|
|
11896
|
+
margin: 2px 0 0;
|
|
11897
|
+
}
|
|
11898
|
+
|
|
11899
|
+
.make-bench {
|
|
11900
|
+
grid-template-columns: minmax(0, 1fr);
|
|
11901
|
+
}
|
|
11902
|
+
|
|
11903
|
+
.make-rail {
|
|
11904
|
+
contain: none;
|
|
11905
|
+
}
|
|
11906
|
+
|
|
11907
|
+
.make-tiles {
|
|
11908
|
+
display: flex;
|
|
11909
|
+
gap: 10px;
|
|
11910
|
+
margin: 0 calc(var(--gutter) * -1);
|
|
11911
|
+
padding: 3px var(--gutter) 8px;
|
|
11912
|
+
overflow: auto hidden;
|
|
11913
|
+
}
|
|
11914
|
+
|
|
11915
|
+
.make-tiles li {
|
|
11916
|
+
flex: 0 0 148px;
|
|
11917
|
+
}
|
|
11918
|
+
|
|
11919
|
+
.btn.create-go {
|
|
11920
|
+
min-width: 0;
|
|
11921
|
+
}
|
|
11922
|
+
}
|
|
11923
|
+
|
|
11924
|
+
/* Signed in: the creator's games, under the box. */
|
|
11925
|
+
.create-page .create-games {
|
|
11926
|
+
margin: 0 0 clamp(40px, 5vw, 64px);
|
|
11927
|
+
}
|
|
11928
|
+
|
|
11929
|
+
.create-home {
|
|
11930
|
+
width: 100%;
|
|
11931
|
+
max-width: var(--page);
|
|
11932
|
+
margin: 0 auto;
|
|
11933
|
+
padding: 0 var(--gutter) 56px;
|
|
11934
|
+
}
|
|
11935
|
+
|
|
11936
|
+
.create-home > .section {
|
|
11937
|
+
margin-bottom: clamp(72px, 9vw, 128px);
|
|
11507
11938
|
}
|
|
11508
11939
|
|
|
11509
11940
|
.create-home .section-head {
|
|
@@ -11605,7 +12036,7 @@ html.is-launching {
|
|
|
11605
12036
|
height: 84px;
|
|
11606
12037
|
box-sizing: border-box;
|
|
11607
12038
|
border: 2px dashed var(--edit-line-strong);
|
|
11608
|
-
border-radius:
|
|
12039
|
+
border-radius: var(--radius-art);
|
|
11609
12040
|
color: var(--muted);
|
|
11610
12041
|
}
|
|
11611
12042
|
|
|
@@ -11616,6 +12047,29 @@ html.is-launching {
|
|
|
11616
12047
|
letter-spacing: -0.02em;
|
|
11617
12048
|
}
|
|
11618
12049
|
|
|
12050
|
+
/* A remix: the game itself, and the word for what's happening over it. */
|
|
12051
|
+
.create-launch-stage.is-remix {
|
|
12052
|
+
position: relative;
|
|
12053
|
+
overflow: hidden;
|
|
12054
|
+
}
|
|
12055
|
+
|
|
12056
|
+
.create-launch-stage.is-remix img {
|
|
12057
|
+
position: absolute;
|
|
12058
|
+
inset: 0;
|
|
12059
|
+
width: 100%;
|
|
12060
|
+
height: 100%;
|
|
12061
|
+
object-fit: cover;
|
|
12062
|
+
opacity: 0.42;
|
|
12063
|
+
}
|
|
12064
|
+
|
|
12065
|
+
.create-launch-stage.is-remix strong {
|
|
12066
|
+
position: relative;
|
|
12067
|
+
color: #fff;
|
|
12068
|
+
font-size: clamp(40px, 7vw, 96px);
|
|
12069
|
+
font-weight: 800;
|
|
12070
|
+
letter-spacing: -0.045em;
|
|
12071
|
+
}
|
|
12072
|
+
|
|
11619
12073
|
/* The box under it, where the description lands. */
|
|
11620
12074
|
.create-launch-ask {
|
|
11621
12075
|
display: flex;
|
|
@@ -11890,6 +12344,30 @@ html.is-launching {
|
|
|
11890
12344
|
height: 30px;
|
|
11891
12345
|
}
|
|
11892
12346
|
|
|
12347
|
+
/* Remix isn't an upload: its own row, with the dashed edge of the place a game is about to go. */
|
|
12348
|
+
.up-choices:has(.up-choice-remix) {
|
|
12349
|
+
grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr));
|
|
12350
|
+
}
|
|
12351
|
+
|
|
12352
|
+
.up-choice-remix {
|
|
12353
|
+
grid-column: 1 / -1;
|
|
12354
|
+
}
|
|
12355
|
+
|
|
12356
|
+
.up-choice-remix .up-choice {
|
|
12357
|
+
border: 1.5px dashed var(--accent);
|
|
12358
|
+
}
|
|
12359
|
+
|
|
12360
|
+
.up-choice-remix .up-choice:hover {
|
|
12361
|
+
border-style: solid;
|
|
12362
|
+
border-color: var(--accent);
|
|
12363
|
+
background: var(--accent-soft);
|
|
12364
|
+
}
|
|
12365
|
+
|
|
12366
|
+
.up-choice-remix .up-choice > svg:first-child,
|
|
12367
|
+
.up-choice-remix .up-chevron {
|
|
12368
|
+
color: var(--accent-text);
|
|
12369
|
+
}
|
|
12370
|
+
|
|
11893
12371
|
.up-choice-text {
|
|
11894
12372
|
display: flex;
|
|
11895
12373
|
flex-direction: column;
|
|
@@ -12023,14 +12501,12 @@ html.is-launching {
|
|
|
12023
12501
|
margin: 0 0 8px;
|
|
12024
12502
|
}
|
|
12025
12503
|
|
|
12026
|
-
/* Upload's helper, bottom right: a
|
|
12027
|
-
padding and the footer's 56px margin, taken back). It hops in, then idles (its SVG breathes, blinks and looks around). */
|
|
12504
|
+
/* Upload's helper, bottom right: a card that sits just above the footer's line. */
|
|
12028
12505
|
.up-buddy {
|
|
12029
12506
|
display: flex;
|
|
12030
12507
|
align-items: flex-end;
|
|
12031
12508
|
justify-content: flex-end;
|
|
12032
|
-
|
|
12033
|
-
margin: 40px 0 -80px;
|
|
12509
|
+
margin: 40px 0 -16px;
|
|
12034
12510
|
pointer-events: none;
|
|
12035
12511
|
}
|
|
12036
12512
|
|
|
@@ -12041,7 +12517,6 @@ html.is-launching {
|
|
|
12041
12517
|
.up-buddy-bubble {
|
|
12042
12518
|
position: relative;
|
|
12043
12519
|
width: min(380px, 100%);
|
|
12044
|
-
margin-bottom: 64px;
|
|
12045
12520
|
padding: 14px 16px;
|
|
12046
12521
|
border: 1px solid var(--line);
|
|
12047
12522
|
border-radius: 16px;
|
|
@@ -12052,20 +12527,6 @@ html.is-launching {
|
|
|
12052
12527
|
animation: up-bubble 0.32s 0.45s cubic-bezier(0.2, 1.4, 0.4, 1) both;
|
|
12053
12528
|
}
|
|
12054
12529
|
|
|
12055
|
-
/* Its tail, pointing at the character's head. */
|
|
12056
|
-
.up-buddy-bubble::after {
|
|
12057
|
-
position: absolute;
|
|
12058
|
-
right: -7px;
|
|
12059
|
-
bottom: 18px;
|
|
12060
|
-
width: 12px;
|
|
12061
|
-
height: 12px;
|
|
12062
|
-
border-top: 1px solid var(--line);
|
|
12063
|
-
border-right: 1px solid var(--line);
|
|
12064
|
-
background: var(--bg-raised);
|
|
12065
|
-
transform: rotate(45deg);
|
|
12066
|
-
content: '';
|
|
12067
|
-
}
|
|
12068
|
-
|
|
12069
12530
|
.up-buddy-head {
|
|
12070
12531
|
margin: 0 0 8px;
|
|
12071
12532
|
font-weight: 700;
|
|
@@ -12124,20 +12585,6 @@ html.is-launching {
|
|
|
12124
12585
|
height: 14px;
|
|
12125
12586
|
}
|
|
12126
12587
|
|
|
12127
|
-
.up-buddy-face {
|
|
12128
|
-
flex: none;
|
|
12129
|
-
width: 64px;
|
|
12130
|
-
height: 112px;
|
|
12131
|
-
animation: up-hop 0.5s cubic-bezier(0.3, 1.5, 0.5, 1) both;
|
|
12132
|
-
}
|
|
12133
|
-
|
|
12134
|
-
@keyframes up-hop {
|
|
12135
|
-
from {
|
|
12136
|
-
opacity: 0;
|
|
12137
|
-
transform: translateY(24px);
|
|
12138
|
-
}
|
|
12139
|
-
}
|
|
12140
|
-
|
|
12141
12588
|
@keyframes up-bubble {
|
|
12142
12589
|
from {
|
|
12143
12590
|
opacity: 0;
|
|
@@ -12146,8 +12593,7 @@ html.is-launching {
|
|
|
12146
12593
|
}
|
|
12147
12594
|
|
|
12148
12595
|
@media (prefers-reduced-motion: reduce) {
|
|
12149
|
-
.up-buddy-bubble
|
|
12150
|
-
.up-buddy-face {
|
|
12596
|
+
.up-buddy-bubble {
|
|
12151
12597
|
animation: none;
|
|
12152
12598
|
}
|
|
12153
12599
|
}
|
|
@@ -12871,7 +13317,7 @@ body:not(:has(.tabbar)) .toast {
|
|
|
12871
13317
|
.cover-wall-tile {
|
|
12872
13318
|
overflow: hidden;
|
|
12873
13319
|
aspect-ratio: 16 / 9;
|
|
12874
|
-
border-radius:
|
|
13320
|
+
border-radius: var(--radius-art);
|
|
12875
13321
|
background: rgba(255, 255, 255, 0.06);
|
|
12876
13322
|
}
|
|
12877
13323
|
|
|
@@ -13470,7 +13916,7 @@ body.share-frame {
|
|
|
13470
13916
|
place-items: center;
|
|
13471
13917
|
aspect-ratio: 16 / 9;
|
|
13472
13918
|
overflow: hidden;
|
|
13473
|
-
border-radius:
|
|
13919
|
+
border-radius: var(--radius-art);
|
|
13474
13920
|
background: #000;
|
|
13475
13921
|
}
|
|
13476
13922
|
|
|
@@ -13530,7 +13976,7 @@ body.share-frame {
|
|
|
13530
13976
|
position: relative;
|
|
13531
13977
|
aspect-ratio: 16 / 9;
|
|
13532
13978
|
overflow: hidden;
|
|
13533
|
-
border-radius:
|
|
13979
|
+
border-radius: var(--radius-art);
|
|
13534
13980
|
background: #000;
|
|
13535
13981
|
}
|
|
13536
13982
|
|
|
@@ -13572,35 +14018,6 @@ body.share-frame {
|
|
|
13572
14018
|
}
|
|
13573
14019
|
}
|
|
13574
14020
|
|
|
13575
|
-
/* The play page's menu: Share (the server's invite link, on X or a phone's share sheet), and for guests one quiet line. */
|
|
13576
|
-
.ow-share {
|
|
13577
|
-
display: flex;
|
|
13578
|
-
gap: 8px;
|
|
13579
|
-
padding: 12px 0;
|
|
13580
|
-
border-top: 1px solid var(--line);
|
|
13581
|
-
}
|
|
13582
|
-
|
|
13583
|
-
.ow-share .ow-pill {
|
|
13584
|
-
text-decoration: none;
|
|
13585
|
-
}
|
|
13586
|
-
|
|
13587
|
-
.ow-made {
|
|
13588
|
-
margin: 0;
|
|
13589
|
-
padding: 0 0 12px;
|
|
13590
|
-
color: var(--muted);
|
|
13591
|
-
font-size: 12px;
|
|
13592
|
-
}
|
|
13593
|
-
|
|
13594
|
-
.ow-made a {
|
|
13595
|
-
color: inherit;
|
|
13596
|
-
font-weight: 600;
|
|
13597
|
-
text-decoration: none;
|
|
13598
|
-
}
|
|
13599
|
-
|
|
13600
|
-
.ow-made a:hover {
|
|
13601
|
-
color: var(--text);
|
|
13602
|
-
}
|
|
13603
|
-
|
|
13604
14021
|
/* A clip frame records the game alone: the platform's corner buttons and chat stay out of the creator's view. */
|
|
13605
14022
|
.ow-clip-frame .ow-hud,
|
|
13606
14023
|
.ow-clip-frame .ow-stats {
|
|
@@ -13721,7 +14138,7 @@ body.share-frame {
|
|
|
13721
14138
|
display: block;
|
|
13722
14139
|
width: 100%;
|
|
13723
14140
|
border: 0;
|
|
13724
|
-
border-radius:
|
|
14141
|
+
border-radius: var(--radius-art);
|
|
13725
14142
|
background: #000;
|
|
13726
14143
|
}
|
|
13727
14144
|
|
|
@@ -13767,7 +14184,7 @@ body.share-frame {
|
|
|
13767
14184
|
.file-page img {
|
|
13768
14185
|
max-width: 100%;
|
|
13769
14186
|
max-height: 82vh;
|
|
13770
|
-
border-radius:
|
|
14187
|
+
border-radius: var(--radius-art);
|
|
13771
14188
|
}
|
|
13772
14189
|
|
|
13773
14190
|
.file-pager {
|
|
@@ -13777,7 +14194,531 @@ body.share-frame {
|
|
|
13777
14194
|
gap: 16px;
|
|
13778
14195
|
margin-top: 12px;
|
|
13779
14196
|
}
|
|
13780
|
-
|
|
14197
|
+
|
|
14198
|
+
|
|
14199
|
+
/*
|
|
14200
|
+
* A game's About (protocol about.ts): text straight on the page and the creator's own pictures, the same way for every game, as on
|
|
14201
|
+
* Steam or itch. The art does the designing: nothing here adds a box, a colour or a shadow.
|
|
14202
|
+
*/
|
|
14203
|
+
.game-about {
|
|
14204
|
+
scroll-margin-top: calc(var(--bar-h) + 16px);
|
|
14205
|
+
}
|
|
14206
|
+
|
|
14207
|
+
.game-about-text {
|
|
14208
|
+
max-width: 72ch;
|
|
14209
|
+
white-space: pre-line;
|
|
14210
|
+
}
|
|
14211
|
+
|
|
14212
|
+
.game-about-text + .game-about-more {
|
|
14213
|
+
margin-top: 20px;
|
|
14214
|
+
}
|
|
14215
|
+
|
|
14216
|
+
.ab {
|
|
14217
|
+
display: flow-root;
|
|
14218
|
+
color: var(--text);
|
|
14219
|
+
font-size: 15px;
|
|
14220
|
+
line-height: 1.6;
|
|
14221
|
+
overflow-wrap: anywhere;
|
|
14222
|
+
}
|
|
14223
|
+
|
|
14224
|
+
.ab-fig,
|
|
14225
|
+
.ab-quote {
|
|
14226
|
+
margin: 0;
|
|
14227
|
+
}
|
|
14228
|
+
|
|
14229
|
+
.ab > * + *,
|
|
14230
|
+
.ab-column > * + *,
|
|
14231
|
+
.ab-fold-body > * + *,
|
|
14232
|
+
.ab-quote > * + * {
|
|
14233
|
+
margin-top: 16px;
|
|
14234
|
+
}
|
|
14235
|
+
|
|
14236
|
+
:is(.ab, .ab-column, .ab-fold-body) > * + .ab-fig,
|
|
14237
|
+
:is(.ab, .ab-column, .ab-fold-body) > .ab-fig + * {
|
|
14238
|
+
margin-top: 24px;
|
|
14239
|
+
}
|
|
14240
|
+
|
|
14241
|
+
.ab p {
|
|
14242
|
+
margin: 0;
|
|
14243
|
+
font-size: inherit;
|
|
14244
|
+
line-height: inherit;
|
|
14245
|
+
white-space: normal;
|
|
14246
|
+
}
|
|
14247
|
+
|
|
14248
|
+
/* Pictures fill the column, like the gallery above them; lines of text stop where they're still easy to read. */
|
|
14249
|
+
.ab :is(p, ul, ol, figcaption),
|
|
14250
|
+
.ab-quote {
|
|
14251
|
+
max-width: 760px;
|
|
14252
|
+
}
|
|
14253
|
+
|
|
14254
|
+
.ab h3,
|
|
14255
|
+
.page .ab h3 {
|
|
14256
|
+
margin: 32px 0 0;
|
|
14257
|
+
color: var(--text);
|
|
14258
|
+
font-size: 17px;
|
|
14259
|
+
font-weight: 700;
|
|
14260
|
+
line-height: 1.3;
|
|
14261
|
+
letter-spacing: 0;
|
|
14262
|
+
}
|
|
14263
|
+
|
|
14264
|
+
.ab h4,
|
|
14265
|
+
.page .ab h4 {
|
|
14266
|
+
margin: 20px 0 0;
|
|
14267
|
+
color: var(--text);
|
|
14268
|
+
font-size: 15px;
|
|
14269
|
+
font-weight: 700;
|
|
14270
|
+
line-height: 1.4;
|
|
14271
|
+
letter-spacing: 0;
|
|
14272
|
+
}
|
|
14273
|
+
|
|
14274
|
+
.ab :is(h3, h4):first-child,
|
|
14275
|
+
.page .ab :is(h3, h4):first-child {
|
|
14276
|
+
margin-top: 0;
|
|
14277
|
+
}
|
|
14278
|
+
|
|
14279
|
+
.ab :is(h3, h4) + * {
|
|
14280
|
+
margin-top: 6px;
|
|
14281
|
+
}
|
|
14282
|
+
|
|
14283
|
+
.ab a:not(.btn, .ab-youtube) {
|
|
14284
|
+
color: inherit;
|
|
14285
|
+
text-decoration: underline;
|
|
14286
|
+
text-underline-offset: 2px;
|
|
14287
|
+
}
|
|
14288
|
+
|
|
14289
|
+
.ab a:not(.btn, .ab-youtube):hover {
|
|
14290
|
+
text-decoration-thickness: 2px;
|
|
14291
|
+
}
|
|
14292
|
+
|
|
14293
|
+
.ab-spoiler {
|
|
14294
|
+
background: var(--muted);
|
|
14295
|
+
color: transparent;
|
|
14296
|
+
cursor: default;
|
|
14297
|
+
}
|
|
14298
|
+
|
|
14299
|
+
.ab-spoiler:hover,
|
|
14300
|
+
.ab-spoiler:focus {
|
|
14301
|
+
background: none;
|
|
14302
|
+
color: inherit;
|
|
14303
|
+
}
|
|
14304
|
+
|
|
14305
|
+
.ab ul,
|
|
14306
|
+
.ab ol {
|
|
14307
|
+
margin-bottom: 0;
|
|
14308
|
+
padding-left: 20px;
|
|
14309
|
+
}
|
|
14310
|
+
|
|
14311
|
+
.ab li + li {
|
|
14312
|
+
margin-top: 4px;
|
|
14313
|
+
}
|
|
14314
|
+
|
|
14315
|
+
.ab hr {
|
|
14316
|
+
height: 1px;
|
|
14317
|
+
margin: 24px 0;
|
|
14318
|
+
border: 0;
|
|
14319
|
+
background: var(--line);
|
|
14320
|
+
}
|
|
14321
|
+
|
|
14322
|
+
/* A picture shows at its own size, up to the column. */
|
|
14323
|
+
.ab-fig img {
|
|
14324
|
+
display: block;
|
|
14325
|
+
max-width: 100%;
|
|
14326
|
+
height: auto;
|
|
14327
|
+
border-radius: var(--radius-art);
|
|
14328
|
+
}
|
|
14329
|
+
|
|
14330
|
+
.ab-fig video,
|
|
14331
|
+
.ab-youtube {
|
|
14332
|
+
display: block;
|
|
14333
|
+
width: 100%;
|
|
14334
|
+
aspect-ratio: 16 / 9;
|
|
14335
|
+
border-radius: var(--radius-art);
|
|
14336
|
+
background: #000;
|
|
14337
|
+
}
|
|
14338
|
+
|
|
14339
|
+
.ab-fig figcaption {
|
|
14340
|
+
margin-top: 6px;
|
|
14341
|
+
color: var(--muted);
|
|
14342
|
+
font-size: 13px;
|
|
14343
|
+
line-height: 1.4;
|
|
14344
|
+
}
|
|
14345
|
+
|
|
14346
|
+
.ab-youtube {
|
|
14347
|
+
position: relative;
|
|
14348
|
+
overflow: hidden;
|
|
14349
|
+
color: #fff;
|
|
14350
|
+
}
|
|
14351
|
+
|
|
14352
|
+
.ab-fig .ab-youtube img {
|
|
14353
|
+
width: 100%;
|
|
14354
|
+
height: 100%;
|
|
14355
|
+
border-radius: 0;
|
|
14356
|
+
object-fit: cover;
|
|
14357
|
+
}
|
|
14358
|
+
|
|
14359
|
+
.ab-yt-play {
|
|
14360
|
+
position: absolute;
|
|
14361
|
+
inset: 0;
|
|
14362
|
+
display: grid;
|
|
14363
|
+
width: 56px;
|
|
14364
|
+
height: 56px;
|
|
14365
|
+
margin: auto;
|
|
14366
|
+
border-radius: 50%;
|
|
14367
|
+
background: rgba(0, 0, 0, 0.6);
|
|
14368
|
+
place-items: center;
|
|
14369
|
+
}
|
|
14370
|
+
|
|
14371
|
+
.ab-youtube:hover .ab-yt-play {
|
|
14372
|
+
background: #000;
|
|
14373
|
+
}
|
|
14374
|
+
|
|
14375
|
+
.ab-yt-mark {
|
|
14376
|
+
width: 28px;
|
|
14377
|
+
height: 28px;
|
|
14378
|
+
}
|
|
14379
|
+
|
|
14380
|
+
.ab-missing {
|
|
14381
|
+
padding: 18px;
|
|
14382
|
+
border: 1.5px dashed var(--line-strong);
|
|
14383
|
+
color: var(--muted);
|
|
14384
|
+
font-size: 13px;
|
|
14385
|
+
text-align: center;
|
|
14386
|
+
}
|
|
14387
|
+
|
|
14388
|
+
.ab-gallery {
|
|
14389
|
+
display: grid;
|
|
14390
|
+
gap: 8px;
|
|
14391
|
+
}
|
|
14392
|
+
|
|
14393
|
+
.ab-gallery-2 {
|
|
14394
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
14395
|
+
}
|
|
14396
|
+
|
|
14397
|
+
.ab-gallery-3 {
|
|
14398
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
14399
|
+
}
|
|
14400
|
+
|
|
14401
|
+
.ab-gallery .ab-fig img {
|
|
14402
|
+
width: 100%;
|
|
14403
|
+
aspect-ratio: 16 / 9;
|
|
14404
|
+
object-fit: cover;
|
|
14405
|
+
}
|
|
14406
|
+
|
|
14407
|
+
.ab-buttons {
|
|
14408
|
+
display: flex;
|
|
14409
|
+
flex-wrap: wrap;
|
|
14410
|
+
gap: 8px;
|
|
14411
|
+
}
|
|
14412
|
+
|
|
14413
|
+
.ab-columns {
|
|
14414
|
+
display: grid;
|
|
14415
|
+
gap: 24px;
|
|
14416
|
+
align-items: start;
|
|
14417
|
+
}
|
|
14418
|
+
|
|
14419
|
+
.ab-columns-2 {
|
|
14420
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
14421
|
+
}
|
|
14422
|
+
|
|
14423
|
+
.ab-columns-3 {
|
|
14424
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
14425
|
+
}
|
|
14426
|
+
|
|
14427
|
+
.ab-column {
|
|
14428
|
+
min-width: 0;
|
|
14429
|
+
}
|
|
14430
|
+
|
|
14431
|
+
.ab-quote {
|
|
14432
|
+
padding-left: 20px;
|
|
14433
|
+
font-style: italic;
|
|
14434
|
+
}
|
|
14435
|
+
|
|
14436
|
+
.ab-quote cite {
|
|
14437
|
+
display: block;
|
|
14438
|
+
margin-top: 4px;
|
|
14439
|
+
color: var(--muted);
|
|
14440
|
+
font-size: 13px;
|
|
14441
|
+
font-style: normal;
|
|
14442
|
+
}
|
|
14443
|
+
|
|
14444
|
+
.ab-table {
|
|
14445
|
+
overflow-x: auto;
|
|
14446
|
+
}
|
|
14447
|
+
|
|
14448
|
+
.ab-table table {
|
|
14449
|
+
width: 100%;
|
|
14450
|
+
border-collapse: collapse;
|
|
14451
|
+
font-size: 14px;
|
|
14452
|
+
}
|
|
14453
|
+
|
|
14454
|
+
.ab-table th,
|
|
14455
|
+
.ab-table td {
|
|
14456
|
+
padding: 8px 16px 8px 0;
|
|
14457
|
+
border-bottom: 1px solid var(--line);
|
|
14458
|
+
text-align: left;
|
|
14459
|
+
vertical-align: top;
|
|
14460
|
+
}
|
|
14461
|
+
|
|
14462
|
+
.ab-table th {
|
|
14463
|
+
font-weight: 700;
|
|
14464
|
+
}
|
|
14465
|
+
|
|
14466
|
+
.ab-fold > summary {
|
|
14467
|
+
font-weight: 700;
|
|
14468
|
+
cursor: pointer;
|
|
14469
|
+
}
|
|
14470
|
+
|
|
14471
|
+
.ab-fold-body {
|
|
14472
|
+
padding-top: 8px;
|
|
14473
|
+
}
|
|
14474
|
+
|
|
14475
|
+
.game-about-more.is-folded {
|
|
14476
|
+
position: relative;
|
|
14477
|
+
overflow: hidden;
|
|
14478
|
+
max-height: 1400px;
|
|
14479
|
+
mask-image: linear-gradient(180deg, #000 calc(100% - 120px), transparent);
|
|
14480
|
+
}
|
|
14481
|
+
|
|
14482
|
+
.about-more {
|
|
14483
|
+
margin-top: 8px;
|
|
14484
|
+
}
|
|
14485
|
+
|
|
14486
|
+
@media (max-width: 720px) {
|
|
14487
|
+
.ab-columns-2,
|
|
14488
|
+
.ab-columns-3 {
|
|
14489
|
+
grid-template-columns: minmax(0, 1fr);
|
|
14490
|
+
}
|
|
14491
|
+
|
|
14492
|
+
.ab-gallery-3 {
|
|
14493
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
14494
|
+
}
|
|
14495
|
+
}
|
|
14496
|
+
|
|
14497
|
+
/* The dashboard's About tab: the source, the same drawing beside it, then its files and the commands. */
|
|
14498
|
+
.about-editor {
|
|
14499
|
+
padding-bottom: 16px;
|
|
14500
|
+
}
|
|
14501
|
+
|
|
14502
|
+
.about-tools {
|
|
14503
|
+
display: flex;
|
|
14504
|
+
flex-wrap: wrap;
|
|
14505
|
+
gap: 4px;
|
|
14506
|
+
margin-bottom: 10px;
|
|
14507
|
+
}
|
|
14508
|
+
|
|
14509
|
+
.about-tool {
|
|
14510
|
+
min-height: 30px;
|
|
14511
|
+
padding: 0 10px;
|
|
14512
|
+
border: 1px solid var(--line);
|
|
14513
|
+
border-radius: 6px;
|
|
14514
|
+
background: transparent;
|
|
14515
|
+
color: var(--text);
|
|
14516
|
+
font: 600 13px var(--font);
|
|
14517
|
+
cursor: pointer;
|
|
14518
|
+
}
|
|
14519
|
+
|
|
14520
|
+
.about-tool:hover {
|
|
14521
|
+
background: var(--bg-hover);
|
|
14522
|
+
}
|
|
14523
|
+
|
|
14524
|
+
.about-tool-example {
|
|
14525
|
+
margin-left: auto;
|
|
14526
|
+
color: var(--muted);
|
|
14527
|
+
}
|
|
14528
|
+
|
|
14529
|
+
.about-panes {
|
|
14530
|
+
display: grid;
|
|
14531
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
14532
|
+
gap: 12px;
|
|
14533
|
+
height: min(72vh, 780px);
|
|
14534
|
+
min-height: 420px;
|
|
14535
|
+
}
|
|
14536
|
+
|
|
14537
|
+
.about-pane {
|
|
14538
|
+
min-width: 0;
|
|
14539
|
+
min-height: 0;
|
|
14540
|
+
}
|
|
14541
|
+
|
|
14542
|
+
.about-source {
|
|
14543
|
+
display: block;
|
|
14544
|
+
width: 100%;
|
|
14545
|
+
height: 100%;
|
|
14546
|
+
padding: 14px;
|
|
14547
|
+
border: 1px solid var(--line-strong);
|
|
14548
|
+
border-radius: var(--radius);
|
|
14549
|
+
background: var(--bg-soft);
|
|
14550
|
+
color: var(--text);
|
|
14551
|
+
font: 13px/1.6 var(--mono);
|
|
14552
|
+
resize: none;
|
|
14553
|
+
tab-size: 2;
|
|
14554
|
+
}
|
|
14555
|
+
|
|
14556
|
+
.about-source:focus {
|
|
14557
|
+
border-color: var(--accent);
|
|
14558
|
+
outline: 1px solid var(--accent);
|
|
14559
|
+
outline-offset: -2px;
|
|
14560
|
+
}
|
|
14561
|
+
|
|
14562
|
+
.about-preview {
|
|
14563
|
+
overflow-y: auto;
|
|
14564
|
+
padding: 16px 18px;
|
|
14565
|
+
border: 1px solid var(--line);
|
|
14566
|
+
border-radius: var(--radius);
|
|
14567
|
+
background: var(--bg);
|
|
14568
|
+
}
|
|
14569
|
+
|
|
14570
|
+
.about-preview-empty {
|
|
14571
|
+
margin: 0;
|
|
14572
|
+
color: var(--muted);
|
|
14573
|
+
}
|
|
14574
|
+
|
|
14575
|
+
.about-problems {
|
|
14576
|
+
display: flex;
|
|
14577
|
+
flex-direction: column;
|
|
14578
|
+
gap: 4px;
|
|
14579
|
+
margin: 10px 0 0;
|
|
14580
|
+
padding: 10px 12px;
|
|
14581
|
+
border-radius: var(--radius);
|
|
14582
|
+
background: var(--danger-soft);
|
|
14583
|
+
font-size: 13px;
|
|
14584
|
+
list-style: none;
|
|
14585
|
+
}
|
|
14586
|
+
|
|
14587
|
+
.about-problem {
|
|
14588
|
+
margin-right: 4px;
|
|
14589
|
+
padding: 0;
|
|
14590
|
+
border: 0;
|
|
14591
|
+
background: none;
|
|
14592
|
+
color: var(--danger);
|
|
14593
|
+
font: 700 13px var(--font);
|
|
14594
|
+
cursor: pointer;
|
|
14595
|
+
text-decoration: underline;
|
|
14596
|
+
}
|
|
14597
|
+
|
|
14598
|
+
.about-foot {
|
|
14599
|
+
display: flex;
|
|
14600
|
+
align-items: center;
|
|
14601
|
+
gap: 12px;
|
|
14602
|
+
margin-top: 12px;
|
|
14603
|
+
}
|
|
14604
|
+
|
|
14605
|
+
.about-state {
|
|
14606
|
+
color: var(--muted);
|
|
14607
|
+
font-size: 13px;
|
|
14608
|
+
}
|
|
14609
|
+
|
|
14610
|
+
.about-count {
|
|
14611
|
+
margin-left: auto;
|
|
14612
|
+
color: var(--muted);
|
|
14613
|
+
font-size: 12px;
|
|
14614
|
+
font-variant-numeric: tabular-nums;
|
|
14615
|
+
}
|
|
14616
|
+
|
|
14617
|
+
.about-count.is-over {
|
|
14618
|
+
color: var(--danger);
|
|
14619
|
+
font-weight: 700;
|
|
14620
|
+
}
|
|
14621
|
+
|
|
14622
|
+
.about-files {
|
|
14623
|
+
display: grid;
|
|
14624
|
+
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
|
14625
|
+
gap: 10px;
|
|
14626
|
+
margin: 0;
|
|
14627
|
+
padding: 0;
|
|
14628
|
+
list-style: none;
|
|
14629
|
+
}
|
|
14630
|
+
|
|
14631
|
+
.about-file {
|
|
14632
|
+
position: relative;
|
|
14633
|
+
min-width: 0;
|
|
14634
|
+
}
|
|
14635
|
+
|
|
14636
|
+
.about-file-pick {
|
|
14637
|
+
display: block;
|
|
14638
|
+
overflow: hidden;
|
|
14639
|
+
width: 100%;
|
|
14640
|
+
padding: 0;
|
|
14641
|
+
border: 1px solid var(--line);
|
|
14642
|
+
border-radius: var(--radius);
|
|
14643
|
+
background: var(--bg-soft);
|
|
14644
|
+
color: var(--text);
|
|
14645
|
+
cursor: pointer;
|
|
14646
|
+
text-align: left;
|
|
14647
|
+
}
|
|
14648
|
+
|
|
14649
|
+
.about-file-pick:hover {
|
|
14650
|
+
border-color: var(--line-strong);
|
|
14651
|
+
}
|
|
14652
|
+
|
|
14653
|
+
.about-file-pick img,
|
|
14654
|
+
.about-file-video {
|
|
14655
|
+
display: flex;
|
|
14656
|
+
align-items: center;
|
|
14657
|
+
justify-content: center;
|
|
14658
|
+
width: 100%;
|
|
14659
|
+
aspect-ratio: 16 / 10;
|
|
14660
|
+
object-fit: cover;
|
|
14661
|
+
color: var(--muted);
|
|
14662
|
+
font-size: 22px;
|
|
14663
|
+
}
|
|
14664
|
+
|
|
14665
|
+
.about-file-name {
|
|
14666
|
+
display: block;
|
|
14667
|
+
overflow: hidden;
|
|
14668
|
+
padding: 6px 8px;
|
|
14669
|
+
font: 12px var(--mono);
|
|
14670
|
+
text-overflow: ellipsis;
|
|
14671
|
+
white-space: nowrap;
|
|
14672
|
+
}
|
|
14673
|
+
|
|
14674
|
+
.about-file-add .dz-wide {
|
|
14675
|
+
aspect-ratio: auto;
|
|
14676
|
+
min-height: 118px;
|
|
14677
|
+
}
|
|
14678
|
+
|
|
14679
|
+
.about-reference h3 {
|
|
14680
|
+
margin: 16px 0 6px;
|
|
14681
|
+
color: var(--muted);
|
|
14682
|
+
font-size: 12px;
|
|
14683
|
+
font-weight: 700;
|
|
14684
|
+
}
|
|
14685
|
+
|
|
14686
|
+
.about-commands {
|
|
14687
|
+
width: 100%;
|
|
14688
|
+
border-collapse: collapse;
|
|
14689
|
+
font-size: 13px;
|
|
14690
|
+
}
|
|
14691
|
+
|
|
14692
|
+
.about-commands td {
|
|
14693
|
+
padding: 6px 12px 6px 0;
|
|
14694
|
+
border-top: 1px solid var(--line);
|
|
14695
|
+
vertical-align: top;
|
|
14696
|
+
}
|
|
14697
|
+
|
|
14698
|
+
.about-commands td:first-child {
|
|
14699
|
+
width: 48%;
|
|
14700
|
+
overflow-wrap: anywhere;
|
|
14701
|
+
}
|
|
14702
|
+
|
|
14703
|
+
.about-commands td:last-child {
|
|
14704
|
+
color: var(--muted);
|
|
14705
|
+
}
|
|
14706
|
+
|
|
14707
|
+
@media (max-width: 860px) {
|
|
14708
|
+
.about-panes {
|
|
14709
|
+
grid-template-columns: minmax(0, 1fr);
|
|
14710
|
+
height: auto;
|
|
14711
|
+
}
|
|
14712
|
+
|
|
14713
|
+
.about-source {
|
|
14714
|
+
height: 52vh;
|
|
14715
|
+
}
|
|
14716
|
+
|
|
14717
|
+
.about-preview {
|
|
14718
|
+
max-height: 70vh;
|
|
14719
|
+
}
|
|
14720
|
+
}
|
|
14721
|
+
`;var X=JSON.parse(document.getElementById("ow-data").textContent),Z=X.game.slug,N=new URL(location.href).searchParams,_e=/^[2-9]$/.test(N.get("player")??"")?N.get("player"):null,De=N.get("demo"),I=De===null||De==="0"?null:{paid:De!=="free"};Gt(I!==null);var Vt=document.createElement("style");Vt.textContent=`${Ut}
|
|
13781
14722
|
.ow-local-panel { position: fixed; z-index: 30; top: 64px; left: 10px; max-width: min(340px, calc(100vw - 20px)); padding: 12px 14px; border-radius: 12px; background: var(--glass); border: 1px solid var(--line); color: var(--text); font: 14px/1.45 var(--font); backdrop-filter: blur(12px); }
|
|
13782
14723
|
.ow-local-panel[hidden] { display: none; }
|
|
13783
14724
|
.ow-local-panel b { font-weight: 650; }
|
|
@@ -13785,4 +14726,4 @@ body.share-frame {
|
|
|
13785
14726
|
.ow-local-panel p { margin: 0 0 6px; }
|
|
13786
14727
|
.ow-local-toast { position: fixed; z-index: 40; left: 50%; bottom: 24px; transform: translateX(-50%); max-width: calc(100vw - 32px); padding: 10px 14px; border-radius: 10px; background: var(--glass); color: var(--text); font: 14px/1.4 var(--font); border: 1px solid var(--line); }
|
|
13787
14728
|
.ow-local-toast[hidden] { display: none; }
|
|
13788
|
-
`;document.head.append(Ht);document.body.classList.add("play");var M=document.getElementById("ow-game");M.setAttribute("sandbox",pt);M.setAttribute("allow",dt);var F=document.getElementById("ow-root");function Ro(){let t=new URLSearchParams;for(let[o,r]of j)gt.has(o)||t.append(o,r);let e=t.toString();return e&&e.length<=400?`?${e}`:""}var B=S("div","ow-hud ow-pos-top-left"),_e=S("div","ow-bar"),Eo='<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="2"/><circle cx="12" cy="12" r="3" fill="currentColor"/></svg>',Po='<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5.5A2.5 2.5 0 0 1 6.5 3h11A2.5 2.5 0 0 1 20 5.5v8a2.5 2.5 0 0 1-2.5 2.5H10l-4.2 3.4c-.5.4-1.3 0-1.3-.6V16A2.5 2.5 0 0 1 4 13.5z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg>',Mo='<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="10" cy="8" r="3.5" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M3.5 19.5c.8-3.4 3.3-5.5 6.5-5.5s5.7 2.1 6.5 5.5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/><path d="M19 7.5v6M16 10.5h6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',Ft=Ie("Local platform",Eo),qt=Ie("Chat (not on this computer)",Po),Kt=Ie("Another player",Mo);_e.append(Ft,qt,Kt);B.append(_e);var D=S("div","ow-local-panel");D.hidden=!0;F.append(B,D);var W=S("div","ow-local-toast");W.hidden=!0;F.append(W);var Nt=0;function N(t){W.textContent=t,W.hidden=!1,window.clearTimeout(Nt),Nt=window.setTimeout(()=>W.hidden=!0,4e3)}Ft.addEventListener("click",()=>{D.hidden=!D.hidden,D.hidden||Ao()});qt.addEventListener("click",()=>N("Chat is the platform\u2019s: it isn\u2019t on this computer."));Kt.addEventListener("click",()=>{window.open(X(),"_blank")});function X(){let t=new URL(location.href),e=Math.min(9,Number(De??1)+1);return t.searchParams.set("player",String(e)),P&&t.searchParams.set("server",P),t.href}function Ao(){D.replaceChildren();let t=e=>{let o=document.createElement("p");o.innerHTML=e,D.append(o)};t(`<b>${ce(Y.game.name)}</b> on this computer`),t(`You are <b>${ce(Vt?.name??"\u2026")}</b>${G?` in <code>${ce(G)}</code>`:""}`),t(`<a href="${ce(X())}" target="_blank">Open another player</a> (up to 9: <code>?player=2</code>\u2026)`),t("Saves, badges and scores are kept by <code>onceworlds serve</code> while it runs.")}function S(t,e=""){let o=document.createElement(t);return e&&(o.className=e),o}function Ie(t,e){let o=S("button","ow-icon-btn");return o.type="button",o.title=t,o.setAttribute("aria-label",t),o.innerHTML=e,o}function ce(t){return t.replace(/[&<>"']/g,e=>`&#${e.charCodeAt(0)};`)}async function k(t,e={}){let o=new URL(`/__emulator/api/${t}`,location.href);De&&o.searchParams.set("player",De);let r=await fetch(o,{...e,headers:e.body?{"Content-Type":"application/json"}:void 0}),n=await r.json().catch(()=>null);if(!r.ok)throw new Error(n?.message??`The local platform answered ${r.status}`);return n}var $o=Date.now(),me=k("me").then(({player:t,now:e})=>({player:t,timeOffset:Math.round(e-($o+Date.now())/2)})),Vt=null;me.then(t=>Vt=t.player).catch(()=>{});var g=null,G=null,U=null,xe="",je=null,Be=!1,Oe=0,Wt=0;me.then(t=>Wt=t.timeOffset).catch(()=>{});var P=Ye.test(j.get("server")??"")?j.get("server"):null,ge={value:At(J)},z={hellos:0,joins:0,errors:[],lastAlive:0,closed:null},f=new ae(F,{now:()=>Date.now()+Wt,onSetting:(t,e)=>{let o=f.chooseSetting(t,e);o&&(g?.send({t:"state",k:K,v:o}),g?.send({t:"unready"}),f.handle({t:"unready"}),v.emit("room",{t:"unready"}))},onReady:t=>Yt(t),onStart:()=>g?.send({t:"start"}),onStop:()=>g?.send({t:"end"}),onInvite:()=>window.open(X(),"_blank"),onLayout:()=>H.changed()}),O=new ne(F,t=>v.emit("controls",t),()=>H.changed());function Yt(t){g?.send({t:"ready",ready:t}),f.setReadyLocal(t),v.emit("room",{t:"ready",id:xe,ready:t})}function Ne(t,e=!1){O.touch!==t&&(O.setTouch(t),e||v.emit("input",{touch:t}))}addEventListener("pointerdown",t=>t.isTrusted&&Ne(t.pointerType!=="mouse"),!0);addEventListener("keydown",t=>t.isTrusted&&Ne(!1),!0);var H=new ie(Jt,t=>v.emit("reserved",t)),he=new te(async()=>({game:J,player:null})),v=new ee(M,{async"session.get"(){let{player:t,timeOffset:e}=await me;return{player:t,game:{slug:J,name:Y.game.name,owner:"local"},audio:{volume:1,muted:!1},settings:{quality:"auto",reducedMotion:!1,showStats:!1},timeOffset:e,platformOrigin:location.origin}},"save.get":({key:t})=>k(`save?key=${encodeURIComponent(String(t))}`),"save.set":({key:t,value:e})=>k(`save?key=${encodeURIComponent(String(t))}`,{method:"PUT",body:JSON.stringify({value:e??null})}).then(()=>null),"save.delete":({key:t})=>k(`save?key=${encodeURIComponent(String(t))}`,{method:"DELETE"}).then(()=>null),"save.list":()=>k("saves"),"storage.open":t=>he.read(t),"storage.commit":t=>he.commit(t),"storage.delete":t=>he.remove(t),"storage.list":()=>he.list(),async"room.join"(t){await me;let e=t??{};if(je=e.lobby==="card"||e.lobby==="bar"?e.lobby:null,Be=!ut(e),f.setSchema(Qe(e.settings)),e.party&&g)throw new Error("Parties go into matchmaking on onceworlds.com: the local platform keeps everyone where they are.");ue();let o=!e.name&&!P&&!e.private&&ge.value&&To(ge.value.key,e)?ge.value:null;if(ge.value=null,o){let r=await Ut({key:o.key,rejoin:o.rejoin,maxPlayers:e.maxPlayers,minPlayers:e.minPlayers,countdown:e.countdown,teams:e.teams,ranked:e.ranked}).catch(()=>null);if(r)return r;ue()}return Ut(Oo(e))},"room.leave"(){return ue(),null},"net.fetch":()=>{throw new Error("onceworlds.fetch fills in secrets on onceworlds.com: it does nothing on this computer. Push a draft (onceworlds deploy) to try it.")},"badges.list":()=>k("badges"),"badges.award":({key:t})=>I?.paid?{awarded:!1}:k("badges",{method:"POST",body:JSON.stringify({key:String(t)})}).then(e=>(e.awarded&&N(`Badge earned: ${e.badge?.name??t}`),{awarded:e.awarded})),"leaderboards.submit":({board:t,score:e,lowerIsBetter:o})=>I?.paid?null:k("leaderboards",{method:"POST",body:JSON.stringify({board:String(t),score:Number(e),lowerIsBetter:o===!0})}),"leaderboards.top":({board:t,limit:e,lowerIsBetter:o})=>k(`leaderboards?board=${encodeURIComponent(String(t))}&limit=${Number(e)||10}&lower=${o===!0?1:0}`),"ratings.get":()=>null,"ratings.top":()=>[],"ui.invite"(){return window.open(X(),"_blank"),null},"ui.fullscreen"(){return document.documentElement.requestFullscreen?.().catch(()=>{}),null},"ui.tapped":()=>null,"ui.controls"(t){return O.setLayout(t),null},"ui.orientation":()=>null,"ui.menuPosition"(t){let e=t?.position;return(e==="top-left"||e==="top-right"||e==="bottom-left"||e==="bottom-right")&&(B.className=`ow-hud ow-pos-${e}`,H.changed()),null},"ui.look"(t){return Gt(t),null},"player.rename":()=>null,"demo.end":()=>I?Lo(I.paid):!1,"data.game.get":({key:t})=>k(`gamedata?key=${encodeURIComponent(String(t))}`),"data.game.op":t=>k("gamedata",{method:"POST",body:JSON.stringify(t)}),"player.avatar":t=>{let e=t?.id;return typeof e=="string"&&/^[A-Za-z0-9-]{1,64}$/.test(e)?Ve(e):null}},{"room.send":({d:t,to:e})=>g?.send({t:"msg",d:t,to:e}),"room.presence":({d:t})=>g?.send({t:"presence",d:t}),"room.hideLobby":({hidden:t})=>f.setHidden(t===!0),"room.state":({k:t,v:e,w:o})=>g?.send({t:"state",k:t,v:e,...typeof o=="number"&&Number.isSafeInteger(o)&&o>0&&o<=2147483647?{w:o}:{}}),"room.team":({id:t,team:e})=>g?.send({t:"team",id:String(t),team:Number(e)}),"room.open":({open:t})=>g?.send({t:"open",open:t===!0}),"room.result":({result:t})=>g?.send({t:"result",result:t}),"room.kick":({id:t})=>g?.send({t:"kick",id:String(t)}),"room.votekick":({id:t})=>g?.send({t:"votekick",id:String(t)}),"room.ready":({ready:t})=>{g?.send({t:"ready",ready:t===!0}),f.setReadyLocal(t===!0)},"room.unready":()=>{g?.send({t:"unready"}),f.handle({t:"unready"})},"room.transfer":({id:t})=>g?.send({t:"transfer",id:String(t)}),"room.start":({countdown:t,open:e})=>g?.send({t:"start",...Number.isFinite(t)?{countdown:Number(t)}:{},...e===!0?{open:!0}:{}}),"room.end":()=>g?.send({t:"end"}),"room.pause":({paused:t})=>g?.send({t:"pause",paused:t===!0}),"room.idle":({idle:t})=>g?.send({t:"idle",idle:t===!0}),"room.private":({k:t,v:e,id:o})=>typeof t=="string"&&g?.send({t:"private",k:t,v:e,...typeof o=="string"?{id:o}:{}}),"room.datareset":()=>g?.send({t:"datareset"}),"room.admit":({ids:t})=>g?.send({t:"admit",ids:Array.isArray(t)?t.filter(e=>typeof e=="string").slice(0,50):[]}),alive:()=>{z.lastAlive=Date.now()},stats:()=>{},hotkey:()=>{},vibrate:()=>{},input:t=>Ne(t?.touch===!0,!0),error:t=>{z.errors.length<20&&z.errors.push(String(t?.message??t).slice(0,300))},"input.first":()=>{},console:()=>{},debug:()=>{}},()=>{z.hellos++,_t(),ue(),B.className="ow-hud ow-pos-top-left",O.setLayout(null),Gt(null),v.emit("input",{touch:O.touch}),H.resend()},{demo:I!==null}),Te=null;function Lo(t){return Te??=new Promise(e=>{v.emit("pause",null);let o=S("div","ow-name ow-demo-end"),r=S("div","ow-name-form ow-demo-box"),n=S("h2");n.textContent="End of demo";let a=S("p","ow-demo-name");a.textContent=Y.game.name;let i=S("button","ow-btn ow-btn-primary");i.type="button",i.textContent=t?"Buy":"Favorite",i.addEventListener("click",()=>N(t?"On onceworlds.com, Buy opens the game\u2019s store page.":"On onceworlds.com, Favorite follows the game."));let s=S("button","ow-text-btn ow-name-login");s.type="button",s.textContent="Back to game",s.addEventListener("click",()=>{o.remove(),Te=null,v.emit("resume",null),M.focus(),e(!0)}),r.append(n,a,i,s),o.append(r),F.append(o),i.focus()}),Te}function Gt(t){let{look:e}=xt(t);f.setLook(St(e)),O.setLook(zt(e))}function Jt(){let t=M.getBoundingClientRect();if(!t.width||!t.height)return null;let{stick:e,buttons:o}=O.reservedBoxes(),r=_e.getBoundingClientRect(),n=parseFloat(getComputedStyle(B).paddingTop)||0,a=r.width&&r.height?{left:r.left-n,top:r.top-n,width:r.width+2*n,height:r.height+2*n}:null;return Mt(t,[{kind:"menu",box:B.hidden?null:a},{kind:"lobby",box:f.reservedBox()},{kind:"stick",box:e},{kind:"buttons",box:o}])}for(let t of["resize","orientationchange"])addEventListener(t,()=>H.changed());typeof ResizeObserver=="function"&&new ResizeObserver(()=>H.changed()).observe(M);function Co(t){return t.slice(0,t.lastIndexOf(":"))}function To(t,e){let o=(e.teams??0)>=2?e.teams:0,r=Math.min(E.roomMaxPlayersCap,Math.max(2,e.maxPlayers??16)),n=Xe(e.minPlayers,r,Z);return Co(t)===`pub:${we({mode:e.mode||"default",max:r,teams:o,ranked:e.ranked===!0,min:n})}`}function Do(){let t="abcdefghijklmnopqrstuvwxyz0123456789";return Array.from(crypto.getRandomValues(new Uint8Array(12)),e=>t[e%t.length]).join("")}function Oo(t){let{name:e,maxPlayers:o,minPlayers:r,countdown:n,mode:a,teams:i,ranked:s}=t,c=t.minPlayersPrivate??r;if(e)return{name:e,maxPlayers:o,minPlayers:c,countdown:n,teams:i};if(t.private&&!P){P=Do(),$t(J,P);let d=new URL(location.href);d.searchParams.set("server",P),history.replaceState(null,"",d.href)}return P?{server:P,maxPlayers:o,minPlayers:c,countdown:n,teams:i,private:t.private}:{mode:a,maxPlayers:o,minPlayers:r,countdown:n,teams:i,ranked:s}}async function Ut(t){let e=new de(J,t,{onMessage:n=>e===g&&_o(n),onClose:n=>e===g&&Io(n),onConnection:n=>{e===g&&(n||v.emit("room.connection",{connected:!1}))}});g=e;let o=await e.join();if(e!==g)throw new Error("Left the server while joining");let r=o.room.startsWith("private:")?{...o,invite:X()}:o;return xe=o.you,U=o.match??null,G=o.room,z.joins++,Oe=Je(o.room)?.max??Math.min(t.maxPlayers??E.roomMaxPlayersDefault,E.roomMaxPlayersCap),f.enable(je,{ownCountdown:Be}),f.setRoom(r,Oe),r}function _o(t){if(t.t==="update"||t.t==="move")return;if(t.t==="datareset"){N("This server\u2019s world was started over."),M.src=M.src;return}t.t==="chat"&&(t.entry.to||t.entry.channel)||t.t==="channel"||v.emit("room",t),t.t!=="welcome"&&f.handle(t),t.t==="welcome"?(f.setRoom(t,Oe),U=t.match??null):t.t==="match"?U=t.match:t.t==="error"&&t.code==="cooldown"&&(N(t.message),f.setReadyLocal(!1),v.emit("room",{t:"ready",id:xe,ready:!1}))}function Io(t){g=null,G=null,U=null,z.closed=t,f.setRoom(null),N(t==="replaced"?"You opened this game in another tab, so multiplayer moved there.":t==="kicked"?"You were removed from the server.":"Disconnected from the server."),v.emit("room.closed",{reason:t})}function ue(){g&&(g.close(),g=null,G=null,U=null,f.setRoom(null))}window.__owLocal={get you(){return xe},get room(){return G},get match(){return U},get lobby(){return je},get ownCountdown(){return Be},get hellos(){return z.hellos},get joins(){return z.joins},get errors(){return z.errors},get lastAlive(){return z.lastAlive},get closed(){return z.closed},get reserved(){return Jt()},ready(t){return g?(Yt(t),!0):!1},start(t){return g?(g.send({t:"start",...Number.isFinite(t)?{countdown:Number(t)}:{}}),!0):!1},chrome(t){F.style.visibility=t?"":"hidden"}};M.src=`${Y.gameOrigin}/${Ro()}`;})();
|
|
14729
|
+
`;document.head.append(Vt);document.body.classList.add("play");var y=document.getElementById("ow-game");y.setAttribute("sandbox",pt);y.setAttribute("allow",dt);var q=document.getElementById("ow-root");function Lo(){let t=new URLSearchParams;for(let[o,r]of N)gt.has(o)||t.append(o,r);let e=t.toString();return e&&e.length<=400?`?${e}`:""}var G=z("div","ow-hud ow-pos-top-left"),Ie=z("div","ow-bar"),$o='<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" stroke-width="2"/><circle cx="12" cy="12" r="3" fill="currentColor"/></svg>',Co='<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 5.5A2.5 2.5 0 0 1 6.5 3h11A2.5 2.5 0 0 1 20 5.5v8a2.5 2.5 0 0 1-2.5 2.5H10l-4.2 3.4c-.5.4-1.3 0-1.3-.6V16A2.5 2.5 0 0 1 4 13.5z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/></svg>',To='<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="10" cy="8" r="3.5" fill="none" stroke="currentColor" stroke-width="1.8"/><path d="M3.5 19.5c.8-3.4 3.3-5.5 6.5-5.5s5.7 2.1 6.5 5.5" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/><path d="M19 7.5v6M16 10.5h6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',Wt=Be("Local platform",$o),Yt=Be("Chat (not on this computer)",Co),Jt=Be("Another player",To);Ie.append(Wt,Yt,Jt);G.append(Ie);var O=z("div","ow-local-panel");O.hidden=!0;q.append(G,O);var J=z("div","ow-local-toast");J.hidden=!0;q.append(J);var Ht=0;function U(t){J.textContent=t,J.hidden=!1,window.clearTimeout(Ht),Ht=window.setTimeout(()=>J.hidden=!0,4e3)}Wt.addEventListener("click",()=>{O.hidden=!O.hidden,O.hidden||Do()});Yt.addEventListener("click",()=>U("Chat is the platform\u2019s: it isn\u2019t on this computer."));Jt.addEventListener("click",()=>{window.open(Q(),"_blank")});function Q(){let t=new URL(location.href),e=Math.min(9,Number(_e??1)+1);return t.searchParams.set("player",String(e)),M&&t.searchParams.set("server",M),t.href}function Do(){O.replaceChildren();let t=e=>{let o=document.createElement("p");o.innerHTML=e,O.append(o)};t(`<b>${he(X.game.name)}</b> on this computer`),t(`You are <b>${he(Xt?.name??"\u2026")}</b>${H?` in <code>${he(H)}</code>`:""}`),t(`<a href="${he(Q())}" target="_blank">Open another player</a> (up to 9: <code>?player=2</code>\u2026)`),t("Saves, badges and scores are kept by <code>onceworlds serve</code> while it runs.")}function z(t,e=""){let o=document.createElement(t);return e&&(o.className=e),o}function Be(t,e){let o=z("button","ow-icon-btn");return o.type="button",o.title=t,o.setAttribute("aria-label",t),o.innerHTML=e,o}function he(t){return t.replace(/[&<>"']/g,e=>`&#${e.charCodeAt(0)};`)}async function S(t,e={}){let o=new URL(`/__emulator/api/${t}`,location.href);_e&&o.searchParams.set("player",_e);let r=await fetch(o,{...e,headers:e.body?{"Content-Type":"application/json"}:void 0}),a=await r.json().catch(()=>null);if(!r.ok)throw new Error(a?.message??`The local platform answered ${r.status}`);return a}var Oo=Date.now(),fe=S("me").then(({player:t,now:e})=>({player:t,timeOffset:Math.round(e-(Oo+Date.now())/2)})),Xt=null;fe.then(t=>Xt=t.player).catch(()=>{});var g=null,H=null,_=null,be="",B=null,we=!1,Zt=!1,je=0,Qt=0;fe.then(t=>Qt=t.timeOffset).catch(()=>{});var M=Ye.test(N.get("server")??"")?N.get("server"):null,me={value:Ct(Z)},R={hellos:0,joins:0,errors:[],lastAlive:0,closed:null},u=new le(q,{now:()=>Date.now()+Qt,onSetting:(t,e)=>{let o=u.chooseSetting(t,e);o&&(g?.send({t:"state",k:V,v:o}),g?.send({t:"unready"}),u.handle({t:"unready"}),w.emit("room",{t:"unready"}))},onReady:t=>eo(t),onStart:()=>g?.send({t:"start"}),onStop:()=>g?.send({t:"end"}),onInvite:()=>window.open(Q(),"_blank"),onLayout:()=>F.changed(),onPressed:to}),C=new ie(q,t=>w.emit("controls",t),()=>F.changed());u.setKeyMark(!C.touch);function eo(t){g?.send({t:"ready",ready:t}),u.setReadyLocal(t),w.emit("room",{t:"ready",id:be,ready:t})}function Ne(t,e=!1){C.touch!==t&&(C.setTouch(t),u.setKeyMark(!t),e||w.emit("input",{touch:t}))}addEventListener("pointerdown",t=>t.isTrusted&&Ne(t.pointerType!=="mouse"),!0);addEventListener("keydown",t=>t.isTrusted&&Ne(!1),!0);addEventListener("keydown",t=>{let e=document.activeElement;t.isTrusted&&!t.repeat&&xt(t)&&(!e||e===document.body)&&u.pressKey()});function to(){y.focus(),y.contentWindow?.focus()}function Ft(){B||Zt||(B="bar",u.enable(B,{ownCountdown:we}))}var F=new se(()=>{let t=oo();return t&&{areas:t,link:u.link(y.getBoundingClientRect())}},({areas:t,link:e})=>{w.emit("reserved",t),w.emit("lobby",e)}),ue=new re(async()=>({game:Z,player:null})),w=new oe(y,{async"session.get"(){let{player:t,timeOffset:e}=await fe;return{player:t,game:{slug:Z,name:X.game.name,owner:"local"},audio:{volume:1,muted:!1},settings:{quality:"auto",reducedMotion:!1,showStats:!1},timeOffset:e,platformOrigin:location.origin}},"save.get":({key:t})=>S(`save?key=${encodeURIComponent(String(t))}`),"save.set":({key:t,value:e})=>S(`save?key=${encodeURIComponent(String(t))}`,{method:"PUT",body:JSON.stringify({value:e??null})}).then(()=>null),"save.delete":({key:t})=>S(`save?key=${encodeURIComponent(String(t))}`,{method:"DELETE"}).then(()=>null),"save.list":()=>S("saves"),"storage.open":t=>ue.read(t),"storage.commit":t=>ue.commit(t),"storage.delete":t=>ue.remove(t),"storage.list":()=>ue.list(),async"room.join"(t){await fe;let e=t??{};if(B=ut(e),Zt=e.lobby==="game",we=!mt(e),u.setSchema(Qe(e.settings)),e.party&&g)throw new Error("Parties go into matchmaking on onceworlds.com: the local platform keeps everyone where they are.");xe();let o=!e.name&&!M&&!e.private&&me.value&&Io(me.value.key,e)?me.value:null;if(me.value=null,o){let r=await Kt({key:o.key,rejoin:o.rejoin,maxPlayers:e.maxPlayers,minPlayers:e.minPlayers,countdown:e.countdown,teams:e.teams,ranked:e.ranked}).catch(()=>null);if(r)return r;xe()}return Kt(No(e))},"room.leave"(){return xe(),null},"net.fetch":()=>{throw new Error("onceworlds.fetch fills in secrets on onceworlds.com: it does nothing on this computer. Push a draft (onceworlds deploy) to try it.")},"badges.list":()=>S("badges"),"badges.award":({key:t})=>I?.paid?{awarded:!1}:S("badges",{method:"POST",body:JSON.stringify({key:String(t)})}).then(e=>(e.awarded&&U(`Badge earned: ${e.badge?.name??t}`),{awarded:e.awarded})),"leaderboards.submit":({board:t,score:e,lowerIsBetter:o})=>I?.paid?null:S("leaderboards",{method:"POST",body:JSON.stringify({board:String(t),score:Number(e),lowerIsBetter:o===!0})}),"leaderboards.top":({board:t,limit:e,lowerIsBetter:o})=>S(`leaderboards?board=${encodeURIComponent(String(t))}&limit=${Number(e)||10}&lower=${o===!0?1:0}`),"ratings.get":()=>null,"ratings.top":()=>[],"ui.invite"(){return window.open(Q(),"_blank"),null},"ui.fullscreen"(){return document.documentElement.requestFullscreen?.().catch(()=>{}),null},"ui.tapped":()=>null,"ui.controls"(t){return C.setLayout(t),null},"ui.orientation":()=>null,"ui.menuPosition"(t){let e=t?.position;return(e==="top-left"||e==="top-right"||e==="bottom-left"||e==="bottom-right")&&(G.className=`ow-hud ow-pos-${e}`,F.changed()),null},"ui.look"(t){return qt(t),null},"player.rename":()=>null,"demo.end":()=>I?_o(I.paid):!1,"data.game.get":({key:t})=>S(`gamedata?key=${encodeURIComponent(String(t))}`),"data.game.op":t=>S("gamedata",{method:"POST",body:JSON.stringify(t)}),"player.avatar":t=>{let e=t?.id;return typeof e=="string"&&/^[A-Za-z0-9-]{1,64}$/.test(e)?Ve(e):null}},{"room.send":({d:t,to:e})=>g?.send({t:"msg",d:t,to:e}),"room.presence":({d:t})=>g?.send({t:"presence",d:t}),"room.hideLobby":()=>{},"lobby.press":()=>u.pressTarget(),"lobby.target":t=>u.setTarget(t?.ok===!0,t?.hover===!0),"room.state":({k:t,v:e,w:o})=>g?.send({t:"state",k:t,v:e,...typeof o=="number"&&Number.isSafeInteger(o)&&o>0&&o<=2147483647?{w:o}:{}}),"room.team":({id:t,team:e})=>g?.send({t:"team",id:String(t),team:Number(e)}),"room.open":({open:t})=>g?.send({t:"open",open:t===!0}),"room.result":({result:t})=>g?.send({t:"result",result:t}),"room.kick":({id:t})=>g?.send({t:"kick",id:String(t)}),"room.votekick":({id:t})=>g?.send({t:"votekick",id:String(t)}),"room.ready":({ready:t})=>{Ft(),g?.send({t:"ready",ready:t===!0}),u.setReadyLocal(t===!0)},"room.unready":()=>{g?.send({t:"unready"}),u.handle({t:"unready"})},"room.transfer":({id:t})=>g?.send({t:"transfer",id:String(t)}),"room.start":({countdown:t,open:e})=>{Ft(),g?.send({t:"start",...Number.isFinite(t)?{countdown:Number(t)}:{},...e===!0?{open:!0}:{}})},"room.end":()=>g?.send({t:"end"}),"room.pause":({paused:t})=>g?.send({t:"pause",paused:t===!0}),"room.idle":({idle:t})=>g?.send({t:"idle",idle:t===!0}),"room.private":({k:t,v:e,id:o})=>typeof t=="string"&&g?.send({t:"private",k:t,v:e,...typeof o=="string"?{id:o}:{}}),"room.datareset":()=>g?.send({t:"datareset"}),"room.admit":({ids:t})=>g?.send({t:"admit",ids:Array.isArray(t)?t.filter(e=>typeof e=="string").slice(0,50):[]}),alive:()=>{R.lastAlive=Date.now()},stats:()=>{},hotkey:({key:t})=>{t==="Enter"&&u.pressKey()},vibrate:()=>{},input:t=>Ne(t?.touch===!0,!0),error:t=>{R.errors.length<20&&R.errors.push(String(t?.message??t).slice(0,300))},"input.first":()=>{},console:()=>{},debug:()=>{}},()=>{R.hellos++,Bt(),xe(),G.className="ow-hud ow-pos-top-left",C.setLayout(null),qt(null),w.emit("input",{touch:C.touch}),F.resend()},{demo:I!==null}),Oe=null;function _o(t){return Oe??=new Promise(e=>{w.emit("pause",null);let o=z("div","ow-name ow-demo-end"),r=z("div","ow-name-form ow-demo-box"),a=z("h2");a.textContent="End of demo";let n=z("p","ow-demo-name");n.textContent=X.game.name;let i=z("button","ow-btn ow-btn-primary");i.type="button",i.textContent=t?"Buy":"Favorite",i.addEventListener("click",()=>U(t?"On onceworlds.com, Buy opens the game\u2019s store page.":"On onceworlds.com, Favorite follows the game."));let s=z("button","ow-text-btn ow-name-login");s.type="button",s.textContent="Back to game",s.addEventListener("click",()=>{o.remove(),Oe=null,w.emit("resume",null),y.focus(),e(!0)}),r.append(a,n,i,s),o.append(r),q.append(o),i.focus()}),Oe}function qt(t){let{look:e}=wt(t);u.setLook(Et(e)),C.setLook(Pt(e))}function oo(){let t=y.getBoundingClientRect();if(!t.width||!t.height)return null;let{stick:e,buttons:o}=C.reservedBoxes(),r=Ie.getBoundingClientRect(),a=parseFloat(getComputedStyle(G).paddingTop)||0,n=r.width&&r.height?{left:r.left-a,top:r.top-a,width:r.width+2*a,height:r.height+2*a}:null;return Y(t,[{kind:"menu",box:G.hidden?null:n},{kind:"lobby",box:u.reservedBox()},{kind:"stick",box:e},{kind:"buttons",box:o}])}for(let t of["resize","orientationchange"])addEventListener(t,()=>F.changed());typeof ResizeObserver=="function"&&new ResizeObserver(()=>F.changed()).observe(y);function jo(t){return t.slice(0,t.lastIndexOf(":"))}function Io(t,e){let o=(e.teams??0)>=2?e.teams:0,r=Math.min(P.roomMaxPlayersCap,Math.max(2,e.maxPlayers??16)),a=Xe(e.minPlayers,r,ee);return jo(t)===`pub:${ke({mode:e.mode||"default",max:r,teams:o,ranked:e.ranked===!0,min:a})}`}function Bo(){let t="abcdefghijklmnopqrstuvwxyz0123456789";return Array.from(crypto.getRandomValues(new Uint8Array(12)),e=>t[e%t.length]).join("")}function No(t){let{name:e,maxPlayers:o,minPlayers:r,countdown:a,mode:n,teams:i,ranked:s}=t,d=t.minPlayersPrivate??r;if(e)return{name:e,maxPlayers:o,minPlayers:d,countdown:a,teams:i};if(t.private&&!M){M=Bo(),Tt(Z,M);let c=new URL(location.href);c.searchParams.set("server",M),history.replaceState(null,"",c.href)}return M?{server:M,maxPlayers:o,minPlayers:d,countdown:a,teams:i,private:t.private}:{mode:n,maxPlayers:o,minPlayers:r,countdown:a,teams:i,ranked:s}}async function Kt(t){let e=new ge(Z,t,{onMessage:a=>e===g&&Go(a),onClose:a=>e===g&&Uo(a),onConnection:a=>{e===g&&(a||w.emit("room.connection",{connected:!1}))}});g=e;let o=await e.join();if(e!==g)throw new Error("Left the server while joining");let r=o.room.startsWith("private:")?{...o,invite:Q()}:o;return be=o.you,_=o.match??null,H=o.room,R.joins++,je=Je(o.room)?.max??Math.min(t.maxPlayers??P.roomMaxPlayersDefault,P.roomMaxPlayersCap),u.enable(B,{ownCountdown:we}),u.setRoom(r,je),r}function Go(t){if(t.t==="update"||t.t==="move")return;if(t.t==="datareset"){U("This server\u2019s world was started over."),y.src=y.src;return}t.t==="chat"&&(t.entry.to||t.entry.channel)||t.t==="channel"||w.emit("room",t),t.t!=="welcome"&&u.handle(t),t.t==="welcome"?(u.setRoom(t,je),_=t.match??null):t.t==="match"?(t.match.phase!=="lobby"&&t.match.phase!==_?.phase&&to(),_=t.match):t.t==="error"&&t.code==="cooldown"&&(U(t.message),u.setReadyLocal(!1),w.emit("room",{t:"ready",id:be,ready:!1}))}function Uo(t){g=null,H=null,_=null,R.closed=t,u.setRoom(null),U(t==="replaced"?"You opened this game in another tab, so multiplayer moved there.":t==="kicked"?"You were removed from the server.":"Disconnected from the server."),w.emit("room.closed",{reason:t})}function xe(){g&&(g.close(),g=null,H=null,_=null,u.setRoom(null))}window.__owLocal={get you(){return be},get room(){return H},get match(){return _},get lobby(){return B},get ownCountdown(){return we},get hellos(){return R.hellos},get joins(){return R.joins},get errors(){return R.errors},get lastAlive(){return R.lastAlive},get closed(){return R.closed},get reserved(){return oo()},ready(t){return g?(eo(t),!0):!1},start(t){return g?(g.send({t:"start",...Number.isFinite(t)?{countdown:Number(t)}:{}}),!0):!1},chrome(t){q.style.visibility=t?"":"hidden"}};y.src=`${X.gameOrigin}/${Lo()}`;})();
|