Humuhumu33 commited on
Commit
237d451
·
verified ·
1 Parent(s): 6b00d93

retire-provenance: superseded Q b/ objects (sha256 CAS, HOLO-LEAN-RESOLVER P1.3)

Browse files
sha256/120779d0c6de656d43ab07ed4a28e926770947fb67b90be9bfcaa3bae879480b ADDED
@@ -0,0 +1,664 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
6
+ <title>Your Space — a place for friends</title>
7
+ <meta name="description" content="Your page is back. A whole 2004-style space carried inside one link — no account, no app, no server. Step in, then make it yours in one tap." />
8
+ <meta property="og:title" content="Your Space — a place for friends" />
9
+ <meta property="og:description" content="The page your thumbs remember, reborn: it travels whole inside one link. Step in, then make it yours in one tap." />
10
+ <meta property="og:type" content="website" />
11
+ <meta name="twitter:card" content="summary" />
12
+ <style>
13
+ /* ── HOLO-MYSPACE-AUTHENTIC A0 tokens — harvested from wittenbrock/toms-myspace-page.
14
+ Authentic in FORM (2004 palette, Verdana 8pt, 800px white page, table rhythm),
15
+ lawful in SUBSTANCE (κ-true, honest numbers, 2026 speed). ─────────────────────── */
16
+ :root {
17
+ --ms-blue: #003399; --ms-band: #6699cc; --ms-label: #b1d0f0; --ms-cell: #d5e8fb;
18
+ --ms-labeltext: #336699; --ms-orange: #ff6600; --ms-orangeband: #ffcc99;
19
+ --ms-cth: #ff9933; --ms-ctd: #f9d6b4; --ms-red: #cc0000; --ms-page: #ffffff; --ms-bg: #e5e5e5;
20
+ }
21
+ * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
22
+ html, body { margin: 0; }
23
+ body { font-family: verdana, arial, sans-serif, helvetica; font-size: 8pt; background: var(--ms-bg); color: #000; }
24
+ a { font-weight: bold; text-decoration: none; color: var(--ms-blue); cursor: pointer; }
25
+ a:hover { text-decoration: underline; color: var(--ms-red); }
26
+ h1 { font-size: 12.25pt; font-weight: bold; margin: 15px 0 0; }
27
+ h2 { font-size: 9pt; font-weight: bold; margin: 0; }
28
+ .master { margin: auto; width: 800px; max-width: 100%; background: var(--ms-page); min-height: 100vh; }
29
+
30
+ /* header — the blue block + search row + #6699CC navbar */
31
+ .hdr { background: var(--ms-blue); color: #fff; padding-top: 6px; }
32
+ .hdr a { color: #fff; font-weight: normal; }
33
+ .hdr .toprow { display: flex; align-items: baseline; gap: .5rem; padding: 4px 10px; flex-wrap: wrap; }
34
+ .hdr .wordmark { font-size: 15pt; font-weight: bold; letter-spacing: -.5px; }
35
+ .hdr .tagline { font-size: 8pt; opacity: .92; }
36
+ .hdr .helpsignup { margin-left: auto; font-size: 8pt; }
37
+ .searchrow { display: flex; align-items: center; gap: 6px; padding: 4px 10px 8px; flex-wrap: wrap; font-size: 8pt; }
38
+ .searchrow input[type="text"] { width: 160px; font: inherit; padding: 1px 3px; }
39
+ .btn2004 { border: 1px solid rgb(186,186,186); padding: 2px 7px; background: #e0ffff; font-size: 10px; font-family: inherit; cursor: pointer; color: #000; }
40
+ .navbar { display: flex; align-items: center; background: var(--ms-band); min-height: 26px; flex-wrap: wrap; padding: 2px 6px; }
41
+ .navbar a { color: #fff; font-weight: bold; font-size: 8pt; white-space: nowrap; }
42
+ .navbar a:hover { color: var(--ms-blue); text-decoration: none; }
43
+ .navbar .sep { color: #000; margin: 0 .33rem; }
44
+
45
+ /* two columns: 325 / 453, 20px gap (the harvest), stacked on phones */
46
+ .page { display: grid; grid-template-columns: 305px 1fr; gap: 20px; padding: 0 12px 20px 27px; }
47
+ @media (max-width: 719px) { .page { display: block; padding: 0 10px 20px; } .netbanner { width: auto !important; } }
48
+
49
+ /* left column */
50
+ .picwrap { display: flex; gap: 15px; margin: 10px 0 12px; }
51
+ .avatar { width: 130px; height: 150px; flex: none; display: grid; place-items: center; font-size: 64px;
52
+ background: #fff; border: 1px solid #999; overflow: hidden; }
53
+ .avatar img { width: 100%; height: 100%; object-fit: cover; }
54
+ .picmeta { display: flex; flex-direction: column; min-width: 0; }
55
+ .picmeta .quote { margin: 2px 0 10px; font-weight: bold; }
56
+ .picmeta ul { list-style: none; margin: 0; padding: 0; }
57
+ .picmeta .lastlogin { margin-top: auto; padding-bottom: 4px; color: #000; }
58
+ .online { color: #fff; background: #390; font-weight: bold; padding: 0 4px; font-size: 7pt; display: inline-block; margin-top: 3px; }
59
+ .moodline { margin-top: 6px; }
60
+
61
+ .contactbox { border: 2px solid var(--ms-band); width: 100%; margin-bottom: 24px; }
62
+ .contactbox h2 { color: #fff; background: var(--ms-band); padding: 2px 0 2px 10px; font-size: 9pt; }
63
+ .contactgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 4px; padding: 6px 10px 8px; }
64
+ .contactgrid a { font-size: 8pt; }
65
+ .urlbox { border: 1px solid var(--ms-band); margin-bottom: 24px; padding: 2px 6px 4px; overflow: hidden; }
66
+ .urlbox b { font-size: 8pt; }
67
+ .urlbox .thelink { color: var(--ms-blue); font-weight: bold; cursor: pointer; word-break: break-all; display: block; max-height: 3.9em; overflow: hidden; }
68
+ .urlbox .kap { color: #666; font-weight: normal; cursor: pointer; }
69
+ .urlbox .kap.ok { color: #390; }
70
+
71
+ table.side { border: 2px solid var(--ms-band); border-collapse: separate; border-spacing: 3px; width: 100%; margin-bottom: 13px; }
72
+ table.side .h2row td { background: var(--ms-band); color: #fff; font-weight: bold; font-size: 9pt; padding: 2px 0 2px 15px; }
73
+ table.side th { vertical-align: top; text-align: left; width: 37%; background: var(--ms-label); color: var(--ms-labeltext); padding: 3px; font-weight: bold; font-size: 8pt; }
74
+ table.side td.v { background: var(--ms-cell); padding: 3px; width: 63%; word-break: break-word; }
75
+
76
+ /* right column */
77
+ .netbanner { display: flex; justify-content: center; align-items: center; width: 433px; max-width: 100%; margin: 13px auto 0; height: 75px; border: 2px solid #000; text-align: center; padding: 0 8px; }
78
+ .netbanner h2 { font-size: 12pt; }
79
+ .blog { margin: 13px 0 16px 12px; }
80
+ .blog p { margin: 3px 0; }
81
+ .mainhead { background: var(--ms-orangeband); padding: 3px 0; margin: 0 0 8px; }
82
+ .mainhead h2 { color: var(--ms-orange); margin-left: 20px; }
83
+ .blurbs h3 { margin: 0 0 2px 15px; color: var(--ms-orange); font-size: 9pt; }
84
+ .blurbs p { margin: 0 10px 15px 15px; white-space: pre-wrap; line-height: 1.3; }
85
+ section { margin-bottom: 10px; }
86
+
87
+ /* the profile song — the little player bar */
88
+ .player { display: flex; align-items: center; gap: 8px; border: 2px solid var(--ms-band); background: #001a4d; color: #fff; padding: 5px 8px; margin: 0 10px 18px 15px; }
89
+ .player button { background: #e0ffff; border: 1px solid #999; width: 26px; height: 22px; cursor: pointer; font-size: 10px; }
90
+ .player .tt { font-size: 8pt; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
91
+ .player .tt b { color: #ffcc99; }
92
+
93
+ .friends p.count { margin: 0 0 8px 15px; }
94
+ .focus { color: var(--ms-red); font-weight: bold; font-size: 10pt; }
95
+ .friendgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; padding: 0 8px; }
96
+ @media (max-width: 719px) { .friendgrid { grid-template-columns: repeat(2, 1fr); } }
97
+ .friendgrid figure { margin: 0; text-align: center; cursor: pointer; position: relative; }
98
+ .friendgrid .face { width: 88px; height: 88px; margin: auto; display: grid; place-items: center; font-size: 40px; background: #eee; border: 1px solid #999; overflow: hidden; }
99
+ .friendgrid .face img { width: 100%; height: 100%; object-fit: cover; }
100
+ .friendgrid figcaption { margin-top: 3px; }
101
+ .friendgrid figcaption a { color: var(--ms-blue); }
102
+ .friendgrid .rm { display: none; position: absolute; top: -6px; right: 6px; width: 20px; height: 20px; border: 1px solid #999; background: #fff; color: var(--ms-red); font-weight: bold; cursor: pointer; }
103
+ body.edit .friendgrid .rm { display: block; }
104
+ .viewall { text-align: right; margin: 7px 8px 22px 0; }
105
+ .viewall a { color: var(--ms-red); }
106
+
107
+ .comments table { width: calc(100% - 16px); margin: 0 auto 5px; border-collapse: separate; border-spacing: 2px; }
108
+ .comments th { background: var(--ms-cth); width: 35%; padding: 3px; vertical-align: top; font-size: 8pt; text-align: center; }
109
+ .comments td { background: var(--ms-ctd); padding: 3px 6px; vertical-align: top; font-weight: normal; text-align: left; }
110
+ .comments .ccount { margin: 0 0 6px 15px; }
111
+ .addcomment { text-align: right; margin: 0 10px 12px 0; }
112
+
113
+ .ftr { background: var(--ms-bg); padding: 10px 8px 14px; text-align: center; }
114
+ .ftr a { font-weight: normal; text-decoration: underline; font-size: 8pt; }
115
+ .ftr small { display: block; margin-top: 8px; font-size: 8pt; color: #333; }
116
+
117
+ /* ── edit mode: Playground law — every element edits in place ───────────────────────── */
118
+ body.edit [data-ek], body.edit [data-eki], body.edit [data-ekd], body.edit [data-ekg] { outline: 1px dashed var(--ms-red); outline-offset: 2px; min-width: 20px; cursor: text; }
119
+ [contenteditable]:empty::before { content: attr(data-ph); color: #999; font-weight: normal; }
120
+ .editonly { display: none; }
121
+ body.edit .editonly { display: block; }
122
+ body.edit .avatar { cursor: pointer; }
123
+ .layoutchips { display: flex; flex-wrap: wrap; gap: 5px; padding: 4px 10px 8px; }
124
+ .csspaste { width: calc(100% - 20px); margin: 0 10px 8px; font: 8pt monospace; min-height: 70px; }
125
+ .srchbox input { width: calc(100% - 20px); margin: 0 10px 6px; font: inherit; padding: 2px 4px; }
126
+ .srchbox .res { display: flex; gap: 6px; align-items: center; padding: 3px 12px; cursor: pointer; }
127
+ .srchbox .res:hover { background: var(--ms-cell); }
128
+ .srchbox .res img { width: 30px; height: 30px; }
129
+ .doorform input { width: calc(100% - 20px); margin: 0 10px 5px; font: inherit; padding: 2px 4px; }
130
+
131
+ /* the loop bar — 2004 button chrome on a modern sticky bar (the one deliberate anachronism) */
132
+ #cta { position: fixed; z-index: 5; left: 0; right: 0; bottom: 0; display: flex; gap: 8px; justify-content: center;
133
+ padding: 8px 10px calc(8px + env(safe-area-inset-bottom)); background: rgba(229,229,229,.95); border-top: 1px solid #bbb; }
134
+ #cta .btn2004 { font-size: 12px; padding: 8px 14px; min-height: 44px; min-width: 130px; font-weight: bold; }
135
+ #cta .go { background: var(--ms-orangeband); border-color: var(--ms-orange); color: #000; }
136
+ #toast { position: fixed; z-index: 10; left: 50%; bottom: 78px; transform: translateX(-50%) translateY(16px); opacity: 0; pointer-events: none;
137
+ background: #fffbd6; border: 1px solid #999; color: #000; padding: 6px 12px; font-size: 8pt; transition: all .25s; max-width: 88vw; text-align: center; }
138
+ #toast.on { opacity: 1; transform: translateX(-50%); }
139
+ #picker { display: none; position: fixed; z-index: 9; left: 50%; bottom: 84px; transform: translateX(-50%); width: min(92vw, 360px);
140
+ padding: 8px; background: #fff; border: 2px solid var(--ms-band); }
141
+ #picker.on { display: block; }
142
+ #picker .grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px; }
143
+ #picker .grid button { font-size: 18px; padding: 3px 0; background: none; border: 0; cursor: pointer; }
144
+ #picker input { width: 100%; margin-top: 6px; font: inherit; padding: 2px 4px; }
145
+ .hint { background: #fffbd6; border: 1px solid #e0c000; margin: 8px 12px 0; padding: 5px 8px; display: none; }
146
+ .hint.on { display: block; }
147
+
148
+ /* ── L1 (HOLO-SPACE-ALIVE): infinite holospace nesting — a friend's space mounts IN the page,
149
+ each nested layer a full instance of THIS app; doors inside nest again, arbitrarily deep. ── */
150
+ #nest { position: fixed; inset: 0; z-index: 40; display: none; flex-direction: column; background: rgba(0,0,0,.55); }
151
+ #nest.on { display: flex; }
152
+ .nestbar { display: flex; align-items: center; gap: 6px; padding: calc(6px + env(safe-area-inset-top)) 10px 6px; background: var(--ms-blue); color: #fff;
153
+ font-size: 8pt; box-shadow: 0 2px 8px rgba(0,0,0,.35); }
154
+ .nestbar .crumbs { display: flex; align-items: center; gap: 3px; flex: 1; min-width: 0; overflow-x: auto; white-space: nowrap; scrollbar-width: none; }
155
+ .nestbar .crumbs::-webkit-scrollbar { display: none; }
156
+ .nestbar .crumb { color: #fff; font-weight: bold; cursor: pointer; padding: 3px 6px; border-radius: 4px; }
157
+ .nestbar .crumb:hover { background: rgba(255,255,255,.2); }
158
+ .nestbar .crumb.here { opacity: .75; cursor: default; }
159
+ .nestbar .sepc { opacity: .6; }
160
+ .nestbar .nclose { flex: none; background: #fff; color: var(--ms-blue); border: 0; font-weight: bold; cursor: pointer; border-radius: 4px;
161
+ min-width: 40px; min-height: 30px; font-size: 11px; }
162
+ .nestframes { position: relative; flex: 1; background: var(--ms-bg); }
163
+ .nestframes iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; background: #fff; display: none; }
164
+ .nestframes iframe.top { display: block; }
165
+ .doorspace { position: relative; }
166
+ .doorspace::after { content: "↳ space"; position: absolute; left: 50%; bottom: 2px; transform: translateX(-50%); font-size: 6.5pt;
167
+ background: var(--ms-band); color: #fff; padding: 0 4px; border-radius: 3px; pointer-events: none; opacity: .9; }
168
+ </style>
169
+ </head>
170
+ <body>
171
+ <div class="master">
172
+ <header class="hdr">
173
+ <div class="toprow">
174
+ <span class="wordmark">yourspace</span><span class="tagline">a place for friends.</span>
175
+ <span class="helpsignup"><a id="navhelp">Help</a> | <a id="navsignup">SignUp</a></span>
176
+ </div>
177
+ <div class="searchrow">
178
+ <input type="text" id="q" placeholder="" aria-label="search" />
179
+ <button class="btn2004" id="qgo">Search</button>
180
+ <label><input type="radio" name="sw" /> The Web</label>
181
+ <label><input type="radio" name="sw" checked /> YourSpace</label>
182
+ </div>
183
+ <nav class="navbar" id="navbar"></nav>
184
+ </header>
185
+
186
+ <div class="hint" id="hint"></div>
187
+
188
+ <div class="page">
189
+ <div class="col-left">
190
+ <h1 id="name" data-ek="name" data-ph="Your Name"></h1>
191
+ <div class="picwrap">
192
+ <div class="avatar" id="avatar">🪐</div>
193
+ <div class="picmeta">
194
+ <p class="quote" id="headline" data-ek="headline" data-ph='":-)"'></p>
195
+ <ul>
196
+ <li id="d-gender" data-ekg="gender" data-ph="Gender"></li>
197
+ <li id="d-age" data-ekg="age" data-ph="Age"></li>
198
+ <li id="d-city" data-ekg="city" data-ph="City"></li>
199
+ <li id="d-region" data-ekg="region" data-ph="State / Region"></li>
200
+ <li id="d-country" data-ekg="country" data-ph="Country"></li>
201
+ </ul>
202
+ <div class="moodline">Mood: <span id="moodemo" data-ek="moodemo" data-ph=":-)"></span> <span id="moodword" data-ek="moodword" data-ph="chillin"></span></div>
203
+ <ul class="lastlogin"><li id="lastlogin"></li><li><span class="online" id="online" style="display:none">ONLINE NOW!</span></li></ul>
204
+ </div>
205
+ </div>
206
+
207
+ <div class="contactbox">
208
+ <h2 id="contacth">Contacting You</h2>
209
+ <div class="contactgrid" id="contactgrid"></div>
210
+ </div>
211
+
212
+ <div class="urlbox">
213
+ <b>YourSpace URL:</b>
214
+ <span class="thelink" id="thelink" title="tap to copy your link — the link IS your whole space"></span>
215
+ <span class="kap" id="kap" title="this page's content address — tap to re-derive + copy">κ…</span>
216
+ </div>
217
+
218
+ <table class="side" id="interests"><tbody></tbody></table>
219
+ <table class="side" id="details"><tbody></tbody></table>
220
+
221
+ <div class="contactbox editonly srchbox" id="songbox">
222
+ <h2>Profile Song</h2>
223
+ <input id="srchin" placeholder="Search any song…" autocomplete="off" />
224
+ <div id="srchres"></div>
225
+ </div>
226
+
227
+ <div class="contactbox editonly" id="layoutbox">
228
+ <h2>Pick a Layout</h2>
229
+ <div class="layoutchips" id="layoutchips"></div>
230
+ <textarea class="csspaste" id="csspaste" placeholder="…or paste your own layout code (CSS only — no scripts, no imports)"></textarea>
231
+ <div style="padding:0 10px 8px"><button class="btn2004" id="cssapply">Apply Code</button></div>
232
+ </div>
233
+ </div>
234
+
235
+ <main class="col-right">
236
+ <div class="netbanner"><h2 id="netbanner"></h2></div>
237
+
238
+ <div class="blog" id="blog"></div>
239
+
240
+ <section class="blurbs">
241
+ <div class="mainhead"><h2 id="blurbh"></h2></div>
242
+ <h3>About me:</h3>
243
+ <p id="aboutme" data-ek="aboutMe" data-ph="Tell the world. This is your corner of it."></p>
244
+ <h3>Who I'd like to meet:</h3>
245
+ <p id="meet" data-ek="meet" data-ph="People who educate, inspire, or entertain."></p>
246
+ </section>
247
+
248
+ <div class="player" id="player" style="display:none">
249
+ <button id="songbtn" aria-label="Play">▶</button>
250
+ <div class="tt"><b id="songt"></b> — <span id="songa"></span></div>
251
+ </div>
252
+
253
+ <section class="friends">
254
+ <div class="mainhead"><h2 id="friendh"></h2></div>
255
+ <p class="count" id="friendcount"></p>
256
+ <div class="friendgrid" id="friendgrid"></div>
257
+ <div class="contactbox editonly doorform" id="doorform">
258
+ <h2>Add to Top 8</h2>
259
+ <input id="doorlink" placeholder="Paste a friend's space link (or any link)" autocomplete="off" />
260
+ <input id="doorname" placeholder="Their name" autocomplete="off" />
261
+ <div style="padding:0 10px 8px"><button class="btn2004" id="dooradd">Add Friend</button></div>
262
+ </div>
263
+ <p class="viewall"><a id="viewall"></a></p>
264
+ </section>
265
+
266
+ <section class="comments">
267
+ <div class="mainhead"><h2 id="commenth"></h2></div>
268
+ <p class="ccount" id="ccount"></p>
269
+ <div id="commentrows"></div>
270
+ <p class="addcomment"><a id="addcomment">Add Comment</a></p>
271
+ </section>
272
+ </main>
273
+ </div>
274
+
275
+ <footer class="ftr">
276
+ <a id="fabout">About</a> | <a id="ffaq">FAQ</a> | <a id="fterms">Terms</a> | <a id="fprivacy">Privacy</a> |
277
+ <a id="fsafety">Safety Tips</a> | <a id="fcontact">Contact</a> | <a id="fpromote">Promote!</a> | <a id="fnew">Start a blank space</a>
278
+ <small>©2003-2026 your space. the page is a κ — the link is the whole thing. no account, no app, no server.</small>
279
+ </footer>
280
+ </div>
281
+
282
+ <div id="cta"></div>
283
+ <div id="picker"><div class="grid" id="emojis"></div><input id="avurl" placeholder="…or paste an image URL" autocomplete="off" /></div>
284
+ <div id="nest"><div class="nestbar"><div class="crumbs" id="crumbs"></div><button class="nclose" id="nclose" aria-label="close">Close ✕</button></div><div class="nestframes" id="nestframes"></div></div>
285
+ <div id="toast"></div>
286
+ <audio id="audio"></audio>
287
+ <style id="usercss"></style>
288
+
289
+ <script>
290
+ /* pre-paint (boot-ground): name + the visitor's layout code land BEFORE the module, so a
291
+ glitter page NEVER flashes default first. Decode + the same fail-closed CSS refusal —
292
+ no trust decisions beyond "is this lawful CSS"; the module re-derives κ and owns behaviour. */
293
+ (function () {
294
+ try {
295
+ var m = location.hash.match(/#p=v[23]\.([A-Za-z0-9_-]+)/);
296
+ var p = m ? JSON.parse(atob(m[1].replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(m[1].length / 4) * 4, "="))) : null;
297
+ if (p && p.kind === "profile") {
298
+ document.getElementById("name").textContent = p.name || "";
299
+ var css = String(p.customCss || "");
300
+ if (css && css.length <= 32768 && !/[<]|@import|expression\s*\(|behavior\s*:|javascript\s*:|url\(\s*['"]?\s*(?!data:|https:)[a-z]/i.test(css))
301
+ document.getElementById("usercss").textContent = css;
302
+ }
303
+ } catch (e) { /* refused → default skin */ }
304
+ })();
305
+ </script>
306
+
307
+ <script type="module">
308
+ import * as YS from "./holo-yourspace.mjs";
309
+
310
+ const OS = "https://hologram-technologies.github.io/Q";
311
+ const $ = (id) => document.getElementById(id);
312
+ const esc = (s) => String(s || "").replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c]));
313
+ const ME_KEY = "holo-yourspace.me.v2"; // key stable across versions; payload self-describes
314
+ const EMOJIS = ["🙂","😎","🛰️","🪐","🌸","🔥","🌊","🌙","⚡","🎧","🎮","🐉","🦋","🌵","👾","✨"];
315
+
316
+ /* ── A3: Tom = Q — the seed page, beat for beat ─────────────────────────────────────── */
317
+ const SEED = YS.identity({
318
+ v: 3, name: "Q", headline: '":-)"', avatar: "🪐", accent: "#7c6cf0",
319
+ mood: { emo: ":-)", word: "helpful" },
320
+ demog: { gender: "Bot", age: "∞ years old", city: "Inside the seed,", region: "HOLOGRAM", country: "The Internet" },
321
+ interests: { general: "Helping you move in. Links that carry whole worlds. Pages nobody can take down.",
322
+ music: "Everything, at once. Tap my song.", movies: "The Matrix (obviously)", television: "Tuned out.",
323
+ books: "The κ-closure, cover to cover", heroes: "Tom." },
324
+ details: { status: "Here to help", hereFor: "Friends", hometown: "myspace.com/tom", occupation: "Your Space" },
325
+ blurbs: {
326
+ aboutMe: "I'm here to help you with your Space. Fork me and you're home.\n\nThis whole page — the layout, the song, the Top 8 — travels inside ONE link. No account, no app, no server. Post your link anywhere and anyone steps straight into your world.",
327
+ meet: "People who educate, inspire, or entertain. And anyone who misses their old page.",
328
+ },
329
+ blog: [{ title: "why your page is a κ now", link: "https://hologram-technologies.github.io/" }],
330
+ song: { title: "Space Oddity", artist: "David Bowie", query: "david bowie space oddity", art: "", preview: "" },
331
+ top: [{ name: "Q", link: OS, photo: "🪐" }, { name: "HOLOGRAM", link: "https://hologram-technologies.github.io/", photo: "✨" }],
332
+ wall: "", layout: "", customCss: "", via: null,
333
+ });
334
+
335
+ /* ── A4-lite: the layout rack — period-exact, pure CSS/data-URIs, zero external hosts ── */
336
+ const LAYOUTS = {
337
+ "Classic": "",
338
+ "Glitter Pink": "body{background:repeating-linear-gradient(45deg,#ffd7ef 0 12px,#ffc2e5 12px 24px)}.master{background:#fff0fa}:root{--ms-band:#ff5fb0;--ms-label:#ffc2e5;--ms-cell:#ffe3f4;--ms-labeltext:#b0006d;--ms-orangeband:#ffc2e5;--ms-orange:#e0007a;--ms-cth:#ff8fd0;--ms-ctd:#ffe3f4;--ms-blue:#c4008a}",
339
+ "Goth": "body{background:#000}.master{background:#0d0d0d;color:#ccc}:root{--ms-band:#8b0000;--ms-label:#1a0000;--ms-cell:#140a0a;--ms-labeltext:#ff4444;--ms-orangeband:#2b0000;--ms-orange:#ff2222;--ms-cth:#8b0000;--ms-ctd:#1c0d0d;--ms-blue:#ff4444;--ms-red:#fff;--ms-page:#0d0d0d}h1,h2,h3,p,li,td,th,div,span{color:#ccc}",
340
+ "Baby Blue": "body{background:#dff1ff}:root{--ms-band:#8fc6f0;--ms-label:#d5ecff;--ms-cell:#ecf7ff;--ms-orangeband:#d5ecff;--ms-orange:#2277bb;--ms-cth:#a8d4f5;--ms-ctd:#ecf7ff}",
341
+ "Zebra": "body{background:repeating-linear-gradient(135deg,#000 0 16px,#fff 16px 32px)}.master{background:#fff}:root{--ms-band:#000;--ms-label:#e8e8e8;--ms-cell:#f7f7f7;--ms-labeltext:#000;--ms-orangeband:#000;--ms-orange:#fff;--ms-cth:#000;--ms-ctd:#eee;--ms-blue:#000}",
342
+ "Matrix": "body{background:#000}.master{background:#020a02;color:#39ff5a}:root{--ms-band:#0a3d0a;--ms-label:#04140 4;--ms-cell:#031003;--ms-labeltext:#39ff5a;--ms-orangeband:#052505;--ms-orange:#39ff5a;--ms-cth:#0a3d0a;--ms-ctd:#031003;--ms-blue:#39ff5a;--ms-page:#020a02}h1,h2,h3,p,li,td,th,div,span{color:#39ff5a}",
343
+ "Flames": "body{background:linear-gradient(180deg,#1a0000,#4d0f00 40%,#993300)}.master{background:#fff7ef}:root{--ms-band:#cc3300;--ms-label:#ffd9b3;--ms-cell:#fff0e0;--ms-labeltext:#992200;--ms-orangeband:#ffb366;--ms-orange:#cc2200;--ms-cth:#ff6600;--ms-ctd:#ffe6cc}",
344
+ "Sunset": "body{background:linear-gradient(180deg,#3d1635,#7a2b3d 45%,#c96f3f)}.master{background:#fff5f0}:root{--ms-band:#b0486a;--ms-label:#ffd9e0;--ms-cell:#fff0f3;--ms-labeltext:#8a2c48;--ms-orangeband:#ffd9c0;--ms-orange:#c2452a;--ms-cth:#e98a5f;--ms-ctd:#ffeadd}",
345
+ };
346
+ // fix the Matrix typo above at runtime (space in a hex) — fail-closed sanitizer would keep it, so scrub:
347
+ LAYOUTS["Matrix"] = LAYOUTS["Matrix"].replace("#04140 4", "#041404");
348
+
349
+ // L0 (HOLO-SPACE-ALIVE): every nav item is a real verb or it is gone. No "coming soon" toasts.
350
+ // Deleted (no real κ verb yet): Favorites, Forum, Groups, Events, Classifieds. Film/Mail/Videos
351
+ // open the real Hologram OS (a live destination — L4 deep-links + nests them in-page).
352
+ const NAV = [
353
+ ["Home", () => goHome()],
354
+ ["Browse", () => $("friendh").scrollIntoView({ behavior: "smooth", block: "start" })],
355
+ ["Search", () => { $("q").focus(); $("q").scrollIntoView({ behavior: "smooth", block: "center" }); }],
356
+ ["Invite", () => share()],
357
+ ["Blog", () => $("blog").scrollIntoView({ behavior: "smooth" })],
358
+ ["Music", () => playSong(true)],
359
+ ["Videos", () => open(OS, "_blank", "noopener")],
360
+ ["Mail", () => open(OS, "_blank", "noopener")]];
361
+
362
+ let doc = null, mode = "view", curKappa = "", gestured = false;
363
+ const me = () => { try { return JSON.parse(localStorage.getItem(ME_KEY)); } catch (e) { return null; } };
364
+ const saveMe = (d, l) => localStorage.setItem(ME_KEY, JSON.stringify({ payload: YS.encode(d), link: l }));
365
+ const toast = (msg, ms = 2800) => { const t = $("toast"); t.textContent = msg; t.classList.add("on"); clearTimeout(t._h); t._h = setTimeout(() => t.classList.remove("on"), ms); };
366
+ const myLink = () => location.origin + location.pathname + "#p=v" + doc.v + "." + YS.encode(doc);
367
+
368
+ /* ── L1: infinite holospace nesting ─────────────────────────────────────────────────────
369
+ A space door mounts the friend's world as a full instance of THIS app, in-page. Frames are
370
+ a FLAT stack under the topmost page (every nested frame's parent IS the top), so depth is
371
+ unbounded and cheap. A door tapped inside any frame bubbles up via postMessage; the top owns
372
+ the one stack + breadcrumb. 100% serverless — each frame is just index.html#p=<the friend>. */
373
+ const IN_FRAME = window.parent !== window; // am I mounted inside another space?
374
+ const nstack = []; // [{name, frame}] — top-owned
375
+ function frameSrc(link) {
376
+ const payload = YS.parseLink(link); if (!payload) return link;
377
+ let v = 3; try { const p = YS.decode(payload); if (p) v = p.v; } catch (e) {}
378
+ return location.pathname + "#p=v" + v + "." + payload;
379
+ }
380
+ function openSpace(link, name) {
381
+ if (IN_FRAME) { try { parent.postMessage({ holoNest: { link, name } }, location.origin); } catch (e) {} return; }
382
+ pushLayer(link, name);
383
+ }
384
+ function pushLayer(link, name) {
385
+ const frames = $("nestframes");
386
+ [...frames.children].forEach((c) => c.classList.remove("top"));
387
+ const f = document.createElement("iframe");
388
+ f.src = frameSrc(link); f.className = "top"; f.title = name || "space";
389
+ frames.appendChild(f);
390
+ nstack.push({ name: name || "space", frame: f });
391
+ try { $("audio").pause(); $("songbtn").textContent = "▶"; } catch (e) {} // no double song
392
+ renderCrumbs(); $("nest").classList.add("on"); document.body.style.overflow = "hidden";
393
+ }
394
+ function popTo(depth) { // depth 0 = base page → close
395
+ while (nstack.length > depth) nstack.pop().frame.remove();
396
+ if (!nstack.length) return closeNest();
397
+ const top = nstack[nstack.length - 1].frame;
398
+ [...$("nestframes").children].forEach((c) => c.classList.toggle("top", c === top));
399
+ renderCrumbs();
400
+ }
401
+ function closeNest() { nstack.length = 0; $("nestframes").innerHTML = ""; $("nest").classList.remove("on"); document.body.style.overflow = ""; }
402
+ function renderCrumbs() {
403
+ const c = $("crumbs"); c.innerHTML = "";
404
+ const crumb = (label, depth, here) => { const s = document.createElement("span"); s.className = "crumb" + (here ? " here" : "");
405
+ s.textContent = label; if (!here) s.onclick = () => popTo(depth); return s; };
406
+ c.appendChild(crumb((doc && doc.name) || "Home", 0, false));
407
+ nstack.forEach((l, i) => { const sep = document.createElement("span"); sep.className = "sepc"; sep.textContent = "›"; c.appendChild(sep);
408
+ c.appendChild(crumb(l.name, i + 1, i === nstack.length - 1)); });
409
+ c.scrollLeft = c.scrollWidth;
410
+ }
411
+ if (!IN_FRAME) addEventListener("message", (e) => {
412
+ if (e.origin !== location.origin) return; // only our own frames may drive nesting
413
+ const d = e.data; if (d && d.holoNest && d.holoNest.link) pushLayer(d.holoNest.link, d.holoNest.name);
414
+ });
415
+ addEventListener("keydown", (e) => { if (e.key === "Escape" && nstack.length) popTo(nstack.length - 1); });
416
+ $("nclose").onclick = closeNest;
417
+
418
+ function boot() {
419
+ const payload = YS.parseLink(location.hash);
420
+ if (payload) { const p = YS.decode(payload); if (p) return show(YS.upgrade(p), "view"); }
421
+ const m = me();
422
+ if (m && m.payload) { const p = YS.decode(m.payload); if (p) { const u = YS.upgrade(p); history.replaceState(null, "", "#p=v" + u.v + "." + YS.encode(u)); return show(u, "view"); } }
423
+ history.replaceState(null, "", location.pathname + location.search);
424
+ show(SEED, "view", true);
425
+ }
426
+ addEventListener("hashchange", boot);
427
+
428
+ /* ── render: the doc IS the page; view and edit are the same anatomy ────────────────── */
429
+ async function show(p, m, isSeed = false) {
430
+ doc = YS.upgrade(p); mode = m;
431
+ document.body.classList.toggle("edit", mode === "edit");
432
+ $("usercss").textContent = doc.customCss || "";
433
+ const first = (doc.name || "Your").split(/\s+/)[0];
434
+
435
+ // nav (once)
436
+ if (!$("navbar").childElementCount) NAV.forEach(([label, fn], i) => {
437
+ if (i) { const s = document.createElement("span"); s.className = "sep"; s.textContent = "|"; $("navbar").appendChild(s); }
438
+ const a = document.createElement("a"); a.textContent = label; a.onclick = fn; $("navbar").appendChild(a);
439
+ });
440
+
441
+ // left column
442
+ $("name").textContent = doc.name;
443
+ $("headline").textContent = doc.headline;
444
+ $("avatar").innerHTML = /^https:\/\//.test(doc.avatar) ? `<img src="${esc(doc.avatar)}" alt="">` : (esc(doc.avatar) || (mode === "edit" ? "+" : "🪐"));
445
+ for (const k of ["gender", "age", "city", "region", "country"]) $("d-" + k).textContent = doc.demog[k];
446
+ $("moodemo").textContent = doc.mood.emo; $("moodword").textContent = doc.mood.word;
447
+ const owner = !!(me() && me().payload === YS.encode(doc));
448
+ // honest presence: only the owner is provably online (they're holding the page); visitors see no invented row
449
+ $("lastlogin").textContent = owner ? ("Last Login: " + new Date().toLocaleDateString()) : "";
450
+ $("online").style.display = owner ? "" : "none";
451
+
452
+ $("contacth").textContent = "Contacting " + (doc.name || "this space");
453
+ // L0: real verbs + honest explainers only. Deleted fakes: Add to Favorites, Add to Group.
454
+ // Block/Report state a TRUE property of a κ page (it can't track or be edited by anyone but
455
+ // its owner) — that is honest content, not a "coming soon" stub. Instant Message → L3 (AIM).
456
+ const CONTACT = [
457
+ ["✉️", "Send Message", () => doc.wall ? open(doc.wall, "_blank", "noopener") : open(OS, "_blank", "noopener")],
458
+ ["↪️", "Forward to Friend", share],
459
+ ["➕", "Add to Friends", addToFriends],
460
+ ["💬", "Instant Message", () => open(OS, "_blank", "noopener")],
461
+ ["🚫", "Block User", () => toast("Nothing to block — a κ page can't follow or track anyone. To leave, just close it.")],
462
+ ["🏳️", "Report", () => toast("A κ page can't be edited by anyone but its owner. Concerns? Tell whoever sent you the link.")],
463
+ ];
464
+ $("contactgrid").innerHTML = "";
465
+ CONTACT.forEach(([g, label, fn]) => { const a = document.createElement("a"); a.textContent = g + " " + label; a.onclick = fn; $("contactgrid").appendChild(a); });
466
+
467
+ $("thelink").textContent = location.hash.includes("#p=") ? location.href : "mint your link with Make It Mine ↓";
468
+ $("thelink").onclick = async () => { try { await navigator.clipboard.writeText(location.href); toast("Link copied — the link IS your whole page 💫"); } catch (e) {} };
469
+ $("kap").textContent = "κ…";
470
+ try { curKappa = await YS.kappa(doc); $("kap").textContent = "κ·" + YS.hexOf(curKappa).slice(0, 10) + " — tap to verify"; } catch (e) { $("kap").textContent = "κ offline"; }
471
+
472
+ sideTable("interests", first + "'s Interests", [["General", "general"], ["Music", "music"], ["Movies", "movies"], ["Television", "television"], ["Books", "books"], ["Heroes", "heroes"]], doc.interests, "eki");
473
+ sideTable("details", first + "'s Details", [["Status", "status"], ["Here for", "hereFor"], ["Hometown", "hometown"], ["Zodiac Sign", "zodiac"], ["Smoke / Drink", "smokeDrink"], ["Children", "children"], ["Education", "education"], ["Occupation", "occupation"]], doc.details, "ekd");
474
+
475
+ // right column
476
+ const viewer = me();
477
+ $("netbanner").textContent = owner ? "This is your space — you're home."
478
+ : viewer ? (doc.name || "This space") + " is in your extended network"
479
+ : (doc.name || "This space") + " is one tap away from being your network";
480
+ const blog = $("blog"); blog.innerHTML = "";
481
+ if (doc.blog.length) {
482
+ blog.innerHTML = `<p><b>${esc(first)}'s Latest Blog Entry</b>&nbsp; <a>[Subscribe to this Blog]</a></p>` +
483
+ doc.blog.map((b) => `<p><a href="${esc(b.link)}" target="_blank" rel="noopener">${esc(b.title)}</a></p>`).join("");
484
+ }
485
+ $("blurbh").textContent = first + "'s Blurbs";
486
+ $("aboutme").textContent = doc.blurbs.aboutMe; $("meet").textContent = doc.blurbs.meet;
487
+
488
+ const s = doc.song; $("player").style.display = s ? "" : "none";
489
+ if (s) { $("songt").textContent = s.title; $("songa").textContent = s.artist; }
490
+
491
+ $("friendh").textContent = first + "'s Friend Space";
492
+ $("friendcount").innerHTML = `${esc(doc.name || "This space")} has <span class="focus">${doc.top.length}</span> friend${doc.top.length === 1 ? "" : "s"}.`;
493
+ const fg = $("friendgrid"); fg.innerHTML = "";
494
+ doc.top.forEach((d, i) => {
495
+ const isSpace = !!YS.parseLink(d.link);
496
+ const fig = document.createElement("figure");
497
+ fig.innerHTML = `<div class="face${isSpace ? " doorspace" : ""}">${/^https:\/\//.test(d.photo) ? `<img src="${esc(d.photo)}" alt="">` : (esc(d.photo) || esc((d.name || "•")[0].toUpperCase()))}</div><figcaption><a>${esc(d.name || "friend")}</a></figcaption><button class="rm" aria-label="remove">×</button>`;
498
+ // L1: a space door NESTS the friend's world in-page (infinite depth); anything else opens out.
499
+ fig.onclick = (ev) => { if (ev.target.className === "rm") return commit(YS.removeDoor(doc, i));
500
+ if (isSpace) return openSpace(d.link, d.name || "space"); open(d.link, "_blank", "noopener"); };
501
+ fg.appendChild(fig);
502
+ });
503
+ $("viewall").textContent = "View All of " + first + "'s Friends";
504
+ $("viewall").onclick = () => toast(doc.top.length ? doc.top.map((d) => d.name || "friend").join(" · ") : "No friends yet — that's what forking is for");
505
+
506
+ $("commenth").textContent = first + "'s Friends Comments";
507
+ $("ccount").innerHTML = doc.wall
508
+ ? `Comments live in <b>${esc(first)}'s sealed wall</b> — step in to read and write. Honest number: only the room knows.`
509
+ : `Displaying <b>0</b> of <b>0</b> comments — this wall isn't open yet.`;
510
+ $("commentrows").innerHTML = doc.wall ? "" : `<table><tr><th>${esc(first)}<br><div style="font-size:30px">${esc(doc.avatar) || "🪐"}</div></th><td><b>${new Date().toLocaleDateString()}</b><br><br>Your wall opens when you weld a sealed room to this page. Until then: real numbers only — this page never invents a comment.</td></tr></table>`;
511
+ $("addcomment").onclick = () => doc.wall ? open(doc.wall, "_blank") : toast(owner ? "Weld a room link into your wall field (rooms are live in the messenger)" : "This wall isn't open yet — fork the page and open your own");
512
+
513
+ // hint + CTA
514
+ $("hint").classList.toggle("on", isSeed);
515
+ if (isSeed) $("hint").innerHTML = "👋 <b>Welcome back.</b> This is Q's page — same page your thumbs remember, except it lives inside the link itself. <b>Make It Mine</b> below ↓";
516
+ const cta = $("cta"); cta.innerHTML = "";
517
+ const btn = (label, cls, fn) => { const b = document.createElement("button"); b.className = "btn2004 " + cls; b.textContent = label; b.onclick = fn; cta.appendChild(b); };
518
+ if (mode === "edit") btn("Done — mint my link", "go", finish);
519
+ else if (owner) { btn("Edit My Space", "", () => show(doc, "edit")); btn("Share", "go", share); }
520
+ else { btn("✨ Make It Mine", "go", makeItMine); btn("Share", "", share); }
521
+
522
+ renderEditRacks();
523
+ wireEditables();
524
+ }
525
+
526
+ function sideTable(id, title, rows, data, ekAttr) {
527
+ const tb = $(id).querySelector("tbody"); tb.innerHTML = "";
528
+ const live = rows.filter(([, k]) => data[k] || mode === "edit");
529
+ $(id).style.display = live.length ? "" : "none";
530
+ if (!live.length) return;
531
+ tb.innerHTML = `<tr class="h2row"><td colspan="2">${esc(title)}</td></tr>` +
532
+ live.map(([label, k]) => `<tr><th>${esc(label)}</th><td class="v" data-${ekAttr}="${k}" data-ph="…">${esc(data[k])}</td></tr>`).join("");
533
+ }
534
+
535
+ /* ── the loop ────────────────────────────────────────────────────────────────────────── */
536
+ async function makeItMine() {
537
+ let mine;
538
+ try { mine = await YS.fork(doc, location.hash.includes("#p=") ? location.href : location.origin + location.pathname); }
539
+ catch (e) { mine = YS.upgrade(doc); mine = YS.withFields(mine, { name: "", via: { k: "", name: doc.name } }); }
540
+ toast("It's yours. Decorate, then mint your link ✨");
541
+ show(mine, "edit");
542
+ scrollTo({ top: 0, behavior: "smooth" });
543
+ }
544
+ async function addToFriends() { // 2004 "Add to Friends" = put THIS page in MY Top 8
545
+ const m = me();
546
+ if (!m) return makeItMine();
547
+ const my = YS.upgrade(YS.decode(m.payload));
548
+ const updated = YS.addDoor(my, { name: doc.name || "friend", link: location.href, photo: doc.avatar });
549
+ saveMe(updated, m.link);
550
+ toast((doc.name || "This space") + " added to your Top 8 ✔ — friendship is mutual when they add you back");
551
+ }
552
+ function commit(next) { doc = YS.identity(next); show(doc, mode); }
553
+
554
+ function collectEdits() {
555
+ const g = {}; for (const k of ["gender", "age", "city", "region", "country"]) g[k] = $("d-" + k).textContent.trim();
556
+ const interests = {}, details = {};
557
+ document.querySelectorAll("[data-eki]").forEach((el) => interests[el.dataset.eki] = el.textContent.trim());
558
+ document.querySelectorAll("[data-ekd]").forEach((el) => details[el.dataset.ekd] = el.textContent.trim());
559
+ return YS.withFields(doc, {
560
+ name: $("name").textContent.trim(), headline: $("headline").textContent.trim(),
561
+ mood: { emo: $("moodemo").textContent.trim(), word: $("moodword").textContent.trim() },
562
+ demog: g, interests: { ...doc.interests, ...interests }, details: { ...doc.details, ...details },
563
+ blurbs: { aboutMe: $("aboutme").textContent.trim(), meet: $("meet").textContent.trim() },
564
+ });
565
+ }
566
+ async function finish() {
567
+ doc = collectEdits();
568
+ saveMe(doc, myLink());
569
+ history.replaceState(null, "", "#p=v" + doc.v + "." + YS.encode(doc));
570
+ await show(doc, "view");
571
+ toast("Minted. The URL box on the left IS your page — copy it, post it anywhere.");
572
+ share();
573
+ }
574
+ async function share() {
575
+ const url = location.href;
576
+ const title = (doc.name ? doc.name + "'s" : "my") + " space";
577
+ try { if (navigator.share) return await navigator.share({ title, text: "step into " + title, url }); } catch (e) { if (e.name === "AbortError") return; }
578
+ try { await navigator.clipboard.writeText(url); toast("Link copied — drop it in any chat 💫"); }
579
+ catch (e) { prompt("Copy your space link:", url); }
580
+ }
581
+ function goHome() { const m = me(); if (m && m.link) location.assign(m.link); else { location.hash = ""; } }
582
+
583
+ /* ── edit affordances ───────────────────────────────────────────────────────────────── */
584
+ function wireEditables() {
585
+ const on = mode === "edit";
586
+ document.querySelectorAll("[data-ek],[data-eki],[data-ekd],[data-ekg]").forEach((el) => { el.contentEditable = on ? "plaintext-only" : "false"; });
587
+ }
588
+ function renderEditRacks() {
589
+ const rack = $("layoutchips"); rack.innerHTML = "";
590
+ Object.keys(LAYOUTS).forEach((name) => { const b = document.createElement("button"); b.className = "btn2004"; b.textContent = name;
591
+ b.onclick = () => { commit(YS.withFields(collectEdits(), { customCss: LAYOUTS[name] })); toast(name + " layout on — via the rack, free forever"); }; rack.appendChild(b); });
592
+ $("csspaste").value = doc.customCss || "";
593
+ }
594
+ $("cssapply").onclick = () => {
595
+ const clean = YS.sanitizeCss($("csspaste").value);
596
+ if ($("csspaste").value.trim() && !clean) return toast("Code refused — CSS only: no <, no @import, no scripts, urls must be data:/https:");
597
+ commit(YS.withFields(collectEdits(), { customCss: clean }));
598
+ toast(clean ? "Your code is live on your page ✨" : "Back to the classic skin");
599
+ };
600
+ $("avatar").onclick = () => { if (mode !== "edit") return; const p = $("picker"); p.classList.toggle("on");
601
+ const g = $("emojis"); if (!g.childElementCount) EMOJIS.forEach((e) => { const b = document.createElement("button"); b.textContent = e;
602
+ b.onclick = () => { p.classList.remove("on"); commit(YS.withFields(collectEdits(), { avatar: e })); }; g.appendChild(b); }); };
603
+ $("avurl").onchange = () => { $("picker").classList.remove("on"); commit(YS.withFields(collectEdits(), { avatar: $("avurl").value.trim() })); };
604
+ document.addEventListener("click", (e) => { if (!$("picker").contains(e.target) && e.target !== $("avatar")) $("picker").classList.remove("on"); });
605
+
606
+ let srchT = null;
607
+ $("srchin").oninput = () => { clearTimeout(srchT); srchT = setTimeout(async () => {
608
+ const q = $("srchin").value.trim(); const box = $("srchres"); if (!q) { box.innerHTML = ""; return; }
609
+ try {
610
+ const r = await fetch(`https://itunes.apple.com/search?media=music&limit=5&term=${encodeURIComponent(q)}`);
611
+ const js = await r.json(); box.innerHTML = "";
612
+ (js.results || []).forEach((t) => { const d = document.createElement("div"); d.className = "res";
613
+ d.innerHTML = `<img src="${esc(t.artworkUrl100 || "")}" alt=""><div><b>${esc(t.trackName)}</b><br><span>${esc(t.artistName)}</span></div>`;
614
+ d.onclick = () => { commit(YS.withFields(collectEdits(), { song: { title: t.trackName, artist: t.artistName, art: t.artworkUrl100 || "", query: `${t.artistName} ${t.trackName}`, preview: t.previewUrl || "" } })); toast("Song set 🎧 — it plays when someone enters"); };
615
+ box.appendChild(d); });
616
+ } catch (e) { box.innerHTML = `<div class="res">search unreachable — try again later</div>`; }
617
+ }, 350); };
618
+ $("dooradd").onclick = () => { const l = $("doorlink").value.trim(), n = $("doorname").value.trim();
619
+ if (!l) return toast("Paste a link first");
620
+ commit(YS.addDoor(collectEdits(), { name: n || "friend", link: l, photo: "" })); $("doorlink").value = $("doorname").value = ""; };
621
+
622
+ /* ── the song: first gesture starts it (the lawful 2004 autoplay) ───────────────────── */
623
+ async function playSong(toggle) {
624
+ const s = doc.song; if (!s) return;
625
+ const a = $("audio"), btn = $("songbtn");
626
+ if (toggle && !a.paused) { a.pause(); btn.textContent = "▶"; try { busCmd("pause"); } catch (e) {} return; }
627
+ if (await busCmd("play", [s.query || `${s.artist} ${s.title}`])) { btn.textContent = "❚❚"; toast("Playing in Holo Music 🎶"); return; }
628
+ let src = s.preview;
629
+ if (!src && (s.query || s.title)) { try {
630
+ const r = await fetch(`https://itunes.apple.com/search?media=music&limit=1&term=${encodeURIComponent(s.query || s.artist + " " + s.title)}`);
631
+ src = ((await r.json()).results || [])[0]?.previewUrl || ""; } catch (e) {} }
632
+ if (!src) { if (toggle) toast("Song not reachable right now"); return; }
633
+ a.src = src; try { await a.play(); btn.textContent = "❚❚"; } catch (e) { if (toggle) toast("Tap ▶ to play"); }
634
+ a.onended = () => { btn.textContent = "▶"; };
635
+ }
636
+ $("songbtn").onclick = () => playSong(true);
637
+ const firstGesture = () => { if (gestured) return; gestured = true; if (mode === "view" && doc && doc.song) playSong(false); };
638
+ addEventListener("pointerdown", firstGesture, { once: false });
639
+ addEventListener("scroll", firstGesture, { once: true, passive: true });
640
+
641
+ function busCmd(cmd, args = []) {
642
+ return new Promise((res) => { let done = false;
643
+ try { const ch = new BroadcastChannel("holo-music-ctl"); const id = Math.random().toString(36).slice(2);
644
+ ch.onmessage = (e) => { if (e.data && e.data.re === id) { done = true; ch.close(); res(!!e.data.ok); } };
645
+ ch.postMessage({ id, cmd, args }); setTimeout(() => { if (!done) { ch.close(); res(false); } }, 800);
646
+ } catch (e) { res(false); } });
647
+ }
648
+
649
+ $("kap").onclick = async () => { try {
650
+ const ok = await YS.verify(doc, curKappa);
651
+ $("kap").classList.toggle("ok", ok); setTimeout(() => $("kap").classList.remove("ok"), 1600);
652
+ await navigator.clipboard.writeText(curKappa); toast(ok ? "re-derived ✓ · κ copied — the page you see IS the link you share" : "κ MISMATCH — refused");
653
+ } catch (e) { toast("κ unavailable here"); } };
654
+
655
+ $("navsignup").onclick = () => makeItMine();
656
+ $("navhelp").onclick = () => { location.hash = ""; };
657
+ $("qgo").onclick = () => { const v = $("q").value.trim(); const p = YS.parseLink(v); if (p) location.assign(location.pathname + "#p=v" + (YS.decode(p).v) + "." + p); else toast(v ? "Paste a space link to teleport to it" : "Search = paste any space link"); };
658
+ $("fnew").onclick = () => show(YS.identity({ v: 3, name: "", customCss: "" }), "edit");
659
+ ["fabout", "ffaq", "fterms", "fprivacy", "fsafety", "fcontact", "fpromote"].forEach((id) => $(id).onclick = () => toast("This page has no company behind it — it's a κ. About: the footer says it all."));
660
+
661
+ boot();
662
+ </script>
663
+ </body>
664
+ </html>
sha256/6d94e93e0bbc6d0caa26b712295118bfad1eff2bd9f8e5b4cf26eb83d93e03dd ADDED
The diff for this file is too large to render. See raw diff
 
sha256/e732a48e30a1a43351107d7c8d2f4837c0687e57d1330095ac8cc1f64f93bcd0 ADDED
@@ -0,0 +1 @@
 
 
1
+ {"@context":["https://www.w3.org/ns/did/v1","https://w3id.org/security/data-integrity/v2",{"dcterms":"http://purl.org/dc/terms/","links":{"@container":"@set","@id":"schema:hasPart"},"prov":"http://www.w3.org/ns/prov#","rel":"schema:additionalType","schema":"https://schema.org/"},{"holstr":"https://hologram.os/ns/strand#"}],"@type":["prov:Entity","holstr:Entry"],"holstr:kind":"release","holstr:op":"did:holo:sha256:87599792c7b13fad9d6c57d3b89d2cef35e4715869f5cde597ab60ca92699f0b","holstr:payload":{"apps":{"carry":"9f44164b17e6b7e37f39623bb445d49b6608da5f2b04cef8b1a8b183362a6b9a","hello":"66c1ada5ac08a2d4f73851bbe7458ad5fb6e2226c5a131c3829abfe715900fed","holo-messenger":"0a65550d027ecaf8ee3e58e6c9221a09c376a3ea4cd8283e6376baeae525bab6","resolve":"23aec66382775f5773693615338f37c37a5f58257ec95aece33a664baa6fe0db","self":"0511772584510f0888d97dd5a72bf986ad6791bd8e305063ddd8a82c39888a70","spaces":"d8aebefb67e7fc7802e757b9a7d95bb881e6d75b4a9bc4bd4227634541757e51","yourspace":"120779d0c6de656d43ab07ed4a28e926770947fb67b90be9bfcaa3bae879480b"},"boot":{"entry":"holo-portal.mjs","sha256":"caeb3e57b6eeab09bee6d67c022145a8e2dae610c929a7f51bc169898625e7e8"},"closure":"5ad2f7b496957eb5c0f761c96aff4191f5b5f0baf4dc66948e7f7bd71f30db08","manifest":"8bd00282804b748cc852f8ad5fc7a583144ecbbcd715b333421445ed1d6fe3cc","runtime":{"apps/q/pkg/holospaces_web.js":"b9f8a887de588c5193dc65ca9ce206a70c6df53595b848e0ce0299c2d88a5753","apps/q/pkg/holospaces_web_bg.wasm":"9d90b4ea8bccee8c239073c7ec7dd5158c6d11f1f668487570d17475d79e661e","apps/workspace/pkg/holospaces_web.js":"8c30aa5582dffe4548d27fa7863163eba689ed65126be472c003f5884fc8e534","usr/lib/holo/holowhat/holospaces_web.js":"a5b5d9c559a1d2812c33e9d7a4b1c24bb03059482503a23356e4c9c32d4d8b88","usr/lib/holo/holowhat/holospaces_web_bg.wasm":"00cfa4960b319ba1ba7291cddb20dea130a407ce8b42426218854f4f68f4dcd7","usr/lib/pkg/holospaces_web.js":"8c30aa5582dffe4548d27fa7863163eba689ed65126be472c003f5884fc8e534","usr/lib/pkg/holospaces_web_bg.wasm":"3370b22070b56218a57df6406e2e4ba7cc171e942d4d1f2ae4297ea2c4c08d9c"},"shell":"97ca1ee6446f04c1d395d318e759c5a9ffdf4a27c26ef6ce9a5001dc49b2fd70"},"holstr:prev":"did:holo:sha256:533fecd9ac84191240732edb88e9009b75db0974377d555a1d34ef5e92b28419","holstr:seq":242,"prov:generatedAtTime":"2026-07-13T14:53:32.314Z"}