diff --git a/tools/xsofy-shell.html b/tools/xsofy-shell.html index 7aaa8a4..15a7340 100644 --- a/tools/xsofy-shell.html +++ b/tools/xsofy-shell.html @@ -714,7 +714,7 @@ { key: 'd', glyph: 'd', label: 'DROP' }, mv('y','↖','y'), mv('k','↑','k'), mv('u','↗','u'), { key: '<', glyph: '<', label: 'ASC' }, mv('h','←','h'), { key: 'x', glyph: 'x', label: 'AUTO' }, mv('l','→','l'), { key: '>', glyph: '>', label: 'DESC' }, mv('b','↙','b'), mv('j','↓','j'), mv('n','↘','n'), - { key: 'r', glyph: 'r', label: 'RUNES' }, { key: 'y', glyph: 'y', label: 'YES' }, { key: 'n', glyph: 'n', label: 'NO' }, { key: '.', glyph: '·', label: 'WAIT', repeat: true }, + { key: 'r', glyph: 'r', label: 'RUNES' }, { key: 'n', glyph: 'n', label: 'NO' }, { key: 'y', glyph: 'y', label: 'YES' }, { key: '.', glyph: '·', label: 'WAIT', repeat: true }, ]}; // Each pane is a FLAT, row-major tile list: a spec, `null` (empty), or (a-z // only) a spacer. MOVE is a 6-col grid holding movement + common actions + y/n; @@ -725,15 +725,17 @@ const PANES = [ { label: 'PLAY', cols: 6, land: LAND_PLAY, tiles: [ // 5 rows (same height as the a-z keyboard pane). D-pad centered on the - // right (rows 2-4, cols 4-6) with y/n/wait below it (row 5). esc anchors + // right (rows 2-4, cols 4-6) with n/y/enter below it (row 5); wait rides + // top row where enter was (swap: wait is the high-frequency key). esc anchors // top-left; col 2 runs the menu letters a-e in order (a/d/e double as // their game actions, b/c are pure menu picks); col 3 stacks fire/get, // then the stair pair, then runes. Remaining cells are muted placeholders. - { key: ESC, glyph: 'esc', label: 'BACK' }, { key: 'a', glyph: 'a', label: 'USE' }, { key: 'f', glyph: 'f', label: 'FIRE' }, { key: '\r', glyph: '⏎', label: 'ENTER' }, { key: 'm', glyph: 'm', label: 'MSG' }, { key: 'i', glyph: 'i', label: 'INV' }, + // ` (DEV) opens the dev console — dev-gated game-side, a no-op otherwise. + { key: ESC, glyph: 'esc', label: 'BACK' }, { key: 'a', glyph: 'a', label: 'USE' }, { key: 'f', glyph: 'f', label: 'FIRE' }, { key: '.', glyph: '·', label: 'WAIT', repeat: true }, { key: 'm', glyph: 'm', label: 'MSG' }, { key: 'i', glyph: 'i', label: 'INV' }, { key: '?', glyph: '?', label: 'HELP' }, { key: 'b', glyph: 'b' }, { key: 'g', glyph: 'g', label: 'GET' }, mv('y','↖','y'), mv('k','↑','k'), mv('u','↗','u'), - null, { key: 'c', glyph: 'c' }, { key: '<', glyph: '<', label: 'ASC' }, mv('h','←','h'), { key: 'x', glyph: 'x', label: 'AUTO' }, mv('l','→','l'), + { key: '`', glyph: '`', label: 'DEV' }, { key: 'c', glyph: 'c' }, { key: '<', glyph: '<', label: 'ASC' }, mv('h','←','h'), { key: 'x', glyph: 'x', label: 'AUTO' }, mv('l','→','l'), null, { key: 'd', glyph: 'd', label: 'DROP' }, { key: '>', glyph: '>', label: 'DESC' }, mv('b','↙','b'), mv('j','↓','j'), mv('n','↘','n'), - null, { key: 'e', glyph: 'e', label: 'EQUIP' }, { key: 'r', glyph: 'r', label: 'RUNES' }, { key: 'y', glyph: 'y', label: 'YES' }, { key: 'n', glyph: 'n', label: 'NO' }, { key: '.', glyph: '·', label: 'WAIT', repeat: true }, + null, { key: 'e', glyph: 'e', label: 'EQUIP' }, { key: 'r', glyph: 'r', label: 'RUNES' }, { key: 'n', glyph: 'n', label: 'NO' }, { key: 'y', glyph: 'y', label: 'YES' }, { key: '\r', glyph: '⏎', label: 'ENTER' }, ]}, { label: 'a–z', cols: 20, // Landscape sheet variant: 4 rows to give the game back a strip — the @@ -744,7 +746,7 @@ ...'1234567890'.split('').map(kbd), ...'qwertyuiop'.split('').map(kbd), { key: '?', glyph: '?', span: 1, cls: 'kbd' }, ...'asdfghjkl'.split('').map(kbd), { key: '\r', glyph: '⏎', span: 1, cls: 'kbd' }, - { key: ESC, glyph: 'esc', label: 'BACK', span: 3 }, ...'zxcvbnm'.split('').map(kbd), { key: '\u007f', glyph: '⌫', span: 3, cls: 'kbd' }, + { key: ESC, glyph: 'esc', label: 'BACK', span: 2 }, { key: '(', glyph: '(', span: 1, cls: 'kbd' }, { key: ')', glyph: ')', span: 1, cls: 'kbd' }, ...'zxcvbnm'.split('').map(kbd), { key: '\u007f', glyph: '⌫', span: 2, cls: 'kbd' }, ]}, tiles: [ // iPhone-ish QWERTY on a fine 20-col grid (each key spans 2 units = 10 per @@ -757,7 +759,7 @@ ...'1234567890'.split('').map(kbd), ...'qwertyuiop'.split('').map(kbd), spacer(1), ...'asdfghjkl'.split('').map(kbd), spacer(1), - spacer(3), ...'zxcvbnm'.split('').map(kbd), { key: '\u007f', glyph: '⌫', span: 3, cls: 'kbd' }, + { key: '(', glyph: '(', span: 2, cls: 'kbd' }, { key: ')', glyph: ')', span: 2, cls: 'kbd' }, ...'zxcvbnm'.split('').map(kbd), { key: '\u007f', glyph: '⌫', span: 2, cls: 'kbd' }, { key: ESC, glyph: 'esc', label: 'BACK', span: 3 }, { key: ' ', glyph: '␣', label: 'SPACE', span: 11 }, { key: '?', glyph: '?', label: 'HELP', span: 3 }, { key: '\r', glyph: '⏎', label: 'ENTER', span: 3 }, ]}, ]; @@ -905,13 +907,15 @@ repeatToggleEl?.addEventListener('mousedown', (e) => e.preventDefault()); // Font-size cycle. xterm's default 14 is unreadable on a 375px viewport; the - // chip cycles a short predictable set. First-ever load picks by orientation. + // chip cycles a short predictable set. First-ever load picks by orientation + // (landscape/desktop bumped 14 -> 18: 14 reads small on laptop screens too; + // a stored user choice always wins over these defaults). const FONT_SIZES = [12, 14, 18, 22, 28], LS_KEY = 'xsofy/font-size'; const cycleEl = $('xs-font-cycle'), fontPxEl = $('xs-font-px'); function applyFontSize(n) { setTermFontSize(n); if (fontPxEl) fontPxEl.textContent = n; } function initFontSize() { let n = parseInt(localStorage.getItem(LS_KEY) || '', 10); - if (!FONT_SIZES.includes(n)) n = matchMedia('(orientation: portrait)').matches ? 22 : 14; + if (!FONT_SIZES.includes(n)) n = matchMedia('(orientation: portrait)').matches ? 22 : 18; applyFontSize(n); } cycleEl?.addEventListener('pointerdown', (e) => {