comparison mrjunejune/src/jrpg/index.html @ 273:e02e2036ef84 default tip

add Layer 2 JRPG component system Add reusable content and window modals, an isolated component sandbox, shared cyberpunk scroll areas, production-safe cache freshness, and server-rendered JRPG panel state. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Sat, 08 Aug 2026 02:08:08 -0700
parents 41a49c29a28f
children
comparison
equal deleted inserted replaced
272:41a49c29a28f 273:e02e2036ef84
5 {{/parts/base_head.html}} 5 {{/parts/base_head.html}}
6 <link rel="preload" href="/public/jrpg/background-frame-2.webp" as="image" media="not ((max-width: 52rem) and (orientation: portrait))"> 6 <link rel="preload" href="/public/jrpg/background-frame-2.webp" as="image" media="not ((max-width: 52rem) and (orientation: portrait))">
7 <link rel="preload" href="/public/jrpg/background-frame-mobile.webp" as="image" media="(max-width: 52rem) and (orientation: portrait)"> 7 <link rel="preload" href="/public/jrpg/background-frame-mobile.webp" as="image" media="(max-width: 52rem) and (orientation: portrait)">
8 <link rel="preload" href="/public/jrpg/bar-ink.webp" as="image"> 8 <link rel="preload" href="/public/jrpg/bar-ink.webp" as="image">
9 <link rel="stylesheet" href="/public/mjj-composer.css"> 9 <link rel="stylesheet" href="/public/mjj-composer.css">
10 <link rel="stylesheet" href="/public/mjj-modal.css">
10 <link rel="stylesheet" href="/jrpg/jrpg.css"> 11 <link rel="stylesheet" href="/jrpg/jrpg.css">
11 <script type="module" src="/public/mjj-composer.js"></script> 12 <script type="module" src="/public/mjj-composer.js"></script>
13 <script type="module" src="/public/mjj-modal.js"></script>
12 <script type="module" src="/jrpg/jrpg.js"></script> 14 <script type="module" src="/jrpg/jrpg.js"></script>
13 </head> 15 </head>
14 <body class="jrpg-page"> 16 <body class="jrpg-page">
15 <main class="jrpg-main"> 17 <main class="jrpg-main">
16 <mjj-jrpg-shell class="jrpg-shell"> 18 <mjj-jrpg-shell
19 class="jrpg-shell"
20 data-initial-panel="__MJJ_PANEL__"
21 >
17 <div class="jrpg-workspace"> 22 <div class="jrpg-workspace">
18 <div class="jrpg-brand"> 23 <div class="jrpg-brand">
19 <header> 24 <header>
20 <h1> 25 <h1>
21 <a href="/" data-zen-link-effect="none">MrJuneJune</a> 26 <a href="/" data-zen-link-effect="none">MrJuneJune</a>
47 <a href="/" aria-label="Close interface and return home"> 52 <a href="/" aria-label="Close interface and return home">
48 <zen-icon name="close"></zen-icon> 53 <zen-icon name="close"></zen-icon>
49 </a> 54 </a>
50 </zen-button> 55 </zen-button>
51 </nav> 56 </nav>
52 <zen-dialog 57 <mjj-window-modal
53 class="jrpg-mobile-destination-owner" 58 class="jrpg-mobile-destination-owner"
54 data-mobile-destination-owner 59 data-mobile-destination-owner
55 > 60 >
56 <zen-button class="jrpg-mobile-menu-btn" appearance="plain" size="xs"> 61 <zen-dialog>
57 <button 62 <zen-button class="jrpg-mobile-menu-btn" appearance="plain" size="xs">
58 type="button" 63 <button
59 data-zen-trigger 64 type="button"
60 data-mobile-menu-toggle 65 data-zen-trigger
61 aria-label="Open destination menu" 66 data-mobile-menu-toggle
67 aria-label="Open destination menu"
68 >
69 <zen-icon name="menu"></zen-icon>
70 </button>
71 </zen-button>
72 <dialog
73 class="jrpg-mobile-destination-dialog"
74 data-mobile-destination-dialog
62 > 75 >
63 <zen-icon name="menu"></zen-icon> 76 <header class="jrpg-mobile-destination-header" data-modal-header>
64 </button> 77 <zen-button
65 </zen-button> 78 appearance="plain"
66 <dialog 79 size="sm"
67 class="jrpg-mobile-destination-dialog" 80 data-mobile-destination-back-owner
68 data-mobile-destination-dialog 81 hidden
69 aria-labelledby="jrpg-mobile-destination-title"
70 >
71 <header class="jrpg-mobile-destination-header">
72 <zen-button
73 appearance="plain"
74 size="sm"
75 data-mobile-destination-back-owner
76 hidden
77 >
78 <button
79 type="button"
80 data-mobile-destination-back
81 aria-label="Back to destination menu"
82 > 82 >
83 <zen-icon name="chevron-left"></zen-icon> 83 <button
84 Menu 84 type="button"
85 </button> 85 data-mobile-destination-back
86 </zen-button> 86 aria-label="Back to destination menu"
87 <h2 87 >
88 id="jrpg-mobile-destination-title" 88 <zen-icon name="chevron-left"></zen-icon>
89 data-mobile-destination-title 89 Menu
90 >Menu</h2> 90 </button>
91 <zen-button appearance="plain" size="sm"> 91 </zen-button>
92 <button 92 <h2
93 type="button" 93 id="jrpg-mobile-destination-title"
94 data-zen-close 94 data-mobile-destination-title
95 aria-label="Close destination menu" 95 data-modal-title
96 > 96 >Menu</h2>
97 <zen-icon name="close"></zen-icon> 97 <zen-button appearance="plain" size="sm">
98 </button> 98 <button
99 </zen-button> 99 type="button"
100 </header> 100 data-zen-close
101 <div 101 aria-label="Close destination menu"
102 class="jrpg-mobile-destination-content" 102 >
103 data-mobile-destination-content 103 <zen-icon name="close"></zen-icon>
104 ></div> 104 </button>
105 </dialog> 105 </zen-button>
106 </zen-dialog> 106 </header>
107 <zen-scroll-area
108 class="jrpg-mobile-destination-content"
109 data-mobile-destination-content
110 data-modal-body
111 data-cyber-scroll
112 tabindex="0"
113 aria-label="Destination content"
114 ></zen-scroll-area>
115 </dialog>
116 </zen-dialog>
117 </mjj-window-modal>
107 <footer class="jrpg-frame-telemetry" aria-label="System telemetry"> 118 <footer class="jrpg-frame-telemetry" aria-label="System telemetry">
108 <span aria-label="Temperature unavailable">N/A</span> 119 <span aria-label="Temperature unavailable">N/A</span>
109 <span data-frame-account aria-live="polite"><a href="/login?next=/jrpg">LOGIN</a></span> 120 <span data-frame-account aria-live="polite"><a href="/login?next=/jrpg">LOGIN</a></span>
110 <span data-frame-network aria-label="Status online">ONLINE</span> 121 <span data-frame-network aria-label="Status online">ONLINE</span>
111 <time data-frame-uptime aria-label="Uptime">00:00:00</time> 122 <time data-frame-uptime aria-label="Uptime">00:00:00</time>
145 </nav> 156 </nav>
146 </mjj-jrpg-chat> 157 </mjj-jrpg-chat>
147 </section> 158 </section>
148 159
149 <section class="jrpg-utility" aria-label="Selected destination"> 160 <section class="jrpg-utility" aria-label="Selected destination">
150 <mjj-jrpg-preview data-selection="resume"> 161 <mjj-jrpg-preview data-selection="__MJJ_PREVIEW_SELECTION__">
151 <article class="jrpg-preview-panel" aria-live="polite"> 162 <article class="jrpg-preview-panel" aria-live="polite">
152 <div class="jrpg-preview-content" data-preview-content> 163 <div
164 class="jrpg-preview-content"
165 data-preview-content
166 __MJJ_PREVIEW_HIDDEN__
167 >
153 <zen-heading size="xl"> 168 <zen-heading size="xl">
154 <h2 data-preview-title>Resume</h2> 169 <h2 data-preview-title>__MJJ_PREVIEW_TITLE__</h2>
155 </zen-heading> 170 </zen-heading>
156 <p data-preview-copy> 171 <p data-preview-copy>
157 Member of Technical Staff and engineering leader with 10+ years building AI agent platforms and production systems. 172 __MJJ_PREVIEW_COPY__
158 </p> 173 </p>
159 <ul class="jrpg-work-showcase" data-work-showcase> 174 <ul class="jrpg-work-showcase" data-work-showcase>__MJJ_PREVIEW_WORKS__</ul>
160 <li> 175 <mjj-content-modal data-detail-modal-owner>
161 <a href="https://www.microsoft.com/en-us/microsoft-copilot/blog/2026/02/26/copilot-tasks-from-answers-to-actions/"> 176 <zen-dialog class="jrpg-preview-dialog">
162 <span>Copilot Tasks</span> 177 <zen-button appearance="plain" size="xs" data-dialog-trigger-owner hidden>
163 <small>Agentic execution</small> 178 <button type="button" data-zen-trigger tabindex="-1" aria-hidden="true"></button>
164 </a> 179 </zen-button>
165 </li> 180 <dialog class="jrpg-detail-dialog">
166 <li> 181 <header class="jrpg-dialog-heading" data-modal-header>
167 <a href="https://www.cio.com/article/3977098/microsoft-doubles-down-on-multi-model-ai-as-it-builds-a-copilot-super-app.html"> 182 <div data-modal-heading>
168 <span>Copilot SuperApp</span> 183 <p data-modal-kicker>DESTINATION DATA</p>
169 <small>AI platform</small> 184 <h2
170 </a> 185 id="jrpg-dialog-title"
171 </li> 186 data-dialog-title
172 </ul> 187 data-modal-title
173 <zen-dialog class="jrpg-preview-dialog"> 188 >Resume</h2>
174 <zen-button appearance="plain" size="xs" data-dialog-trigger-owner hidden> 189 </div>
175 <button type="button" data-zen-trigger tabindex="-1" aria-hidden="true"></button>
176 </zen-button>
177 <dialog class="jrpg-detail-dialog" aria-labelledby="jrpg-dialog-title">
178 <div class="jrpg-dialog-heading">
179 <p>DESTINATION DATA</p>
180 <div class="jrpg-dialog-heading-actions"> 190 <div class="jrpg-dialog-heading-actions">
181 <zen-button appearance="plain" size="md"> 191 <zen-button
182 <a href="/resume" data-preview-link> 192 appearance="plain"
183 Open page 193 size="sm"
184 <zen-icon name="external"></zen-icon> 194 data-resume-download
195 >
196 <a href="/public/resume.pdf">
197 Download PDF
198 <zen-icon name="download"></zen-icon>
185 </a> 199 </a>
186 </zen-button> 200 </zen-button>
187 <zen-button appearance="plain" size="md"> 201 <zen-button appearance="plain" size="sm">
188 <button type="button" data-zen-close aria-label="Close destination details"> 202 <button type="button" data-zen-close aria-label="Close destination details">
189 <zen-icon name="close"></zen-icon> 203 <zen-icon name="close"></zen-icon>
190 </button> 204 </button>
191 </zen-button> 205 </zen-button>
192 </div> 206 </div>
193 </div> 207 </header>
194 <h2 id="jrpg-dialog-title" data-dialog-title>Resume</h2> 208 <zen-scroll-area
195 <p data-dialog-copy>Experience, projects, and the systems I have helped build.</p> 209 class="jrpg-detail-body"
210 data-modal-body
211 data-cyber-scroll
212 tabindex="0"
213 aria-label="Destination details"
214 >
215 <div class="jrpg-detail-content" data-modal-article>
216 <p data-dialog-copy>Experience, projects, and the systems I have helped build.</p>
196 <section 217 <section
197 class="jrpg-resume-dossier" 218 class="jrpg-resume-dossier"
198 data-resume-dossier 219 data-resume-dossier
199 aria-label="Resume dossier" 220 aria-label="Resume dossier"
200 > 221 >
227 <article> 248 <article>
228 <p data-tool-status>Select a tool to inspect.</p> 249 <p data-tool-status>Select a tool to inspect.</p>
229 <div data-tool-content></div> 250 <div data-tool-content></div>
230 </article> 251 </article>
231 </section> 252 </section>
232 <div class="jrpg-dialog-actions" data-dialog-actions> 253 </div>
233 <zen-button appearance="plain" size="lg" data-resume-download> 254 </zen-scroll-area>
234 <a href="/public/resume.pdf"> 255 </dialog>
235 Download PDF 256 </zen-dialog>
236 <zen-icon name="download"></zen-icon> 257 </mjj-content-modal>
237 </a>
238 </zen-button>
239 </div>
240 </dialog>
241 </zen-dialog>
242 </div> 258 </div>
243 <mjj-conversation-archive hidden aria-label="Conversations"> 259 <mjj-conversation-archive
260 __MJJ_ARCHIVE_HIDDEN__
261 aria-label="Conversations"
262 >
244 <div class="jrpg-archive-heading"> 263 <div class="jrpg-archive-heading">
245 <h2>Archive</h2> 264 <h2>Archive</h2>
246 <zen-button appearance="plain" size="xs"> 265 <zen-button appearance="plain" size="xs">
247 <button type="button" data-archive-close aria-label="Close conversations"> 266 <button type="button" data-archive-close aria-label="Close conversations">
248 <zen-icon name="close"></zen-icon> 267 <zen-icon name="close"></zen-icon>
261 </ol> 280 </ol>
262 <zen-button appearance="plain" size="sm" data-archive-load-more-owner hidden> 281 <zen-button appearance="plain" size="sm" data-archive-load-more-owner hidden>
263 <button type="button" data-archive-load-more>Load more</button> 282 <button type="button" data-archive-load-more>Load more</button>
264 </zen-button> 283 </zen-button>
265 <p class="jrpg-archive-status" data-archive-status aria-live="polite">Loading conversations...</p> 284 <p class="jrpg-archive-status" data-archive-status aria-live="polite">Loading conversations...</p>
266 <dialog 285 <mjj-content-modal data-archive-delete-owner>
267 class="jrpg-archive-dialog" 286 <zen-dialog>
268 data-archive-delete-dialog 287 <zen-button appearance="plain" size="xs" hidden>
269 aria-labelledby="archive-delete-title" 288 <button type="button" data-zen-trigger tabindex="-1" aria-hidden="true"></button>
270 aria-modal="true" 289 </zen-button>
271 > 290 <dialog
272 <p id="archive-delete-title" class="jrpg-archive-dialog-title">Delete this conversation?</p> 291 class="jrpg-archive-dialog"
273 <p data-archive-delete-name class="jrpg-archive-dialog-subtitle"></p> 292 data-archive-delete-dialog
274 <div class="jrpg-archive-dialog-actions"> 293 >
275 <zen-button appearance="plain" size="md"> 294 <header data-modal-header>
276 <button type="button" data-archive-delete-cancel>Cancel</button> 295 <h2
277 </zen-button> 296 id="archive-delete-title"
278 <zen-button appearance="plain" size="md"> 297 class="jrpg-archive-dialog-title"
279 <button type="button" data-archive-delete-confirm>Delete</button> 298 data-modal-title
280 </zen-button> 299 >Delete this conversation?</h2>
281 </div> 300 </header>
282 </dialog> 301 <div data-modal-body>
283 <dialog 302 <div data-modal-article>
284 class="jrpg-archive-dialog" 303 <p data-archive-delete-name class="jrpg-archive-dialog-subtitle"></p>
285 data-archive-rename-dialog 304 </div>
286 aria-labelledby="archive-rename-title" 305 </div>
287 aria-modal="true" 306 <footer class="jrpg-archive-dialog-actions" data-modal-footer>
288 > 307 <zen-button appearance="plain" size="md">
289 <p id="archive-rename-title" class="jrpg-archive-dialog-title">Rename conversation</p> 308 <button type="button" data-archive-delete-cancel>Cancel</button>
290 <form data-archive-rename-form novalidate> 309 </zen-button>
291 <zen-field appearance="plain" size="md"> 310 <zen-button appearance="plain" size="md">
292 <label for="archive-rename-input">New title</label> 311 <button type="button" data-archive-delete-confirm>Delete</button>
293 <input 312 </zen-button>
294 id="archive-rename-input" 313 </footer>
295 data-archive-rename-input 314 </dialog>
296 type="text" 315 </zen-dialog>
297 maxlength="200" 316 </mjj-content-modal>
298 required 317 <mjj-window-modal data-archive-rename-owner>
299 autocomplete="off" 318 <zen-dialog>
319 <zen-button appearance="plain" size="xs" hidden>
320 <button type="button" data-zen-trigger tabindex="-1" aria-hidden="true"></button>
321 </zen-button>
322 <dialog
323 class="jrpg-archive-dialog"
324 data-archive-rename-dialog
325 >
326 <header data-modal-header>
327 <h2
328 id="archive-rename-title"
329 class="jrpg-archive-dialog-title"
330 data-modal-title
331 >Rename conversation</h2>
332 </header>
333 <form
334 id="archive-rename-form"
335 data-modal-body
336 data-archive-rename-form
337 novalidate
300 > 338 >
301 </zen-field> 339 <zen-field appearance="plain" size="md">
302 <div class="jrpg-archive-dialog-actions"> 340 <label for="archive-rename-input">New title</label>
341 <input
342 id="archive-rename-input"
343 data-archive-rename-input
344 type="text"
345 maxlength="200"
346 required
347 autocomplete="off"
348 >
349 </zen-field>
350 </form>
351 <footer class="jrpg-archive-dialog-actions" data-modal-footer>
303 <zen-button appearance="plain" size="md"> 352 <zen-button appearance="plain" size="md">
304 <button type="button" data-archive-rename-cancel>Cancel</button> 353 <button type="button" data-archive-rename-cancel>Cancel</button>
305 </zen-button> 354 </zen-button>
306 <zen-button appearance="plain" size="md"> 355 <zen-button appearance="plain" size="md">
307 <button type="submit">Save</button> 356 <button type="submit" form="archive-rename-form">Save</button>
308 </zen-button> 357 </zen-button>
309 </div> 358 </footer>
310 </form> 359 </dialog>
311 </dialog> 360 </zen-dialog>
361 </mjj-window-modal>
312 </mjj-conversation-archive> 362 </mjj-conversation-archive>
313 </article> 363 </article>
314 </mjj-jrpg-preview> 364 </mjj-jrpg-preview>
315 </section> 365 </section>
316 366
370 <nav aria-label="Shiba Quest destinations"> 420 <nav aria-label="Shiba Quest destinations">
371 <p class="jrpg-menu-label">Menu</p> 421 <p class="jrpg-menu-label">Menu</p>
372 <ul> 422 <ul>
373 <li> 423 <li>
374 <zen-button appearance="plain" size="sm"> 424 <zen-button appearance="plain" size="sm">
375 <button type="button" data-preview="resume" aria-pressed="true"> 425 <button type="button" data-preview="resume" aria-pressed="__MJJ_RESUME_PRESSED__">
376 <zen-icon name="chevron-right"></zen-icon> 426 <zen-icon name="chevron-right"></zen-icon>
377 Resume 427 Resume
378 </button> 428 </button>
379 </zen-button> 429 </zen-button>
380 </li> 430 </li>
381 <li> 431 <li>
382 <zen-button appearance="plain" size="sm"> 432 <zen-button appearance="plain" size="sm">
383 <button type="button" data-preview="tools" aria-pressed="false"> 433 <button type="button" data-preview="tools" aria-pressed="__MJJ_TOOLS_PRESSED__">
384 <zen-icon name="chevron-right"></zen-icon> 434 <zen-icon name="chevron-right"></zen-icon>
385 Tools 435 Tools
386 </button> 436 </button>
387 </zen-button> 437 </zen-button>
388 </li> 438 </li>
389 <li> 439 <li>
390 <zen-button appearance="plain" size="sm"> 440 <zen-button appearance="plain" size="sm">
391 <button type="button" data-preview="blog" aria-pressed="false"> 441 <button type="button" data-preview="blog" aria-pressed="__MJJ_BLOG_PRESSED__">
392 <zen-icon name="chevron-right"></zen-icon> 442 <zen-icon name="chevron-right"></zen-icon>
393 Blogs 443 Blogs
394 </button> 444 </button>
395 </zen-button> 445 </zen-button>
396 </li> 446 </li>
397 <li> 447 <li>
398 <zen-button appearance="plain" size="sm"> 448 <zen-button appearance="plain" size="sm">
399 <button type="button" data-preview="conversations" aria-pressed="false"> 449 <button type="button" data-preview="conversations" aria-pressed="__MJJ_CONVERSATIONS_PRESSED__">
400 <zen-icon name="chevron-right"></zen-icon> 450 <zen-icon name="chevron-right"></zen-icon>
401 Conversations 451 Conversations
402 </button> 452 </button>
403 </zen-button> 453 </zen-button>
404 </li> 454 </li>
405 </ul> 455 </ul>
406 </nav> 456 </nav>
407 </mjj-jrpg-menu> 457 </mjj-jrpg-menu>
408 458
409 <zen-dialog class="jrpg-login-dialog-owner" data-login-dialog-owner> 459 <mjj-window-modal class="jrpg-login-dialog-owner" data-login-dialog-owner>
410 <zen-button appearance="plain" size="md" hidden> 460 <zen-dialog>
411 <button type="button" data-zen-trigger tabindex="-1" aria-hidden="true"></button> 461 <zen-button appearance="plain" size="md" hidden>
412 </zen-button> 462 <button type="button" data-zen-trigger tabindex="-1" aria-hidden="true"></button>
413 <dialog 463 </zen-button>
414 class="jrpg-login-dialog" 464 <dialog
415 data-login-dialog 465 class="jrpg-login-dialog"
416 aria-labelledby="jrpg-login-title" 466 data-login-dialog
417 aria-modal="true" 467 >
418 > 468 <header class="jrpg-login-dialog-header" data-modal-header>
419 <div class="jrpg-login-dialog-header"> 469 <h2 id="jrpg-login-title" data-modal-title>SIGN IN</h2>
420 <h2 id="jrpg-login-title">SIGN IN</h2> 470 <zen-button appearance="plain" size="md">
421 <zen-button appearance="plain" size="md"> 471 <button type="button" data-zen-close aria-label="Close sign-in dialog">
422 <button type="button" data-zen-close aria-label="Close sign-in dialog"> 472 <zen-icon name="close"></zen-icon>
423 <zen-icon name="close"></zen-icon> 473 </button>
424 </button> 474 </zen-button>
425 </zen-button> 475 </header>
426 </div> 476 <form
427 <div role="alert" data-login-error aria-live="assertive" hidden></div> 477 id="jrpg-login-form"
428 <form data-login-form novalidate> 478 data-login-form
479 data-modal-body
480 novalidate
481 >
482 <div role="alert" data-login-error aria-live="assertive" hidden></div>
429 <zen-field appearance="plain" size="md"> 483 <zen-field appearance="plain" size="md">
430 <label for="jrpg-login-username">Username</label> 484 <label for="jrpg-login-username">Username</label>
431 <input 485 <input
432 id="jrpg-login-username" 486 id="jrpg-login-username"
433 name="username" 487 name="username"
449 required 503 required
450 minlength="12" 504 minlength="12"
451 maxlength="1024" 505 maxlength="1024"
452 > 506 >
453 </zen-field> 507 </zen-field>
454 <div class="jrpg-login-dialog-actions"> 508 </form>
509 <footer class="jrpg-login-dialog-actions" data-modal-footer>
455 <zen-button appearance="plain" size="md"> 510 <zen-button appearance="plain" size="md">
456 <button type="button" data-login-cancel data-zen-close>Cancel</button> 511 <button type="button" data-login-cancel data-zen-close>Cancel</button>
457 </zen-button> 512 </zen-button>
458 <zen-button appearance="plain" size="md"> 513 <zen-button appearance="plain" size="md">
459 <button type="submit" data-login-submit>Sign in</button> 514 <button
460 </zen-button> 515 type="submit"
461 </div> 516 form="jrpg-login-form"
462 </form> 517 data-login-submit
463 </dialog> 518 >Sign in</button>
464 </zen-dialog> 519 </zen-button>
520 </footer>
521 </dialog>
522 </zen-dialog>
523 </mjj-window-modal>
465 </div> 524 </div>
466 </mjj-jrpg-shell> 525 </mjj-jrpg-shell>
467 </main> 526 </main>
468 </body> 527 </body>
469 </html> 528 </html>