@bloopjs/web 0.0.91 → 0.0.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/debugui/components/BottomBar.d.ts.map +1 -1
- package/dist/debugui/state.d.ts +1 -0
- package/dist/debugui/state.d.ts.map +1 -1
- package/dist/debugui/styles.d.ts +1 -1
- package/dist/debugui/styles.d.ts.map +1 -1
- package/dist/mod.js +250 -26
- package/dist/mod.js.map +7 -7
- package/package.json +3 -3
- package/src/debugui/components/BottomBar.tsx +15 -5
- package/src/debugui/state.ts +18 -3
- package/src/debugui/styles.ts +173 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomBar.d.ts","sourceRoot":"","sources":["../../../src/debugui/components/BottomBar.tsx"],"names":[],"mappings":"AAiFA,wBAAgB,SAAS,
|
|
1
|
+
{"version":3,"file":"BottomBar.d.ts","sourceRoot":"","sources":["../../../src/debugui/components/BottomBar.tsx"],"names":[],"mappings":"AAiFA,wBAAgB,SAAS,4CAuGxB"}
|
package/dist/debugui/state.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ export type DebugState = {
|
|
|
41
41
|
onSeek: Signal<((position: number) => void) | null>;
|
|
42
42
|
onLoadTape: Signal<((bytes: Uint8Array, fileName: string) => void) | null>;
|
|
43
43
|
onReplayLastTape: Signal<(() => void) | null>;
|
|
44
|
+
onSaveTape: Signal<(() => void) | null>;
|
|
44
45
|
lastTapeName: Signal<string | null>;
|
|
45
46
|
isLoadDialogOpen: Signal<boolean>;
|
|
46
47
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/debugui/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,MAAM,EAEZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAClC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,aAAa,GAAG,MAAM,CAAC;AAExD,MAAM,MAAM,IAAI,GAAG;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,WAAW,CAAC;IACjB,GAAG,EAAE,WAAW,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,IAAI,EAAE,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAC/B,SAAS,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IACpB,IAAI,EAAE,cAAc,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAClC,SAAS,EAAE,cAAc,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAEzC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAE5B,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAE1B,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAChC,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAE/B,UAAU,EAAE,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACxC,UAAU,EAAE,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACxC,WAAW,EAAE,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IACzC,aAAa,EAAE,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3C,aAAa,EAAE,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3C,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAEpD,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3E,gBAAgB,EAAE,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;IAC9C,YAAY,EAAE,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACpC,gBAAgB,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;CACnC,CAAC;
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/debugui/state.ts"],"names":[],"mappings":"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"}
|
package/dist/debugui/styles.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const styles = "\n/* Reset for shadow DOM */\n* {\n box-sizing: border-box;\n}\n\n/* Layout */\n.fullscreen {\n width: 100vw;\n height: 100vh;\n margin: 0;\n padding: 0;\n overflow: hidden;\n}\n\n.fullscreen .canvas-container {\n width: 100%;\n height: 100%;\n}\n\n.fullscreen canvas {\n width: 100%;\n height: 100%;\n display: block;\n}\n\n.layout {\n display: grid;\n grid-template-areas:\n \"game stats\"\n \"logs logs\";\n grid-template-columns: calc(50% - 0.5rem) calc(50% - 0.5rem);\n grid-template-rows: calc(50% - 0.5rem) calc(50% - 0.5rem);\n gap: 1rem;\n width: 100%;\n height: 100%;\n padding: 1rem;\n}\n\n/* Letterboxed layout - using equal vw/vh percentages keeps game at viewport aspect ratio */\n.layout-letterboxed {\n display: grid;\n grid-template-areas:\n \"top-bar top-bar top-bar\"\n \"left-bar game right-bar\"\n \"bottom-bar bottom-bar bottom-bar\";\n grid-template-columns: 2vw 1fr 2vw;\n grid-template-rows: 2vh 1fr 2vh;\n width: 100vw;\n height: 100vh;\n background: #1a1a1a;\n overflow: hidden;\n overscroll-behavior: none;\n}\n\n.top-bar {\n grid-area: top-bar;\n display: flex;\n align-items: center;\n justify-content: space-between;\n background: #111;\n color: #aaa;\n font-family: monospace;\n font-size: 12px;\n padding: 0;\n}\n\n.top-bar-side-label {\n width: 2vw;\n text-align: center;\n font-size: 9px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: #666;\n}\n\n.top-bar-center {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 24px;\n flex: 1;\n}\n\n.top-bar-item {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.top-bar-label {\n opacity: 0.6;\n}\n\n.top-bar-value {\n color: #fff;\n font-weight: 500;\n}\n\n.left-bar {\n grid-area: left-bar;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: flex-end;\n background: #111;\n padding: 4px 0;\n}\n\n.right-bar {\n grid-area: right-bar;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: flex-end;\n background: #111;\n padding: 4px 0;\n}\n\n.vertical-bar {\n width: 12px;\n flex: 1;\n background: #333;\n border-radius: 2px;\n position: relative;\n overflow: hidden;\n}\n\n.vertical-bar-fill {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: #4a9eff;\n border-radius: 2px;\n transition: height 0.1s ease-out;\n}\n\n\n.bottom-bar {\n grid-area: bottom-bar;\n display: flex;\n align-items: center;\n background: #111;\n padding: 0 8px;\n gap: 8px;\n}\n\n.playbar-controls {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n}\n\n.playbar-btn {\n width: 1.5vh;\n height: 1.5vh;\n min-width: 18px;\n min-height: 18px;\n border: none;\n outline: none;\n background: transparent;\n color: #888;\n font-size: 10px;\n cursor: pointer;\n border-radius: 2px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, color 0.15s;\n position: relative;\n}\n\n.playbar-btn:hover {\n background: #333;\n color: #fff;\n}\n\n.playbar-btn:hover .tooltip {\n opacity: 1;\n visibility: visible;\n}\n\n.tooltip {\n position: absolute;\n bottom: calc(100% + 4px);\n left: 50%;\n transform: translateX(-50%);\n background: #222;\n color: #ccc;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 10px;\n white-space: nowrap;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.15s;\n pointer-events: none;\n z-index: 10;\n}\n\n.tooltip-left {\n left: 0;\n transform: none;\n}\n\n.tooltip kbd {\n background: #444;\n padding: 1px 4px;\n border-radius: 2px;\n margin-left: 4px;\n font-family: monospace;\n}\n\n.seek-bar {\n flex: 1;\n height: 16px;\n background: #222;\n border-radius: 4px;\n position: relative;\n cursor: pointer;\n overflow: hidden;\n}\n\n.seek-bar-fill {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n background: linear-gradient(to right, #4a2070, #7b3fa0);\n border-radius: 4px;\n transition: width 0.1s ease-out;\n}\n\n.seek-bar-position {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 2px;\n background: #fff;\n}\n\n.letterboxed-game {\n grid-area: game;\n overflow: hidden;\n}\n\n.letterboxed-game .canvas-container {\n width: 100%;\n height: 100%;\n}\n\n.letterboxed-game canvas {\n width: 100%;\n height: 100%;\n display: block;\n}\n\n.letterboxed-game {\n position: relative;\n}\n\n.letterboxed-game.hmr-flash::after {\n content: \"\";\n position: absolute;\n inset: 0;\n pointer-events: none;\n animation: hmr-pulse 0.3s ease-out forwards;\n}\n\n@keyframes hmr-pulse {\n 0% { box-shadow: inset 0 0 0 36px #7b3fa0; }\n 100% { box-shadow: inset 0 0 0 0 #7b3fa0; }\n}\n\n.game {\n grid-area: game;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.stats {\n grid-area: stats;\n background-color: #f0f0f0;\n padding: 1rem;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.logs {\n grid-area: logs;\n background-color: #f0f0f0;\n padding: 1rem;\n border-radius: 8px;\n overflow: hidden;\n}\n\n/* Canvas container */\n.canvas-container {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.canvas-container canvas {\n max-width: 100%;\n max-height: 100%;\n}\n\n/* Debug toggle button */\n.debug-toggle {\n position: fixed;\n bottom: 16px;\n right: 16px;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background-color: rgba(0, 0, 0, 0.5);\n color: white;\n font-size: 18px;\n cursor: pointer;\n z-index: 1000;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.2s;\n}\n\n.debug-toggle:hover {\n background-color: rgba(0, 0, 0, 0.7);\n}\n\n/* Stats panel */\n.stats-panel {\n background: rgba(0, 0, 0, 0.7);\n color: white;\n padding: 12px;\n border-radius: 8px;\n font-family: monospace;\n font-size: 14px;\n max-width: 100%;\n overflow: hidden;\n}\n\n.stats-panel h3 {\n margin: 0 0 8px 0;\n font-size: 14px;\n font-weight: 600;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.stats-panel table {\n width: 100%;\n border-collapse: collapse;\n table-layout: fixed;\n}\n\n.stats-panel tr {\n border-bottom: 1px solid rgba(255, 255, 255, 0.2);\n}\n\n.stats-panel tr:last-child {\n border-bottom: none;\n}\n\n.stats-panel td {\n padding: 4px 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.stats-panel td:first-child {\n opacity: 0.7;\n width: 60%;\n}\n\n.stats-panel td:last-child {\n text-align: right;\n font-weight: 600;\n width: 40%;\n}\n\n.stats-panel p {\n margin: 0;\n opacity: 0.7;\n}\n\n/* Logs panel */\n.logs-list {\n width: 100%;\n height: 100%;\n overflow: auto;\n margin: 0;\n padding: 0;\n}\n\n.logs-list li {\n margin: 0 0 24px 0;\n list-style: none;\n}\n\n.logs-list h3 {\n font-size: 16px;\n font-weight: 500;\n margin: 0;\n}\n\n.logs-list .ws {\n color: darkolivegreen;\n}\n\n.logs-list .webrtc {\n color: darkmagenta;\n}\n\n.logs-list .rollback {\n color: darkblue;\n}\n\n.logs-list .local {\n color: #333;\n}\n\n.logs-list .content {\n font-size: 16px;\n}\n\n.logs-list p {\n margin: 4px 0;\n}\n\n.logs-list pre {\n margin: 0;\n white-space: pre-wrap;\n word-break: break-word;\n background-color: oldlace;\n padding: 8px;\n border-radius: 4px;\n border: 1px inset lavender;\n}\n\n/* Load Tape Dialog */\n.load-tape-dialog {\n background: #1a1a1a;\n border: 1px solid #333;\n border-radius: 8px;\n padding: 0;\n color: #ccc;\n font-family: monospace;\n max-width: 320px;\n width: 90vw;\n}\n\n.load-tape-dialog::backdrop {\n background: rgba(0, 0, 0, 0.7);\n}\n\n.load-tape-dialog-content {\n padding: 16px;\n}\n\n.load-tape-dialog h3 {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: #fff;\n}\n\n.drop-zone {\n border: 2px dashed #444;\n border-radius: 8px;\n padding: 32px 16px;\n text-align: center;\n cursor: pointer;\n transition: border-color 0.15s, background 0.15s;\n}\n\n.drop-zone:hover {\n border-color: #666;\n background: #222;\n}\n\n.drop-zone.drag-over {\n border-color: #7b3fa0;\n background: rgba(123, 63, 160, 0.1);\n}\n\n.drop-zone-text {\n color: #888;\n font-size: 12px;\n line-height: 1.5;\n}\n\n.hidden-file-input {\n display: none;\n}\n\n.replay-last-btn {\n width: 100%;\n margin-top: 12px;\n padding: 8px 12px;\n background: #333;\n border: none;\n border-radius: 4px;\n color: #ccc;\n font-family: monospace;\n font-size: 12px;\n cursor: pointer;\n transition: background 0.15s;\n text-align: left;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.replay-last-btn:hover {\n background: #444;\n color: #fff;\n}\n\n.load-tape-btn {\n margin-left: 4px;\n}\n";
|
|
1
|
+
export declare const styles = "\n/* Reset for shadow DOM */\n* {\n box-sizing: border-box;\n}\n\n/* Mobile-first CSS variables */\n:host {\n --bar-size: 10vw;\n --bar-size-h: 10vh;\n --bar-size-h: 10dvh;\n}\n\n/* Desktop overrides */\n@media (min-width: 769px) {\n :host {\n --bar-size: 2vw;\n --bar-size-h: 2vh;\n }\n}\n\n/* Layout */\n.fullscreen {\n width: 100vw;\n height: 100vh;\n height: 100dvh;\n margin: 0;\n padding: 0;\n overflow: hidden;\n}\n\n.fullscreen .canvas-container {\n width: 100%;\n height: 100%;\n}\n\n.fullscreen canvas {\n width: 100%;\n height: 100%;\n display: block;\n}\n\n/* Mobile-first: vertical scroll layout */\n.layout {\n /* Use fixed position on mobile to escape parent overflow:hidden */\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n flex-direction: column;\n overflow-y: auto;\n overflow-x: hidden;\n -webkit-overflow-scrolling: touch;\n overscroll-behavior-y: contain;\n padding: 0;\n gap: 0;\n background: #1a1a1a;\n}\n\n.layout .game {\n /* Use dvh with vh fallback for mobile Safari address bar */\n height: 100vh;\n height: 100dvh;\n width: 100%;\n flex-shrink: 0;\n /* Mobile: no border radius, fullscreen game */\n border-radius: 0;\n}\n\n/* Mobile: stretch canvas to fill game area */\n.layout .game .canvas-container {\n width: 100%;\n height: 100%;\n}\n\n.layout .game .canvas-container canvas {\n width: 100%;\n height: 100%;\n max-width: none;\n max-height: none;\n display: block;\n}\n\n.layout .stats,\n.layout .logs {\n width: 100%;\n min-height: 50vh;\n min-height: 50dvh;\n padding: 1rem;\n flex-shrink: 0;\n}\n\n/* Desktop: 2x2 grid layout */\n@media (min-width: 769px) {\n .layout {\n position: static;\n display: grid;\n grid-template-areas:\n \"game stats\"\n \"logs logs\";\n grid-template-columns: calc(50% - 0.5rem) calc(50% - 0.5rem);\n grid-template-rows: calc(50% - 0.5rem) calc(50% - 0.5rem);\n gap: 1rem;\n padding: 1rem;\n height: 100%;\n overflow: hidden;\n -webkit-overflow-scrolling: auto;\n overscroll-behavior-y: auto;\n }\n\n .layout .game {\n height: auto;\n flex-shrink: initial;\n border-radius: 8px;\n }\n\n /* Desktop: restore centered canvas with constraints */\n .layout .game .canvas-container canvas {\n width: auto;\n height: auto;\n max-width: 100%;\n max-height: 100%;\n }\n\n .layout .stats,\n .layout .logs {\n min-height: auto;\n padding: 1rem;\n flex-shrink: initial;\n }\n}\n\n/* Letterboxed layout - using equal vw/vh percentages keeps game at viewport aspect ratio */\n.layout-letterboxed {\n display: grid;\n grid-template-areas:\n \"top-bar top-bar top-bar\"\n \"left-bar game right-bar\"\n \"bottom-bar bottom-bar bottom-bar\";\n grid-template-columns: var(--bar-size) 1fr var(--bar-size);\n grid-template-rows: var(--bar-size-h) 1fr var(--bar-size-h);\n width: 100vw;\n /* Use dvh with vh fallback for mobile Safari address bar */\n height: 100vh;\n height: 100dvh;\n background: #1a1a1a;\n overflow: hidden;\n overscroll-behavior: none;\n}\n\n.top-bar {\n grid-area: top-bar;\n display: flex;\n align-items: center;\n justify-content: space-between;\n background: #111;\n color: #aaa;\n font-family: monospace;\n font-size: 12px;\n padding: 0;\n}\n\n.top-bar-side-label {\n width: var(--bar-size);\n text-align: center;\n font-size: 9px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: #666;\n}\n\n/* Mobile: larger top bar text */\n@media (max-width: 768px) {\n .top-bar-side-label {\n font-size: 12px;\n }\n\n .top-bar {\n font-size: 14px;\n }\n}\n\n.top-bar-center {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 24px;\n flex: 1;\n}\n\n.top-bar-item {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.top-bar-label {\n opacity: 0.6;\n}\n\n.top-bar-value {\n color: #fff;\n font-weight: 500;\n}\n\n.left-bar {\n grid-area: left-bar;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: flex-end;\n background: #111;\n padding: 4px 0;\n}\n\n.right-bar {\n grid-area: right-bar;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: flex-end;\n background: #111;\n padding: 4px 0;\n}\n\n.vertical-bar {\n width: 12px;\n flex: 1;\n background: #333;\n border-radius: 2px;\n position: relative;\n overflow: hidden;\n}\n\n.vertical-bar-fill {\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: #4a9eff;\n border-radius: 2px;\n transition: height 0.1s ease-out;\n}\n\n\n.bottom-bar {\n grid-area: bottom-bar;\n display: flex;\n align-items: center;\n background: #111;\n /* Mobile-first: more padding */\n padding: 0 16px;\n gap: 12px;\n}\n\n/* Desktop: tighter padding */\n@media (min-width: 769px) {\n .bottom-bar {\n padding: 0 8px;\n gap: 8px;\n }\n}\n\n.playbar-controls {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-shrink: 0;\n}\n\n/* Mobile-first: hide step/jump buttons */\n.playbar-btn.jump-back,\n.playbar-btn.step-back,\n.playbar-btn.step-forward,\n.playbar-btn.jump-forward {\n display: none;\n}\n\n/* Desktop: show all controls */\n@media (min-width: 769px) {\n .playbar-btn.jump-back,\n .playbar-btn.step-back,\n .playbar-btn.step-forward,\n .playbar-btn.jump-forward {\n display: flex;\n }\n}\n\n.playbar-btn {\n /* Mobile-first: larger buttons */\n width: 4vh;\n height: 4vh;\n min-width: 32px;\n min-height: 32px;\n border: none;\n outline: none;\n background: transparent;\n color: #888;\n font-size: 16px;\n cursor: pointer;\n border-radius: 2px;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.15s, color 0.15s;\n position: relative;\n}\n\n/* Desktop: smaller buttons */\n@media (min-width: 769px) {\n .playbar-btn {\n width: 1.5vh;\n height: 1.5vh;\n min-width: 18px;\n min-height: 18px;\n font-size: 10px;\n }\n}\n\n.playbar-btn:hover {\n background: #333;\n color: #fff;\n}\n\n.playbar-btn:hover .tooltip {\n opacity: 1;\n visibility: visible;\n}\n\n.tooltip {\n position: absolute;\n bottom: calc(100% + 4px);\n left: 50%;\n transform: translateX(-50%);\n background: #222;\n color: #ccc;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 10px;\n white-space: nowrap;\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.15s;\n pointer-events: none;\n z-index: 10;\n}\n\n.tooltip-left {\n left: 0;\n transform: none;\n}\n\n.tooltip kbd {\n background: #444;\n padding: 1px 4px;\n border-radius: 2px;\n margin-left: 4px;\n font-family: monospace;\n}\n\n.seek-bar {\n flex: 1;\n /* Mobile-first: larger seek bar */\n height: 32px;\n background: #222;\n border-radius: 4px;\n position: relative;\n cursor: pointer;\n overflow: hidden;\n}\n\n/* Desktop: smaller seek bar */\n@media (min-width: 769px) {\n .seek-bar {\n height: 16px;\n }\n}\n\n.seek-bar-fill {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n background: linear-gradient(to right, #4a2070, #7b3fa0);\n border-radius: 4px;\n transition: width 0.1s ease-out;\n}\n\n.seek-bar-position {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 2px;\n background: #fff;\n}\n\n.letterboxed-game {\n grid-area: game;\n overflow: hidden;\n}\n\n.letterboxed-game .canvas-container {\n width: 100%;\n height: 100%;\n}\n\n.letterboxed-game canvas {\n width: 100%;\n height: 100%;\n display: block;\n}\n\n.letterboxed-game {\n position: relative;\n}\n\n.letterboxed-game.hmr-flash::after {\n content: \"\";\n position: absolute;\n inset: 0;\n pointer-events: none;\n animation: hmr-pulse 0.3s ease-out forwards;\n}\n\n@keyframes hmr-pulse {\n 0% { box-shadow: inset 0 0 0 36px #7b3fa0; }\n 100% { box-shadow: inset 0 0 0 0 #7b3fa0; }\n}\n\n.game {\n grid-area: game;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.stats {\n grid-area: stats;\n background-color: #f0f0f0;\n padding: 1rem;\n border-radius: 8px;\n overflow: hidden;\n}\n\n.logs {\n grid-area: logs;\n background-color: #f0f0f0;\n padding: 1rem;\n border-radius: 8px;\n overflow: hidden;\n}\n\n/* Canvas container */\n.canvas-container {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.canvas-container canvas {\n max-width: 100%;\n max-height: 100%;\n}\n\n/* Debug toggle button */\n.debug-toggle {\n position: fixed;\n bottom: 16px;\n right: 16px;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background-color: rgba(0, 0, 0, 0.5);\n color: white;\n font-size: 18px;\n cursor: pointer;\n z-index: 1000;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.2s;\n}\n\n.debug-toggle:hover {\n background-color: rgba(0, 0, 0, 0.7);\n}\n\n/* Stats panel */\n.stats-panel {\n background: rgba(0, 0, 0, 0.7);\n color: white;\n padding: 12px;\n border-radius: 8px;\n font-family: monospace;\n font-size: 14px;\n max-width: 100%;\n overflow: hidden;\n}\n\n.stats-panel h3 {\n margin: 0 0 8px 0;\n font-size: 14px;\n font-weight: 600;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.stats-panel table {\n width: 100%;\n border-collapse: collapse;\n table-layout: fixed;\n}\n\n.stats-panel tr {\n border-bottom: 1px solid rgba(255, 255, 255, 0.2);\n}\n\n.stats-panel tr:last-child {\n border-bottom: none;\n}\n\n.stats-panel td {\n padding: 4px 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.stats-panel td:first-child {\n opacity: 0.7;\n width: 60%;\n}\n\n.stats-panel td:last-child {\n text-align: right;\n font-weight: 600;\n width: 40%;\n}\n\n.stats-panel p {\n margin: 0;\n opacity: 0.7;\n}\n\n/* Logs panel */\n.logs-list {\n width: 100%;\n height: 100%;\n overflow: auto;\n margin: 0;\n padding: 0;\n}\n\n.logs-list li {\n margin: 0 0 24px 0;\n list-style: none;\n}\n\n.logs-list h3 {\n font-size: 16px;\n font-weight: 500;\n margin: 0;\n}\n\n.logs-list .ws {\n color: darkolivegreen;\n}\n\n.logs-list .webrtc {\n color: darkmagenta;\n}\n\n.logs-list .rollback {\n color: darkblue;\n}\n\n.logs-list .local {\n color: #333;\n}\n\n.logs-list .content {\n font-size: 16px;\n}\n\n.logs-list p {\n margin: 4px 0;\n}\n\n.logs-list pre {\n margin: 0;\n white-space: pre-wrap;\n word-break: break-word;\n background-color: oldlace;\n padding: 8px;\n border-radius: 4px;\n border: 1px inset lavender;\n}\n\n/* Load Tape Dialog */\n.load-tape-dialog {\n background: #1a1a1a;\n border: 1px solid #333;\n border-radius: 8px;\n padding: 0;\n color: #ccc;\n font-family: monospace;\n max-width: 320px;\n width: 90vw;\n}\n\n.load-tape-dialog::backdrop {\n background: rgba(0, 0, 0, 0.7);\n}\n\n.load-tape-dialog-content {\n padding: 16px;\n}\n\n.load-tape-dialog h3 {\n margin: 0 0 16px 0;\n font-size: 14px;\n font-weight: 600;\n color: #fff;\n}\n\n.drop-zone {\n border: 2px dashed #444;\n border-radius: 8px;\n padding: 32px 16px;\n text-align: center;\n cursor: pointer;\n transition: border-color 0.15s, background 0.15s;\n}\n\n.drop-zone:hover {\n border-color: #666;\n background: #222;\n}\n\n.drop-zone.drag-over {\n border-color: #7b3fa0;\n background: rgba(123, 63, 160, 0.1);\n}\n\n.drop-zone-text {\n color: #888;\n font-size: 12px;\n line-height: 1.5;\n}\n\n.hidden-file-input {\n display: none;\n}\n\n.replay-last-btn {\n width: 100%;\n margin-top: 12px;\n padding: 8px 12px;\n background: #333;\n border: none;\n border-radius: 4px;\n color: #ccc;\n font-family: monospace;\n font-size: 12px;\n cursor: pointer;\n transition: background 0.15s;\n text-align: left;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.replay-last-btn:hover {\n background: #444;\n color: #fff;\n}\n\n.load-tape-btn {\n margin-left: 4px;\n}\n";
|
|
2
2
|
//# sourceMappingURL=styles.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/debugui/styles.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../src/debugui/styles.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM,itXA6qBlB,CAAC"}
|
package/dist/mod.js
CHANGED
|
@@ -415,6 +415,7 @@ var NET_CTX_PEERS_OFFSET = 32;
|
|
|
415
415
|
var NET_CTX_LAST_ROLLBACK_DEPTH_OFFSET = 128;
|
|
416
416
|
var NET_CTX_TOTAL_ROLLBACKS_OFFSET = 132;
|
|
417
417
|
var NET_CTX_FRAMES_RESIMULATED_OFFSET = 136;
|
|
418
|
+
var NET_CTX_CONFIRMED_MATCH_FRAME_OFFSET = 144;
|
|
418
419
|
var SCREEN_CTX_WIDTH_OFFSET = 0;
|
|
419
420
|
var SCREEN_CTX_HEIGHT_OFFSET = 4;
|
|
420
421
|
var SCREEN_CTX_PHYSICAL_WIDTH_OFFSET = 8;
|
|
@@ -1334,6 +1335,23 @@ class NetContext {
|
|
|
1334
1335
|
}
|
|
1335
1336
|
return Number(this.dataView.getBigUint64(NET_CTX_FRAMES_RESIMULATED_OFFSET, true));
|
|
1336
1337
|
}
|
|
1338
|
+
get confirmedMatchFrame() {
|
|
1339
|
+
if (!this.#hasValidBuffer()) {
|
|
1340
|
+
throw new Error("NetContext dataView is not valid");
|
|
1341
|
+
}
|
|
1342
|
+
return this.dataView.getInt32(NET_CTX_CONFIRMED_MATCH_FRAME_OFFSET, true);
|
|
1343
|
+
}
|
|
1344
|
+
get isConfirmFrame() {
|
|
1345
|
+
if (this.peerCount <= 1)
|
|
1346
|
+
return true;
|
|
1347
|
+
const confirmed = this.confirmedMatchFrame;
|
|
1348
|
+
if (confirmed < 0)
|
|
1349
|
+
return false;
|
|
1350
|
+
return this.matchFrame <= confirmed;
|
|
1351
|
+
}
|
|
1352
|
+
get isPredictionFrame() {
|
|
1353
|
+
return !this.isConfirmFrame;
|
|
1354
|
+
}
|
|
1337
1355
|
}
|
|
1338
1356
|
|
|
1339
1357
|
class ScreenContext {
|
|
@@ -1432,7 +1450,7 @@ function readTapeHeader(tape) {
|
|
|
1432
1450
|
eventCount: view.getUint16(14, true)
|
|
1433
1451
|
};
|
|
1434
1452
|
}
|
|
1435
|
-
var DEFAULT_WASM_URL = new URL("https://unpkg.com/@bloopjs/engine@0.0.
|
|
1453
|
+
var DEFAULT_WASM_URL = new URL("https://unpkg.com/@bloopjs/engine@0.0.93/wasm/bloop.wasm");
|
|
1436
1454
|
var MAX_ROLLBACK_FRAMES = 500;
|
|
1437
1455
|
var TIME_CTX_OFFSET = 0;
|
|
1438
1456
|
var INPUT_CTX_OFFSET = TIME_CTX_OFFSET + 4;
|
|
@@ -2343,6 +2361,7 @@ var NET_CTX_PEERS_OFFSET2 = 32;
|
|
|
2343
2361
|
var NET_CTX_LAST_ROLLBACK_DEPTH_OFFSET2 = 128;
|
|
2344
2362
|
var NET_CTX_TOTAL_ROLLBACKS_OFFSET2 = 132;
|
|
2345
2363
|
var NET_CTX_FRAMES_RESIMULATED_OFFSET2 = 136;
|
|
2364
|
+
var NET_CTX_CONFIRMED_MATCH_FRAME_OFFSET2 = 144;
|
|
2346
2365
|
var MOUSE_CTX_X_OFFSET2 = 0;
|
|
2347
2366
|
var MOUSE_CTX_Y_OFFSET2 = 4;
|
|
2348
2367
|
var MOUSE_CTX_WHEEL_X_OFFSET2 = 8;
|
|
@@ -3254,6 +3273,23 @@ class NetContext2 {
|
|
|
3254
3273
|
}
|
|
3255
3274
|
return Number(this.dataView.getBigUint64(NET_CTX_FRAMES_RESIMULATED_OFFSET2, true));
|
|
3256
3275
|
}
|
|
3276
|
+
get confirmedMatchFrame() {
|
|
3277
|
+
if (!this.#hasValidBuffer()) {
|
|
3278
|
+
throw new Error("NetContext dataView is not valid");
|
|
3279
|
+
}
|
|
3280
|
+
return this.dataView.getInt32(NET_CTX_CONFIRMED_MATCH_FRAME_OFFSET2, true);
|
|
3281
|
+
}
|
|
3282
|
+
get isConfirmFrame() {
|
|
3283
|
+
if (this.peerCount <= 1)
|
|
3284
|
+
return true;
|
|
3285
|
+
const confirmed = this.confirmedMatchFrame;
|
|
3286
|
+
if (confirmed < 0)
|
|
3287
|
+
return false;
|
|
3288
|
+
return this.matchFrame <= confirmed;
|
|
3289
|
+
}
|
|
3290
|
+
get isPredictionFrame() {
|
|
3291
|
+
return !this.isConfirmFrame;
|
|
3292
|
+
}
|
|
3257
3293
|
}
|
|
3258
3294
|
function mouseButtonCodeToMouseButton2(code) {
|
|
3259
3295
|
return MouseButton2[code];
|
|
@@ -3273,7 +3309,7 @@ function readTapeHeader2(tape) {
|
|
|
3273
3309
|
eventCount: view.getUint16(14, true)
|
|
3274
3310
|
};
|
|
3275
3311
|
}
|
|
3276
|
-
var DEFAULT_WASM_URL2 = new URL("https://unpkg.com/@bloopjs/engine@0.0.
|
|
3312
|
+
var DEFAULT_WASM_URL2 = new URL("https://unpkg.com/@bloopjs/engine@0.0.93/wasm/bloop.wasm");
|
|
3277
3313
|
var TIME_CTX_OFFSET2 = 0;
|
|
3278
3314
|
var INPUT_CTX_OFFSET2 = TIME_CTX_OFFSET2 + 4;
|
|
3279
3315
|
var EVENTS_OFFSET2 = INPUT_CTX_OFFSET2 + 4;
|
|
@@ -4394,6 +4430,7 @@ var onJumpForward = d3(null);
|
|
|
4394
4430
|
var onSeek = d3(null);
|
|
4395
4431
|
var onLoadTape = d3(null);
|
|
4396
4432
|
var onReplayLastTape = d3(null);
|
|
4433
|
+
var onSaveTape = d3(null);
|
|
4397
4434
|
var lastTapeName = d3(null);
|
|
4398
4435
|
var isLoadDialogOpen = d3(false);
|
|
4399
4436
|
var debugState = {
|
|
@@ -4424,6 +4461,7 @@ var debugState = {
|
|
|
4424
4461
|
onSeek,
|
|
4425
4462
|
onLoadTape,
|
|
4426
4463
|
onReplayLastTape,
|
|
4464
|
+
onSaveTape,
|
|
4427
4465
|
lastTapeName,
|
|
4428
4466
|
isLoadDialogOpen
|
|
4429
4467
|
};
|
|
@@ -4634,6 +4672,18 @@ function wireTapeLoadHandlers(app) {
|
|
|
4634
4672
|
debugState.isLoadDialogOpen.value = false;
|
|
4635
4673
|
}
|
|
4636
4674
|
};
|
|
4675
|
+
debugState.onSaveTape.value = () => {
|
|
4676
|
+
if (!app.sim.hasHistory)
|
|
4677
|
+
return;
|
|
4678
|
+
const tape = app.sim.saveTape();
|
|
4679
|
+
const blob = new Blob([tape], { type: "application/octet-stream" });
|
|
4680
|
+
const url = URL.createObjectURL(blob);
|
|
4681
|
+
const a4 = document.createElement("a");
|
|
4682
|
+
a4.href = url;
|
|
4683
|
+
a4.download = `tape-${Date.now()}.bloop`;
|
|
4684
|
+
a4.click();
|
|
4685
|
+
URL.revokeObjectURL(url);
|
|
4686
|
+
};
|
|
4637
4687
|
checkForSavedTape();
|
|
4638
4688
|
}
|
|
4639
4689
|
// ../../node_modules/preact/jsx-runtime/dist/jsxRuntime.module.js
|
|
@@ -5187,6 +5237,9 @@ function BottomBar() {
|
|
|
5187
5237
|
const handleLoadTapeClick = q2(() => {
|
|
5188
5238
|
debugState.isLoadDialogOpen.value = true;
|
|
5189
5239
|
}, []);
|
|
5240
|
+
const handleSaveTapeClick = q2(() => {
|
|
5241
|
+
debugState.onSaveTape.value?.();
|
|
5242
|
+
}, []);
|
|
5190
5243
|
return /* @__PURE__ */ u4("div", {
|
|
5191
5244
|
className: "bottom-bar",
|
|
5192
5245
|
children: [
|
|
@@ -5194,7 +5247,7 @@ function BottomBar() {
|
|
|
5194
5247
|
className: "playbar-controls",
|
|
5195
5248
|
children: [
|
|
5196
5249
|
/* @__PURE__ */ u4("button", {
|
|
5197
|
-
className: "playbar-btn",
|
|
5250
|
+
className: "playbar-btn jump-back",
|
|
5198
5251
|
...jumpBackRepeat,
|
|
5199
5252
|
children: [
|
|
5200
5253
|
"<<",
|
|
@@ -5210,7 +5263,7 @@ function BottomBar() {
|
|
|
5210
5263
|
]
|
|
5211
5264
|
}, undefined, true, undefined, this),
|
|
5212
5265
|
/* @__PURE__ */ u4("button", {
|
|
5213
|
-
className: "playbar-btn",
|
|
5266
|
+
className: "playbar-btn step-back",
|
|
5214
5267
|
...stepBackRepeat,
|
|
5215
5268
|
children: [
|
|
5216
5269
|
"<",
|
|
@@ -5226,7 +5279,7 @@ function BottomBar() {
|
|
|
5226
5279
|
]
|
|
5227
5280
|
}, undefined, true, undefined, this),
|
|
5228
5281
|
/* @__PURE__ */ u4("button", {
|
|
5229
|
-
className: "playbar-btn",
|
|
5282
|
+
className: "playbar-btn play-pause",
|
|
5230
5283
|
onClick: handlePlayPause,
|
|
5231
5284
|
children: [
|
|
5232
5285
|
isPlaying2 ? "||" : ">",
|
|
@@ -5243,7 +5296,7 @@ function BottomBar() {
|
|
|
5243
5296
|
]
|
|
5244
5297
|
}, undefined, true, undefined, this),
|
|
5245
5298
|
/* @__PURE__ */ u4("button", {
|
|
5246
|
-
className: "playbar-btn",
|
|
5299
|
+
className: "playbar-btn step-forward",
|
|
5247
5300
|
...stepForwardRepeat,
|
|
5248
5301
|
children: [
|
|
5249
5302
|
">",
|
|
@@ -5259,7 +5312,7 @@ function BottomBar() {
|
|
|
5259
5312
|
]
|
|
5260
5313
|
}, undefined, true, undefined, this),
|
|
5261
5314
|
/* @__PURE__ */ u4("button", {
|
|
5262
|
-
className: "playbar-btn",
|
|
5315
|
+
className: "playbar-btn jump-forward",
|
|
5263
5316
|
...jumpForwardRepeat,
|
|
5264
5317
|
children: [
|
|
5265
5318
|
">>",
|
|
@@ -5274,6 +5327,22 @@ function BottomBar() {
|
|
|
5274
5327
|
}, undefined, true, undefined, this)
|
|
5275
5328
|
]
|
|
5276
5329
|
}, undefined, true, undefined, this),
|
|
5330
|
+
/* @__PURE__ */ u4("button", {
|
|
5331
|
+
className: "playbar-btn save-tape-btn",
|
|
5332
|
+
onClick: handleSaveTapeClick,
|
|
5333
|
+
children: [
|
|
5334
|
+
"Save",
|
|
5335
|
+
/* @__PURE__ */ u4("span", {
|
|
5336
|
+
className: "tooltip",
|
|
5337
|
+
children: [
|
|
5338
|
+
"Save tape ",
|
|
5339
|
+
/* @__PURE__ */ u4("kbd", {
|
|
5340
|
+
children: "Cmd+S"
|
|
5341
|
+
}, undefined, false, undefined, this)
|
|
5342
|
+
]
|
|
5343
|
+
}, undefined, true, undefined, this)
|
|
5344
|
+
]
|
|
5345
|
+
}, undefined, true, undefined, this),
|
|
5277
5346
|
/* @__PURE__ */ u4("button", {
|
|
5278
5347
|
className: "playbar-btn load-tape-btn",
|
|
5279
5348
|
onClick: handleLoadTapeClick,
|
|
@@ -5427,10 +5496,26 @@ var styles = `
|
|
|
5427
5496
|
box-sizing: border-box;
|
|
5428
5497
|
}
|
|
5429
5498
|
|
|
5499
|
+
/* Mobile-first CSS variables */
|
|
5500
|
+
:host {
|
|
5501
|
+
--bar-size: 10vw;
|
|
5502
|
+
--bar-size-h: 10vh;
|
|
5503
|
+
--bar-size-h: 10dvh;
|
|
5504
|
+
}
|
|
5505
|
+
|
|
5506
|
+
/* Desktop overrides */
|
|
5507
|
+
@media (min-width: 769px) {
|
|
5508
|
+
:host {
|
|
5509
|
+
--bar-size: 2vw;
|
|
5510
|
+
--bar-size-h: 2vh;
|
|
5511
|
+
}
|
|
5512
|
+
}
|
|
5513
|
+
|
|
5430
5514
|
/* Layout */
|
|
5431
5515
|
.fullscreen {
|
|
5432
5516
|
width: 100vw;
|
|
5433
5517
|
height: 100vh;
|
|
5518
|
+
height: 100dvh;
|
|
5434
5519
|
margin: 0;
|
|
5435
5520
|
padding: 0;
|
|
5436
5521
|
overflow: hidden;
|
|
@@ -5447,17 +5532,96 @@ var styles = `
|
|
|
5447
5532
|
display: block;
|
|
5448
5533
|
}
|
|
5449
5534
|
|
|
5535
|
+
/* Mobile-first: vertical scroll layout */
|
|
5450
5536
|
.layout {
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5537
|
+
/* Use fixed position on mobile to escape parent overflow:hidden */
|
|
5538
|
+
position: fixed;
|
|
5539
|
+
top: 0;
|
|
5540
|
+
left: 0;
|
|
5541
|
+
right: 0;
|
|
5542
|
+
bottom: 0;
|
|
5543
|
+
display: flex;
|
|
5544
|
+
flex-direction: column;
|
|
5545
|
+
overflow-y: auto;
|
|
5546
|
+
overflow-x: hidden;
|
|
5547
|
+
-webkit-overflow-scrolling: touch;
|
|
5548
|
+
overscroll-behavior-y: contain;
|
|
5549
|
+
padding: 0;
|
|
5550
|
+
gap: 0;
|
|
5551
|
+
background: #1a1a1a;
|
|
5552
|
+
}
|
|
5553
|
+
|
|
5554
|
+
.layout .game {
|
|
5555
|
+
/* Use dvh with vh fallback for mobile Safari address bar */
|
|
5556
|
+
height: 100vh;
|
|
5557
|
+
height: 100dvh;
|
|
5558
|
+
width: 100%;
|
|
5559
|
+
flex-shrink: 0;
|
|
5560
|
+
/* Mobile: no border radius, fullscreen game */
|
|
5561
|
+
border-radius: 0;
|
|
5562
|
+
}
|
|
5563
|
+
|
|
5564
|
+
/* Mobile: stretch canvas to fill game area */
|
|
5565
|
+
.layout .game .canvas-container {
|
|
5458
5566
|
width: 100%;
|
|
5459
5567
|
height: 100%;
|
|
5568
|
+
}
|
|
5569
|
+
|
|
5570
|
+
.layout .game .canvas-container canvas {
|
|
5571
|
+
width: 100%;
|
|
5572
|
+
height: 100%;
|
|
5573
|
+
max-width: none;
|
|
5574
|
+
max-height: none;
|
|
5575
|
+
display: block;
|
|
5576
|
+
}
|
|
5577
|
+
|
|
5578
|
+
.layout .stats,
|
|
5579
|
+
.layout .logs {
|
|
5580
|
+
width: 100%;
|
|
5581
|
+
min-height: 50vh;
|
|
5582
|
+
min-height: 50dvh;
|
|
5460
5583
|
padding: 1rem;
|
|
5584
|
+
flex-shrink: 0;
|
|
5585
|
+
}
|
|
5586
|
+
|
|
5587
|
+
/* Desktop: 2x2 grid layout */
|
|
5588
|
+
@media (min-width: 769px) {
|
|
5589
|
+
.layout {
|
|
5590
|
+
position: static;
|
|
5591
|
+
display: grid;
|
|
5592
|
+
grid-template-areas:
|
|
5593
|
+
"game stats"
|
|
5594
|
+
"logs logs";
|
|
5595
|
+
grid-template-columns: calc(50% - 0.5rem) calc(50% - 0.5rem);
|
|
5596
|
+
grid-template-rows: calc(50% - 0.5rem) calc(50% - 0.5rem);
|
|
5597
|
+
gap: 1rem;
|
|
5598
|
+
padding: 1rem;
|
|
5599
|
+
height: 100%;
|
|
5600
|
+
overflow: hidden;
|
|
5601
|
+
-webkit-overflow-scrolling: auto;
|
|
5602
|
+
overscroll-behavior-y: auto;
|
|
5603
|
+
}
|
|
5604
|
+
|
|
5605
|
+
.layout .game {
|
|
5606
|
+
height: auto;
|
|
5607
|
+
flex-shrink: initial;
|
|
5608
|
+
border-radius: 8px;
|
|
5609
|
+
}
|
|
5610
|
+
|
|
5611
|
+
/* Desktop: restore centered canvas with constraints */
|
|
5612
|
+
.layout .game .canvas-container canvas {
|
|
5613
|
+
width: auto;
|
|
5614
|
+
height: auto;
|
|
5615
|
+
max-width: 100%;
|
|
5616
|
+
max-height: 100%;
|
|
5617
|
+
}
|
|
5618
|
+
|
|
5619
|
+
.layout .stats,
|
|
5620
|
+
.layout .logs {
|
|
5621
|
+
min-height: auto;
|
|
5622
|
+
padding: 1rem;
|
|
5623
|
+
flex-shrink: initial;
|
|
5624
|
+
}
|
|
5461
5625
|
}
|
|
5462
5626
|
|
|
5463
5627
|
/* Letterboxed layout - using equal vw/vh percentages keeps game at viewport aspect ratio */
|
|
@@ -5467,10 +5631,12 @@ var styles = `
|
|
|
5467
5631
|
"top-bar top-bar top-bar"
|
|
5468
5632
|
"left-bar game right-bar"
|
|
5469
5633
|
"bottom-bar bottom-bar bottom-bar";
|
|
5470
|
-
grid-template-columns:
|
|
5471
|
-
grid-template-rows:
|
|
5634
|
+
grid-template-columns: var(--bar-size) 1fr var(--bar-size);
|
|
5635
|
+
grid-template-rows: var(--bar-size-h) 1fr var(--bar-size-h);
|
|
5472
5636
|
width: 100vw;
|
|
5637
|
+
/* Use dvh with vh fallback for mobile Safari address bar */
|
|
5473
5638
|
height: 100vh;
|
|
5639
|
+
height: 100dvh;
|
|
5474
5640
|
background: #1a1a1a;
|
|
5475
5641
|
overflow: hidden;
|
|
5476
5642
|
overscroll-behavior: none;
|
|
@@ -5489,7 +5655,7 @@ var styles = `
|
|
|
5489
5655
|
}
|
|
5490
5656
|
|
|
5491
5657
|
.top-bar-side-label {
|
|
5492
|
-
width:
|
|
5658
|
+
width: var(--bar-size);
|
|
5493
5659
|
text-align: center;
|
|
5494
5660
|
font-size: 9px;
|
|
5495
5661
|
text-transform: uppercase;
|
|
@@ -5497,6 +5663,17 @@ var styles = `
|
|
|
5497
5663
|
color: #666;
|
|
5498
5664
|
}
|
|
5499
5665
|
|
|
5666
|
+
/* Mobile: larger top bar text */
|
|
5667
|
+
@media (max-width: 768px) {
|
|
5668
|
+
.top-bar-side-label {
|
|
5669
|
+
font-size: 12px;
|
|
5670
|
+
}
|
|
5671
|
+
|
|
5672
|
+
.top-bar {
|
|
5673
|
+
font-size: 14px;
|
|
5674
|
+
}
|
|
5675
|
+
}
|
|
5676
|
+
|
|
5500
5677
|
.top-bar-center {
|
|
5501
5678
|
display: flex;
|
|
5502
5679
|
align-items: center;
|
|
@@ -5565,8 +5742,17 @@ var styles = `
|
|
|
5565
5742
|
display: flex;
|
|
5566
5743
|
align-items: center;
|
|
5567
5744
|
background: #111;
|
|
5568
|
-
|
|
5569
|
-
|
|
5745
|
+
/* Mobile-first: more padding */
|
|
5746
|
+
padding: 0 16px;
|
|
5747
|
+
gap: 12px;
|
|
5748
|
+
}
|
|
5749
|
+
|
|
5750
|
+
/* Desktop: tighter padding */
|
|
5751
|
+
@media (min-width: 769px) {
|
|
5752
|
+
.bottom-bar {
|
|
5753
|
+
padding: 0 8px;
|
|
5754
|
+
gap: 8px;
|
|
5755
|
+
}
|
|
5570
5756
|
}
|
|
5571
5757
|
|
|
5572
5758
|
.playbar-controls {
|
|
@@ -5576,16 +5762,35 @@ var styles = `
|
|
|
5576
5762
|
flex-shrink: 0;
|
|
5577
5763
|
}
|
|
5578
5764
|
|
|
5765
|
+
/* Mobile-first: hide step/jump buttons */
|
|
5766
|
+
.playbar-btn.jump-back,
|
|
5767
|
+
.playbar-btn.step-back,
|
|
5768
|
+
.playbar-btn.step-forward,
|
|
5769
|
+
.playbar-btn.jump-forward {
|
|
5770
|
+
display: none;
|
|
5771
|
+
}
|
|
5772
|
+
|
|
5773
|
+
/* Desktop: show all controls */
|
|
5774
|
+
@media (min-width: 769px) {
|
|
5775
|
+
.playbar-btn.jump-back,
|
|
5776
|
+
.playbar-btn.step-back,
|
|
5777
|
+
.playbar-btn.step-forward,
|
|
5778
|
+
.playbar-btn.jump-forward {
|
|
5779
|
+
display: flex;
|
|
5780
|
+
}
|
|
5781
|
+
}
|
|
5782
|
+
|
|
5579
5783
|
.playbar-btn {
|
|
5580
|
-
|
|
5581
|
-
|
|
5582
|
-
|
|
5583
|
-
min-
|
|
5784
|
+
/* Mobile-first: larger buttons */
|
|
5785
|
+
width: 4vh;
|
|
5786
|
+
height: 4vh;
|
|
5787
|
+
min-width: 32px;
|
|
5788
|
+
min-height: 32px;
|
|
5584
5789
|
border: none;
|
|
5585
5790
|
outline: none;
|
|
5586
5791
|
background: transparent;
|
|
5587
5792
|
color: #888;
|
|
5588
|
-
font-size:
|
|
5793
|
+
font-size: 16px;
|
|
5589
5794
|
cursor: pointer;
|
|
5590
5795
|
border-radius: 2px;
|
|
5591
5796
|
display: flex;
|
|
@@ -5595,6 +5800,17 @@ var styles = `
|
|
|
5595
5800
|
position: relative;
|
|
5596
5801
|
}
|
|
5597
5802
|
|
|
5803
|
+
/* Desktop: smaller buttons */
|
|
5804
|
+
@media (min-width: 769px) {
|
|
5805
|
+
.playbar-btn {
|
|
5806
|
+
width: 1.5vh;
|
|
5807
|
+
height: 1.5vh;
|
|
5808
|
+
min-width: 18px;
|
|
5809
|
+
min-height: 18px;
|
|
5810
|
+
font-size: 10px;
|
|
5811
|
+
}
|
|
5812
|
+
}
|
|
5813
|
+
|
|
5598
5814
|
.playbar-btn:hover {
|
|
5599
5815
|
background: #333;
|
|
5600
5816
|
color: #fff;
|
|
@@ -5638,7 +5854,8 @@ var styles = `
|
|
|
5638
5854
|
|
|
5639
5855
|
.seek-bar {
|
|
5640
5856
|
flex: 1;
|
|
5641
|
-
|
|
5857
|
+
/* Mobile-first: larger seek bar */
|
|
5858
|
+
height: 32px;
|
|
5642
5859
|
background: #222;
|
|
5643
5860
|
border-radius: 4px;
|
|
5644
5861
|
position: relative;
|
|
@@ -5646,6 +5863,13 @@ var styles = `
|
|
|
5646
5863
|
overflow: hidden;
|
|
5647
5864
|
}
|
|
5648
5865
|
|
|
5866
|
+
/* Desktop: smaller seek bar */
|
|
5867
|
+
@media (min-width: 769px) {
|
|
5868
|
+
.seek-bar {
|
|
5869
|
+
height: 16px;
|
|
5870
|
+
}
|
|
5871
|
+
}
|
|
5872
|
+
|
|
5649
5873
|
.seek-bar-fill {
|
|
5650
5874
|
position: absolute;
|
|
5651
5875
|
top: 0;
|
|
@@ -7262,5 +7486,5 @@ export {
|
|
|
7262
7486
|
App
|
|
7263
7487
|
};
|
|
7264
7488
|
|
|
7265
|
-
//# debugId=
|
|
7489
|
+
//# debugId=18A1E6B20945E8E464756E2164756E21
|
|
7266
7490
|
//# sourceMappingURL=mod.js.map
|