1// The UI switch: yesterday's arcade, on demand. 2// 3// The Dark Minimal redesign changed two things a player notices before they 4// notice anything else â the palette (near-black and WEBCADE yellow, where it 5// had been near-black and a purple-to-blue gradient) and the voice (Oswald, 6// condensed and shouted, where it had been Inter, and a handful of labels 7// renamed). Some people preferred the old one. This lets them have it back 8// without the site keeping two of everything. 9// 10// WHAT THE SWITCH DOES NOT DO IS THE POINT OF IT. It repaints and it re-words; 11// it never moves anything. The redesign also restructured pages â a sidebar 12// came off the arcade floor, the front door became a homepage, the board grew 13// tabs â and none of that comes back, because a toggle that rearranges the page 14// under someone is not a preference, it is a second product. So: 15// 16// the skin (style.css, `html[data-ui="legacy"]`) sets colour, type face, 17// casing and radius, and touches NO box property â no display, 18// position, width, height, margin, padding, gap, grid, flex, or 19// font-size. Every element keeps the box it had. 20// the wording (legacytext.js) swaps the strings that were renamed and have 21// an element to sit in today. Copy belonging to markup that no 22// longer exists is not resurrected. 23// 24// THIS FILE IS BLOCKING, IN THE HEAD, AND STAYS SMALL FOR THAT REASON. The 25// attribute has to be on <html> before the first paint or a legacy player gets 26// a yellow flash of the current design on every navigation, which is worse than 27// not offering the switch. Everything that can wait â the wording pass, the 28// switch's own markup â waits in a deferred file. server.js injects both into 29// every page rather than thirty-five files carrying two more script tags. 30(() => { 31 const KEY = 'webcade-ui'; 32 const LEGACY = 'legacy'; 33 const root = document.documentElement; 34 35 // A URL can ask too: /arcade?ui=legacy and ?ui=new. It is how the browser 36 // test drives this, and it is the link you send somebody who says "it looked 37 // better yesterday" â one URL, no instructions. The choice it makes is 38 // stored, so it survives the next navigation without the query string. 39 let asked = null; 40 try { 41 const q = new URLSearchParams(location.search).get('ui'); 42 if (q === LEGACY) asked = true; 43 else if (q === 'new' || q === 'current') asked = false; 44 } catch (_) { /* no URL API: fall through to the stored answer */ } 45 46 let stored = null; 47 // Private browsing throws on localStorage rather than returning null, and a 48 // theme preference is not worth a broken page in the head of every document. 49 try { stored = localStorage.getItem(KEY); } catch (_) {} 50 51 const subs = []; 52 const api = { 53 get legacy() { return root.dataset.ui === LEGACY; }, 54 set(on) { 55 on = !!on; 56 if (on) root.dataset.ui = LEGACY; 57 else delete root.dataset.ui; 58 try { 59 if (on) localStorage.setItem(KEY, LEGACY); 60 else localStorage.removeItem(KEY); 61 } catch (_) {} 62 // One listener throwing must not stop the others: the wording pass and 63 // the switch's own checked state are separate subscribers, and a page 64 // where the colours changed and the switch did not is a confusing page. 65 for (const fn of subs) { try { fn(on); } catch (_) {} } 66 }, 67 toggle() { api.set(!api.legacy); }, 68 // Called immediately with the current state, so a subscriber never has to 69 // ask AND subscribe to get itself into the right shape. 70 onChange(fn) { subs.push(fn); try { fn(api.legacy); } catch (_) {} }, 71 }; 72 73 if (asked === null ? stored === LEGACY : asked) root.dataset.ui = LEGACY; 74 if (asked !== null) api.set(asked); 75 76 window.WEBCADE_UI = api; 77})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.