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) => {