diff mrjunejune/src/jrpg/jrpg.css @ 263:ee04e4e69fed

Add functional JRPG frame and tools Add full-screen background_2 apertures, functional frame chrome, card-driven details, dual-window tools, live conversion workflows, and bounded cleanup for generated downloads. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <mrjunejune@users.noreply.github.com>
date Thu, 06 Aug 2026 11:31:30 -0700
parents 0f45474c1b1a
children 04fee26ecce0
line wrap: on
line diff
--- a/mrjunejune/src/jrpg/jrpg.css	Thu Aug 06 04:08:45 2026 -0700
+++ b/mrjunejune/src/jrpg/jrpg.css	Thu Aug 06 11:31:30 2026 -0700
@@ -6,6 +6,7 @@
 
 :root {
   --mjj-jrpg-art: url("/public/jrpg/bar-ink.webp");
+  --mjj-jrpg-frame-art: url("/public/jrpg/background-frame-2.webp");
   --mjj-jrpg-canvas: var(--zenbu-sys-color-surface-page);
   --mjj-jrpg-surface: var(--zenbu-sys-color-surface-default);
   --mjj-jrpg-surface-raised: var(--zenbu-sys-color-surface-raised);
@@ -55,6 +56,12 @@
   font-family: inherit;
 }
 
+.jrpg-page zen-icon svg {
+  shape-rendering: crispEdges;
+  stroke-linecap: square;
+  stroke-linejoin: miter;
+}
+
 .jrpg-main {
   box-sizing: border-box;
   width: 100%;
@@ -65,29 +72,243 @@
 }
 
 .jrpg-shell {
+  --mjj-frame-scene-inline: 3.2%;
+  --mjj-frame-scene-block: 9.4%;
+  --mjj-frame-scene-width: 54.8%;
+  --mjj-frame-scene-height: 57%;
+  --mjj-frame-utility-inline: 60.4%;
+  --mjj-frame-utility-block: 9.4%;
+  --mjj-frame-utility-width: 36.5%;
+  --mjj-frame-utility-height: 57%;
+  --mjj-frame-composer-inline: 3.2%;
+  --mjj-frame-composer-block: 72%;
+  --mjj-frame-composer-width: 68.2%;
+  --mjj-frame-composer-height: 17.2%;
+  --mjj-frame-menu-inline: 73.4%;
+  --mjj-frame-menu-block: 72%;
+  --mjj-frame-menu-width: 23.4%;
+  --mjj-frame-menu-height: 17.2%;
+  --mjj-frame-brand-inline: 5.4%;
+  --mjj-frame-brand-block: 2.2%;
+  --mjj-frame-brand-width: 7.8%;
+  --mjj-frame-brand-height: 5.2%;
+  --mjj-frame-controls-inline: 86.6%;
+  --mjj-frame-controls-block: 3.4%;
+  --mjj-frame-controls-width: 11.5%;
+  --mjj-frame-controls-height: 10%;
+  --mjj-frame-controls-gap: 7%;
+  --mjj-frame-telemetry-inline: 8.5%;
+  --mjj-frame-telemetry-block: 92.8%;
+  --mjj-frame-telemetry-width: 75%;
+  --mjj-frame-telemetry-height: 4.8%;
+  --mjj-frame-temp-value-inline: 12%;
+  --mjj-frame-user-value-inline: 32.5%;
+  --mjj-frame-status-value-inline: 60.5%;
+  --mjj-frame-uptime-value-inline: 88%;
+  --mjj-frame-dog-bar-block-end: 4%;
+  --mjj-frame-dog-bar-height: 31%;
   box-sizing: border-box;
-  display: block;
+  display: grid;
+  place-items: center;
   width: 100%;
   max-width: none;
   height: 100%;
   margin: 0;
-  padding: var(--zenbu-sys-padding-sm);
-  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-frame);
+  padding: 0;
+  border: 0;
   background: var(--mjj-jrpg-canvas);
-  box-shadow:
-    inset 0 0 0 var(--zenbu-sys-stroke-width)
-    var(--mjj-jrpg-frame-soft);
+  box-shadow: none;
 }
 
 .jrpg-workspace {
+  position: relative;
+  display: block;
+  width: 100%;
+  height: 100%;
+  max-height: none;
+  aspect-ratio: auto;
+  min-height: 0;
+  background-image: var(--mjj-jrpg-frame-art);
+  background-position: center;
+  background-repeat: no-repeat;
+  background-size: 100% 100%;
+  image-rendering: pixelated;
+}
+
+.jrpg-workspace > .jrpg-brand {
+  position: absolute;
+  z-index: 4;
+  inset:
+    var(--mjj-frame-brand-block)
+    auto
+    auto
+    var(--mjj-frame-brand-inline);
   display: grid;
-  grid-template:
-    "scene utility" minmax(0, 1fr)
-    "composer menu" minmax(9rem, auto) /
-    minmax(0, 1.22fr) minmax(19rem, 0.95fr);
-  gap: var(--zenbu-sys-space-group);
+  place-items: center;
+  width: var(--mjj-frame-brand-width);
+  height: var(--mjj-frame-brand-height);
+  margin: 0;
+  padding: 0;
+  border: 0;
+  background: var(--mjj-jrpg-canvas);
+  box-shadow: none;
+  text-align: center;
+}
+
+.jrpg-workspace > .jrpg-brand header {
+  position: relative;
+  z-index: 1;
+}
+
+.jrpg-frame-controls {
+  position: absolute;
+  z-index: 5;
+  inset:
+    var(--mjj-frame-controls-block)
+    auto
+    auto
+    var(--mjj-frame-controls-inline);
+  display: grid;
+  grid-template-columns: repeat(3, minmax(0, 1fr));
+  gap: var(--mjj-frame-controls-gap);
+  width: var(--mjj-frame-controls-width);
+  height: var(--mjj-frame-controls-height);
+  margin: 0;
+}
+
+.jrpg-frame-controls zen-button,
+.jrpg-frame-controls :where(button, a) {
+  width: 100%;
   height: 100%;
-  min-height: 0;
+}
+
+.jrpg-frame-controls :where(button, a) {
+  padding: 0;
+  border: 0;
+  border-radius: 0;
+  background: transparent;
+  color: transparent;
+  cursor: pointer;
+}
+
+.jrpg-frame-controls zen-icon {
+  opacity: 0;
+}
+
+.jrpg-frame-telemetry {
+  position: absolute;
+  z-index: 4;
+  inset:
+    var(--mjj-frame-telemetry-block)
+    auto
+    auto
+    var(--mjj-frame-telemetry-inline);
+  display: block;
+  width: var(--mjj-frame-telemetry-width);
+  height: var(--mjj-frame-telemetry-height);
+  margin: 0;
+  padding: 0;
+  color: var(--mjj-jrpg-primary);
+  font-size: clamp(
+    var(--zenbu-sys-font-size-xs),
+    1vw,
+    var(--zenbu-sys-font-size-sm)
+  );
+}
+
+.jrpg-frame-telemetry > * {
+  position: absolute;
+  top: 50%;
+  padding-inline: var(--zenbu-sys-padding-md);
+  background: var(--mjj-jrpg-canvas);
+  transform: translate(-50%, -50%);
+  white-space: nowrap;
+}
+
+.jrpg-frame-telemetry > :nth-child(1) {
+  left: var(--mjj-frame-temp-value-inline);
+}
+
+.jrpg-frame-telemetry > :nth-child(2) {
+  left: var(--mjj-frame-user-value-inline);
+  padding-inline: var(--zenbu-sys-padding-xl);
+}
+
+.jrpg-frame-telemetry > :nth-child(3) {
+  left: var(--mjj-frame-status-value-inline);
+  padding-inline: var(--zenbu-sys-padding-xl);
+}
+
+.jrpg-frame-telemetry > :nth-child(4) {
+  left: var(--mjj-frame-uptime-value-inline);
+}
+
+.jrpg-frame-telemetry [data-frame-network][data-state="offline"] {
+  color: var(--mjj-jrpg-accent);
+}
+
+.jrpg-frame-controls :where(button, a):focus-visible {
+  outline-color: var(--mjj-jrpg-focus);
+}
+
+.jrpg-shell[data-minimized="true"] .jrpg-workspace > :is(
+  .jrpg-scene,
+  .jrpg-utility,
+  mjj-jrpg-composer,
+  mjj-jrpg-menu
+) {
+  visibility: hidden;
+}
+
+.jrpg-workspace > .jrpg-scene,
+.jrpg-workspace > .jrpg-utility,
+.jrpg-workspace > mjj-jrpg-composer,
+.jrpg-workspace > mjj-jrpg-menu {
+  position: absolute;
+  margin: 0;
+  border: 0;
+  border-radius: 0;
+  box-shadow: none;
+}
+
+.jrpg-workspace > .jrpg-scene {
+  inset:
+    var(--mjj-frame-scene-block)
+    auto
+    auto
+    var(--mjj-frame-scene-inline);
+  width: var(--mjj-frame-scene-width);
+  height: var(--mjj-frame-scene-height);
+}
+
+.jrpg-workspace > .jrpg-utility {
+  inset:
+    var(--mjj-frame-utility-block)
+    auto
+    auto
+    var(--mjj-frame-utility-inline);
+  width: var(--mjj-frame-utility-width);
+  height: var(--mjj-frame-utility-height);
+}
+
+.jrpg-workspace > mjj-jrpg-composer {
+  inset:
+    var(--mjj-frame-composer-block)
+    auto
+    auto
+    var(--mjj-frame-composer-inline);
+  width: var(--mjj-frame-composer-width);
+  height: var(--mjj-frame-composer-height);
+}
+
+.jrpg-workspace > mjj-jrpg-menu {
+  inset:
+    var(--mjj-frame-menu-block)
+    auto
+    auto
+    var(--mjj-frame-menu-inline);
+  width: var(--mjj-frame-menu-width);
+  height: var(--mjj-frame-menu-height);
 }
 
 .jrpg-scene,
@@ -102,12 +323,13 @@
 
 .jrpg-scene {
   grid-area: scene;
+  position: relative;
   display: grid;
-  grid-template-columns: minmax(8rem, 0.38fr) minmax(15rem, 0.92fr);
+  grid-template-columns: minmax(5rem, 0.38fr) minmax(0, 0.92fr);
   align-items: end;
-  gap: var(--zenbu-sys-space-group);
+  gap: var(--zenbu-sys-space-control);
   min-height: 0;
-  padding: var(--zenbu-sys-padding-lg);
+  padding: var(--zenbu-sys-padding-md);
   overflow: hidden;
   background-image:
     linear-gradient(
@@ -124,7 +346,23 @@
   background-size: cover;
 }
 
+.jrpg-scene::before {
+  position: absolute;
+  z-index: 0;
+  inset: auto 0 var(--mjj-frame-dog-bar-block-end);
+  height: var(--mjj-frame-dog-bar-height);
+  background-image: var(--mjj-jrpg-art);
+  background-position: center;
+  background-repeat: no-repeat;
+  background-size: 100% 100%;
+  content: "";
+  image-rendering: pixelated;
+  pointer-events: none;
+}
+
 mjj-jrpg-character {
+  position: relative;
+  z-index: 2;
   display: block;
   align-self: end;
   min-width: 0;
@@ -156,6 +394,7 @@
 
 mjj-jrpg-chat {
   position: relative;
+  z-index: 1;
   display: grid;
   grid-template-rows: auto minmax(0, 1fr) auto;
   align-self: stretch;
@@ -180,8 +419,7 @@
 .jrpg-preview-kicker,
 .jrpg-menu-label,
 .jrpg-brand > p,
-.jrpg-dialog-heading p,
-.jrpg-preview-stats dt {
+.jrpg-dialog-heading p {
   color: var(--mjj-jrpg-text-muted);
   font-size: var(--zenbu-sys-font-size-xs);
   letter-spacing: 0.08em;
@@ -317,8 +555,8 @@
 .jrpg-utility {
   grid-area: utility;
   display: grid;
-  grid-template-rows: auto minmax(0, 1fr);
-  gap: var(--zenbu-sys-space-group);
+  grid-template-rows: minmax(0, 1fr);
+  gap: 0;
   padding: var(--zenbu-sys-padding-md);
   background: var(--mjj-jrpg-surface);
 }
@@ -363,9 +601,19 @@
   min-height: 0;
 }
 
+.jrpg-workspace > .jrpg-brand header h1 {
+  font-size: clamp(
+    var(--zenbu-sys-font-size-xs),
+    0.95vw,
+    var(--zenbu-sys-font-size-sm)
+  );
+  line-height: 1;
+  white-space: nowrap;
+}
+
 .jrpg-preview-panel {
   display: grid;
-  grid-template-rows: auto auto auto minmax(0, 1fr) auto auto;
+  grid-template-rows: auto auto auto minmax(0, 1fr) auto;
   gap: var(--zenbu-sys-space-group);
   height: 100%;
   padding: var(--zenbu-sys-padding-lg);
@@ -427,22 +675,14 @@
   font-size: var(--zenbu-sys-font-size-xs);
 }
 
-.jrpg-preview-stats {
-  display: grid;
-  grid-template-columns: repeat(2, 1fr);
-  gap: var(--zenbu-sys-space-control);
-  margin: 0;
+.jrpg-work-showcase a:has(> zen-icon) {
+  grid-template-columns: auto minmax(0, 1fr);
 }
 
-.jrpg-preview-stats div {
-  padding: var(--zenbu-sys-padding-sm);
-  border: var(--zenbu-sys-stroke-width) solid var(--mjj-jrpg-frame-soft);
-  background: var(--mjj-jrpg-panel);
-}
-
-.jrpg-preview-stats dd {
-  color: var(--mjj-jrpg-success);
-  margin: var(--zenbu-sys-space-icon-label) 0 0;
+.jrpg-work-showcase a > zen-icon {
+  grid-row: 1 / 3;
+  align-self: center;
+  color: var(--mjj-jrpg-highlight);
 }
 
 .jrpg-preview-dialog > zen-button > button,
@@ -517,15 +757,25 @@
   width: auto;
 }
 
-.jrpg-dialog-heading zen-button > button {
-  width: var(--zenbu-control-height);
+.jrpg-dialog-heading-actions {
+  display: flex;
+  align-items: center;
+  gap: var(--zenbu-sys-space-control);
+}
+
+.jrpg-dialog-heading zen-button > :where(button, a) {
+  width: auto;
   min-width: var(--zenbu-control-height);
-  padding: 0;
   border-color: var(--mjj-jrpg-accent);
   background: var(--mjj-jrpg-surface);
   color: var(--mjj-jrpg-text);
 }
 
+.jrpg-dialog-heading zen-button > button {
+  width: var(--zenbu-control-height);
+  padding: 0;
+}
+
 .jrpg-preview-dialog dialog h2 {
   margin-top: var(--zenbu-sys-space-content);
 }
@@ -546,6 +796,35 @@
   gap: var(--zenbu-sys-space-group);
 }
 
+.jrpg-preview-dialog dialog.jrpg-detail-dialog[data-detail-mode="tools"] {
+  width: calc(100vw - var(--zenbu-sys-space-content));
+  max-width: none;
+  height: calc(100dvh - var(--zenbu-sys-space-content));
+  max-height: none;
+  padding: 0;
+  border: 0;
+  background: transparent;
+  box-shadow: none;
+}
+
+.jrpg-preview-dialog dialog.jrpg-detail-dialog[data-detail-mode="tools"][open] {
+  grid-template-rows: auto minmax(0, 1fr);
+  gap: var(--zenbu-sys-space-control);
+}
+
+.jrpg-detail-dialog[data-detail-mode="tools"] > h2 {
+  display: none;
+}
+
+.jrpg-detail-dialog[data-detail-mode="tools"] .jrpg-dialog-heading {
+  padding: var(--zenbu-sys-padding-sm);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-frame);
+  background: var(--mjj-jrpg-surface-raised);
+  box-shadow:
+    inset 0 0 0 var(--zenbu-sys-stroke-width)
+    var(--mjj-jrpg-accent);
+}
+
 .jrpg-resume-dossier {
   min-height: 0;
   padding: var(--zenbu-sys-padding-lg);
@@ -557,9 +836,13 @@
 
 .jrpg-resume-dossier[hidden],
 .jrpg-blog-browser[hidden],
+.jrpg-tool-browser[hidden],
+[data-dialog-trigger-owner][hidden],
 [data-dialog-copy][hidden],
 [data-blog-status][hidden],
+[data-tool-status][hidden],
 [data-resume-status][hidden],
+[data-dialog-actions][hidden],
 [data-resume-download][hidden] {
   display: none;
 }
@@ -659,7 +942,7 @@
   gap: var(--zenbu-sys-space-control);
 }
 
-.jrpg-blog-browser {
+:is(.jrpg-blog-browser, .jrpg-tool-browser) {
   display: grid;
   grid-template-columns: minmax(12rem, 0.35fr) minmax(0, 1fr);
   gap: var(--zenbu-sys-space-group);
@@ -667,8 +950,8 @@
   overflow: hidden;
 }
 
-.jrpg-blog-browser > aside,
-.jrpg-blog-browser > article {
+:is(.jrpg-blog-browser, .jrpg-tool-browser) > aside,
+:is(.jrpg-blog-browser, .jrpg-tool-browser) > article {
   min-height: 0;
   padding: var(--zenbu-sys-padding-md);
   overflow: auto;
@@ -677,13 +960,35 @@
   scrollbar-color: var(--mjj-jrpg-frame) transparent;
 }
 
-.jrpg-blog-browser h3,
-.jrpg-blog-browser [data-blog-status] {
+.jrpg-tool-browser {
+  display: block;
+  height: 100%;
+}
+
+.jrpg-tool-browser > article {
+  height: 100%;
+  padding: 0;
+  overflow: hidden;
+  border: 0;
+  background: transparent;
+}
+
+.jrpg-tool-browser [data-tool-content],
+.jrpg-functional-tool,
+.jrpg-tool-panes {
+  height: 100%;
+  min-height: 0;
+}
+
+:is(.jrpg-blog-browser, .jrpg-tool-browser) h3,
+.jrpg-blog-browser [data-blog-status],
+.jrpg-tool-browser [data-tool-status] {
   margin-top: 0;
   color: var(--mjj-jrpg-highlight);
 }
 
-.jrpg-blog-browser [data-blog-list] {
+:is(.jrpg-blog-browser, .jrpg-tool-browser)
+  :is([data-blog-list], [data-tool-list]) {
   display: grid;
   gap: var(--zenbu-sys-space-control);
   margin: 0;
@@ -691,12 +996,15 @@
   list-style: none;
 }
 
-.jrpg-blog-browser [data-blog-list] zen-button,
-.jrpg-blog-browser [data-blog-list] button {
+:is(.jrpg-blog-browser, .jrpg-tool-browser)
+  :is([data-blog-list], [data-tool-list]) zen-button,
+:is(.jrpg-blog-browser, .jrpg-tool-browser)
+  :is([data-blog-list], [data-tool-list]) button {
   width: 100%;
 }
 
-.jrpg-blog-browser [data-blog-list] button {
+:is(.jrpg-blog-browser, .jrpg-tool-browser)
+  :is([data-blog-list], [data-tool-list]) button {
   display: grid;
   justify-items: start;
   gap: var(--zenbu-sys-space-icon-label);
@@ -708,40 +1016,51 @@
   cursor: pointer;
 }
 
-.jrpg-blog-browser [data-blog-list] button:hover,
-.jrpg-blog-browser [data-blog-list] button[aria-pressed="true"] {
+:is(.jrpg-blog-browser, .jrpg-tool-browser)
+  :is([data-blog-list], [data-tool-list]) button:hover,
+:is(.jrpg-blog-browser, .jrpg-tool-browser)
+  :is([data-blog-list], [data-tool-list]) button[aria-pressed="true"] {
   border-color: var(--mjj-jrpg-accent);
   background: var(--mjj-jrpg-surface-raised);
 }
 
-.jrpg-blog-browser [data-blog-list] small {
+:is(.jrpg-blog-browser, .jrpg-tool-browser)
+  :is([data-blog-list], [data-tool-list]) small {
   color: var(--mjj-jrpg-text-muted);
   font-size: var(--zenbu-sys-font-size-xs);
 }
 
-.jrpg-blog-browser [data-blog-content] {
+:is(.jrpg-blog-browser, .jrpg-tool-browser)
+  :is([data-blog-content], [data-tool-content]) {
   color: var(--mjj-jrpg-text);
   line-height: var(--zenbu-sys-line-height-lg);
 }
 
-.jrpg-blog-browser [data-blog-content] :where(h1, h2, h3, h4) {
+:is(.jrpg-blog-browser, .jrpg-tool-browser)
+  :is([data-blog-content], [data-tool-content])
+  :where(h1, h2, h3, h4) {
   color: var(--mjj-jrpg-primary);
 }
 
-.jrpg-blog-browser [data-blog-content] a {
+:is(.jrpg-blog-browser, .jrpg-tool-browser)
+  :is([data-blog-content], [data-tool-content]) a {
   color: var(--mjj-jrpg-primary);
   text-decoration-color: var(--mjj-jrpg-accent);
   text-underline-offset: var(--zenbu-sys-space-icon-label);
 }
 
-.jrpg-blog-browser [data-blog-content] :where(img, video) {
+:is(.jrpg-blog-browser, .jrpg-tool-browser)
+  :is([data-blog-content], [data-tool-content])
+  :where(img, video) {
   display: block;
   max-width: 100%;
   height: auto;
   margin-inline: auto;
 }
 
-.jrpg-blog-browser [data-blog-content] :where(pre, blockquote) {
+:is(.jrpg-blog-browser, .jrpg-tool-browser)
+  :is([data-blog-content], [data-tool-content])
+  :where(pre, blockquote) {
   max-width: 100%;
   padding: var(--zenbu-sys-padding-md);
   overflow: auto;
@@ -749,12 +1068,265 @@
   background: var(--mjj-jrpg-panel);
 }
 
-.jrpg-blog-browser [data-blog-content] code {
+:is(.jrpg-blog-browser, .jrpg-tool-browser)
+  :is([data-blog-content], [data-tool-content]) code {
   color: var(--mjj-jrpg-success);
   white-space: pre-wrap;
   overflow-wrap: anywhere;
 }
 
+.jrpg-tool-readonly-note {
+  padding: var(--zenbu-sys-padding-sm);
+  border: var(--zenbu-sys-stroke-width) solid var(--mjj-jrpg-highlight);
+  background: var(--mjj-jrpg-panel);
+  color: var(--mjj-jrpg-highlight);
+}
+
+.jrpg-functional-tool {
+  min-height: 100%;
+}
+
+.jrpg-functional-tool [hidden] {
+  display: none;
+}
+
+.jrpg-tool-panes {
+  position: relative;
+  box-sizing: border-box;
+  display: grid;
+  grid-template-columns:
+    minmax(0, 1fr)
+    calc(var(--zenbu-sys-space-container) * 2)
+    minmax(0, 1fr);
+  gap: var(--zenbu-sys-space-control);
+  height: 100%;
+  min-height: 0;
+  padding: var(--zenbu-sys-padding-sm);
+}
+
+.jrpg-tool-panes::before {
+  grid-column: 2;
+  grid-row: 1;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-frame);
+  background-image:
+    radial-gradient(
+      circle at 50% var(--zenbu-sys-space-content),
+      var(--mjj-jrpg-highlight) 0 var(--zenbu-sys-stroke-width-emphasis),
+      var(--mjj-jrpg-frame) var(--zenbu-sys-stroke-width-emphasis)
+        calc(var(--zenbu-sys-stroke-width-emphasis) * 2),
+      transparent calc(var(--zenbu-sys-stroke-width-emphasis) * 2)
+    ),
+    radial-gradient(
+      circle at 50% calc(100% - var(--zenbu-sys-space-content)),
+      var(--mjj-jrpg-highlight) 0 var(--zenbu-sys-stroke-width-emphasis),
+      var(--mjj-jrpg-frame) var(--zenbu-sys-stroke-width-emphasis)
+        calc(var(--zenbu-sys-stroke-width-emphasis) * 2),
+      transparent calc(var(--zenbu-sys-stroke-width-emphasis) * 2)
+    ),
+    linear-gradient(
+      90deg,
+      var(--mjj-jrpg-surface-sunken),
+      var(--mjj-jrpg-surface-raised) 45%,
+      var(--mjj-jrpg-frame) 50%,
+      var(--mjj-jrpg-surface-raised) 55%,
+      var(--mjj-jrpg-surface-sunken)
+    ),
+    var(--mjj-jrpg-art);
+  background-position: center;
+  background-size: auto, auto, auto, cover;
+  box-shadow:
+    inset 0 0 0 var(--zenbu-sys-stroke-width)
+    var(--mjj-jrpg-info),
+    0 0 var(--zenbu-sys-space-related)
+    color-mix(in srgb, var(--mjj-jrpg-primary) 65%, transparent);
+  content: "";
+  image-rendering: pixelated;
+}
+
+.jrpg-tool-window:first-of-type {
+  grid-column: 1;
+  grid-row: 1;
+}
+
+.jrpg-tool-window:last-of-type {
+  grid-column: 3;
+  grid-row: 1;
+}
+
+.jrpg-tool-pane {
+  display: grid;
+  grid-template-rows: auto minmax(0, 1fr) auto;
+  align-content: start;
+  gap: var(--zenbu-sys-space-control);
+  min-width: 0;
+  min-height: 0;
+  padding: var(--zenbu-sys-padding-md);
+  overflow: auto;
+  border: var(--zenbu-sys-stroke-width) solid var(--mjj-jrpg-frame-soft);
+  background: var(--mjj-jrpg-panel);
+}
+
+.jrpg-tool-window {
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-primary);
+  box-shadow:
+    inset 0 0 0 var(--zenbu-sys-stroke-width)
+    var(--mjj-jrpg-info),
+    0 0 0 var(--zenbu-sys-stroke-width-emphasis)
+    var(--mjj-jrpg-accent),
+    0 0 var(--zenbu-sys-space-control)
+    color-mix(in srgb, var(--mjj-jrpg-info) 68%, transparent);
+}
+
+.jrpg-tool-pane h2,
+.jrpg-tool-pane-heading {
+  margin: 0;
+  color: var(--mjj-jrpg-primary);
+}
+
+.jrpg-tool-pane h2 {
+  display: flex;
+  align-items: center;
+  gap: var(--zenbu-sys-space-icon-label);
+}
+
+.jrpg-tool-pane h2 zen-icon {
+  color: var(--mjj-jrpg-highlight);
+}
+
+.jrpg-tool-pane-heading {
+  display: flex;
+  align-items: baseline;
+  justify-content: space-between;
+  gap: var(--zenbu-sys-space-control);
+}
+
+.jrpg-tool-pane-heading h2 {
+  margin: 0;
+}
+
+.jrpg-functional-tool zen-field[appearance="plain"] {
+  display: grid;
+  grid-template-rows: auto minmax(0, 1fr);
+  gap: var(--zenbu-sys-space-icon-label);
+  min-height: 0;
+}
+
+.jrpg-functional-tool :where(input, textarea) {
+  box-sizing: border-box;
+  width: 100%;
+  min-height: var(--zenbu-control-height);
+  padding:
+    var(--zenbu-control-padding-block)
+    var(--zenbu-control-padding-inline);
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-frame);
+  border-radius: 0;
+  background: var(--mjj-jrpg-surface-sunken);
+  color: var(--mjj-jrpg-text);
+  font: inherit;
+}
+
+.jrpg-functional-tool textarea {
+  height: 100%;
+  min-height: 22rem;
+  resize: vertical;
+}
+
+.jrpg-functional-tool zen-button > :where(button, a) {
+  width: 100%;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-frame);
+  border-radius: 0;
+  background: var(--mjj-jrpg-primary);
+  color: var(--mjj-jrpg-primary-foreground);
+  cursor: pointer;
+}
+
+.jrpg-functional-tool zen-button > :where(button, a):hover {
+  border-color: var(--mjj-jrpg-primary-hover);
+  background: var(--mjj-jrpg-primary-hover);
+}
+
+.jrpg-functional-tool button:disabled {
+  opacity: var(--zenbu-sys-opacity-disabled);
+  cursor: not-allowed;
+}
+
+.jrpg-tool-actions {
+  display: flex;
+  gap: var(--zenbu-sys-space-control);
+}
+
+.jrpg-tool-actions zen-button {
+  flex: 1;
+}
+
+.jrpg-tool-status {
+  margin-top: 0;
+  padding: var(--zenbu-sys-padding-sm);
+  border-left: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-info);
+  background: var(--mjj-jrpg-panel);
+  color: var(--mjj-jrpg-text);
+}
+
+.jrpg-tool-status[data-state="ready"] {
+  border-left-color: var(--mjj-jrpg-success);
+  color: var(--mjj-jrpg-success);
+}
+
+.jrpg-tool-status[data-state="working"] {
+  border-left-color: var(--mjj-jrpg-highlight);
+  color: var(--mjj-jrpg-highlight);
+}
+
+.jrpg-tool-status[data-state="error"] {
+  border-left-color: var(--mjj-jrpg-accent);
+  color: var(--mjj-jrpg-accent);
+}
+
+.jrpg-markdown-output {
+  min-height: 22rem;
+  padding: var(--zenbu-sys-padding-md);
+  overflow: auto;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-frame);
+  background: var(--mjj-jrpg-surface-sunken);
+}
+
+.jrpg-markdown-output :where(h1, h2, h3) {
+  color: var(--mjj-jrpg-primary);
+}
+
+.jrpg-markdown-output code {
+  color: var(--mjj-jrpg-success);
+}
+
+.jrpg-functional-tool :where(video, iframe) {
+  width: 100%;
+  min-height: 22rem;
+  border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-frame);
+  background: var(--mjj-jrpg-canvas);
+}
+
+.jrpg-tool-details {
+  display: grid;
+  grid-template-columns: repeat(2, minmax(0, 1fr));
+  gap: var(--zenbu-sys-space-control);
+  margin: 0;
+}
+
+.jrpg-tool-details div {
+  padding: var(--zenbu-sys-padding-sm);
+  border: var(--zenbu-sys-stroke-width) solid var(--mjj-jrpg-frame-soft);
+}
+
+.jrpg-tool-details dd {
+  margin: var(--zenbu-sys-space-icon-label) 0 0;
+  color: var(--mjj-jrpg-success);
+}
+
+.jrpg-functional-tool [data-converter-download] {
+  color: var(--mjj-jrpg-primary);
+  text-decoration-color: var(--mjj-jrpg-accent);
+}
+
 mjj-jrpg-composer {
   grid-area: composer;
   display: block;
@@ -928,7 +1500,48 @@
   opacity: 1;
 }
 
-@media (max-width: 52rem) {
+.jrpg-workspace > :is(
+  .jrpg-scene,
+  .jrpg-utility,
+  mjj-jrpg-composer,
+  mjj-jrpg-menu
+),
+.jrpg-scene > mjj-jrpg-chat,
+.jrpg-utility > mjj-jrpg-preview > .jrpg-preview-panel {
+  border: 0;
+  background-color: transparent;
+  box-shadow: none;
+}
+
+.jrpg-workspace > .jrpg-scene {
+  background-image: none;
+}
+
+.jrpg-workspace > mjj-jrpg-composer,
+.jrpg-workspace > mjj-jrpg-menu {
+  padding: var(--zenbu-sys-padding-sm);
+}
+
+.jrpg-workspace > mjj-jrpg-composer textarea {
+  min-height: 0;
+}
+
+.jrpg-scene .jrpg-panel-heading,
+.jrpg-scene .jrpg-message,
+.jrpg-scene .jrpg-turn-navigation,
+.jrpg-brand,
+.jrpg-work-showcase a,
+.jrpg-preview-panel > .jrpg-preview-dialog > zen-button > button,
+mjj-jrpg-composer > .jrpg-composer textarea,
+mjj-jrpg-composer > .jrpg-composer zen-button > button,
+mjj-jrpg-menu nav button {
+  border: 0;
+}
+
+@media
+  (max-width: 52rem),
+  (max-height: 40rem),
+  (min-aspect-ratio: 2 / 1) {
   .jrpg-page {
     overflow-y: auto;
   }
@@ -945,14 +1558,82 @@
   }
 
   .jrpg-workspace {
+    display: grid;
     grid-template:
+      "brand" auto
       "scene" auto
       "utility" auto
       "menu" auto
-      "composer" auto /
+      "composer" auto
+      "telemetry" auto /
       minmax(0, 1fr);
+    gap: var(--zenbu-sys-space-group);
+    width: 100%;
+    max-height: none;
     height: auto;
+    aspect-ratio: auto;
     min-height: 0;
+    background-size: cover;
+  }
+
+  .jrpg-workspace > .jrpg-scene,
+  .jrpg-workspace > .jrpg-utility,
+  .jrpg-workspace > mjj-jrpg-composer,
+  .jrpg-workspace > mjj-jrpg-menu,
+  .jrpg-workspace > .jrpg-brand,
+  .jrpg-workspace > .jrpg-frame-controls,
+  .jrpg-workspace > .jrpg-frame-telemetry {
+    position: relative;
+    inset: auto;
+    width: auto;
+    height: auto;
+  }
+
+  .jrpg-workspace > .jrpg-brand {
+    grid-area: brand;
+    justify-self: start;
+    padding: var(--zenbu-sys-padding-sm);
+    background: transparent;
+    box-shadow: none;
+  }
+
+  .jrpg-workspace > .jrpg-frame-controls {
+    grid-area: brand;
+    justify-self: end;
+    align-self: center;
+    display: flex;
+    gap: var(--zenbu-sys-space-icon-label);
+  }
+
+  .jrpg-frame-controls zen-button,
+  .jrpg-frame-controls :where(button, a) {
+    width: var(--zenbu-control-height);
+    height: var(--zenbu-control-height);
+  }
+
+  .jrpg-frame-controls :where(button, a) {
+    background: var(--mjj-jrpg-surface-raised);
+    color: var(--mjj-jrpg-text);
+  }
+
+  .jrpg-frame-controls zen-icon {
+    opacity: 1;
+  }
+
+  .jrpg-workspace > .jrpg-frame-telemetry {
+    grid-area: telemetry;
+    display: grid;
+    grid-template-columns: repeat(2, minmax(0, 1fr));
+    gap: var(--zenbu-sys-space-control);
+    padding: var(--zenbu-sys-padding-sm);
+    background: var(--mjj-jrpg-surface-sunken);
+  }
+
+  .jrpg-frame-telemetry > * {
+    position: static;
+    justify-self: start;
+    background: transparent;
+    transform: none;
   }
 
   .jrpg-scene {
@@ -1001,10 +1682,6 @@
     align-items: center;
   }
 
-  .jrpg-brand > p {
-    max-width: 9rem;
-  }
-
   .jrpg-composer {
     grid-template-columns: 1fr;
     grid-template-rows:
@@ -1046,15 +1723,66 @@
     width: 100%;
   }
 
-  .jrpg-blog-browser {
+  :is(.jrpg-blog-browser, .jrpg-tool-browser) {
     grid-template-columns: 1fr;
     overflow: auto;
   }
 
-  .jrpg-blog-browser > aside {
+  :is(.jrpg-blog-browser, .jrpg-tool-browser) > aside {
     max-height: 16rem;
   }
 
+  .jrpg-tool-panes {
+    grid-template-columns: 1fr;
+    grid-template-rows:
+      minmax(24rem, auto)
+      calc(var(--zenbu-sys-space-container) * 2)
+      minmax(24rem, auto);
+    overflow: auto;
+  }
+
+  .jrpg-tool-panes::before {
+    grid-column: 1;
+    grid-row: 2;
+    background-image:
+      radial-gradient(
+        circle at var(--zenbu-sys-space-content) 50%,
+        var(--mjj-jrpg-highlight) 0 var(--zenbu-sys-stroke-width-emphasis),
+        var(--mjj-jrpg-frame) var(--zenbu-sys-stroke-width-emphasis)
+          calc(var(--zenbu-sys-stroke-width-emphasis) * 2),
+        transparent calc(var(--zenbu-sys-stroke-width-emphasis) * 2)
+      ),
+      radial-gradient(
+        circle at calc(100% - var(--zenbu-sys-space-content)) 50%,
+        var(--mjj-jrpg-highlight) 0 var(--zenbu-sys-stroke-width-emphasis),
+        var(--mjj-jrpg-frame) var(--zenbu-sys-stroke-width-emphasis)
+          calc(var(--zenbu-sys-stroke-width-emphasis) * 2),
+        transparent calc(var(--zenbu-sys-stroke-width-emphasis) * 2)
+      ),
+      linear-gradient(
+        var(--mjj-jrpg-surface-sunken),
+        var(--mjj-jrpg-surface-raised) 45%,
+        var(--mjj-jrpg-frame) 50%,
+        var(--mjj-jrpg-surface-raised) 55%,
+        var(--mjj-jrpg-surface-sunken)
+      ),
+      var(--mjj-jrpg-art);
+  }
+
+  .jrpg-tool-window:first-of-type {
+    grid-column: 1;
+    grid-row: 1;
+  }
+
+  .jrpg-tool-window:last-of-type {
+    grid-column: 1;
+    grid-row: 3;
+  }
+
+  .jrpg-tool-pane {
+    min-height: 24rem;
+  }
+
   mjj-jrpg-menu ul {
     grid-template-columns: 1fr;
   }
@@ -1073,8 +1801,39 @@
   }
 }
 
+.jrpg-page,
+.jrpg-page * {
+  scrollbar-color: var(--mjj-jrpg-primary) transparent;
+  scrollbar-width: thin;
+}
+
+.jrpg-page::-webkit-scrollbar,
+.jrpg-page *::-webkit-scrollbar {
+  width: var(--zenbu-sys-space-related);
+  height: var(--zenbu-sys-space-related);
+}
+
+.jrpg-page::-webkit-scrollbar-track,
+.jrpg-page *::-webkit-scrollbar-track {
+  background: transparent;
+}
+
+.jrpg-page::-webkit-scrollbar-thumb,
+.jrpg-page *::-webkit-scrollbar-thumb {
+  border: 0;
+  border-radius: 0;
+  background: var(--mjj-jrpg-primary);
+}
+
+.jrpg-page::-webkit-scrollbar-button,
+.jrpg-page *::-webkit-scrollbar-button {
+  display: none;
+}
+
 @media (forced-colors: active) {
-  .jrpg-scene {
+  .jrpg-workspace,
+  .jrpg-scene,
+  .jrpg-scene::before {
     background-image: none;
   }
 }