diff --git a/html/js/network/smirkAuth.js b/html/js/network/smirkAuth.js
index d9dbde6..35073e1 100644
--- a/html/js/network/smirkAuth.js
+++ b/html/js/network/smirkAuth.js
@@ -77,10 +77,16 @@ const SmirkAuth = {
verifyData = result.verifyData;
provenPublicKey = result.pubkey;
} catch (nip98Err) {
- // Graceful fallback: if NIP-98 signing/verification fails
- // (wallet threw, lacks the method mid-flow, etc.) fall back to
- // the legacy path so login still works.
- console.warn('Smirk NIP-98 auth failed, falling back to legacy:', nip98Err && nip98Err.message);
+ // Only fall back to the legacy path when the wallet genuinely can't do NIP-98
+ // (method missing / unsupported). For LOCKED (unlock the extension), USER_REJECTED
+ // (user closed the popup), or a real signing failure, SURFACE it — re-invoking
+ // connect() would just pop a second prompt. On a current Smirk build a locked
+ // signNostrEvent auto-opens the unlock popup and never reaches here.
+ const code = nip98Err && nip98Err.code;
+ const methodMissing = code === 'UNSUPPORTED' || code === 'METHOD_NOT_FOUND'
+ || /not a function|is not supported|no such method|unsupported/i.test((nip98Err && nip98Err.message) || '');
+ if (!methodMissing) throw nip98Err;
+ console.warn('Smirk NIP-98 unsupported, falling back to legacy:', nip98Err && nip98Err.message);
const result = await this._verifyLegacy(socketId, challenge);
verifyData = result.verifyData;
provenPublicKey = result.pubkey;
diff --git a/html/js/ui/ui.js b/html/js/ui/ui.js
index 53b9af3..d40c9dc 100644
--- a/html/js/ui/ui.js
+++ b/html/js/ui/ui.js
@@ -19,10 +19,9 @@ const UI = {
var chatInput = $('#chatInput');
if (document.activeElement === gameDisplay[0]) {
- // Inset the outline (offset -2px) so it is drawn INSIDE the box — the play area is
- // flush to the viewport's right edge and the container clips an outward outline there,
- // which hid the border on the right side.
- gameDisplay.css({ 'outline': '2px solid yellow', 'outline-offset': '-2px' });
+ // Outward outline; the .container now has a right gutter (padding-right) so the right
+ // segment isn't clipped by overflow:hidden. (Inset offset gets clipped in Chromium.)
+ gameDisplay.css({ 'outline': '2px solid yellow', 'outline-offset': '0' });
chatInput.css('outline', 'none');
} else if (document.activeElement === chatInput[0]) {
chatInput.css('outline', '2px solid cyan');
diff --git a/html/styles/stylesheet.css b/html/styles/stylesheet.css
index 807e0f8..bc33238 100644
--- a/html/styles/stylesheet.css
+++ b/html/styles/stylesheet.css
@@ -73,6 +73,10 @@ body {
height: 100vh;
width: 100%;
max-width: 100vw;
+ box-sizing: border-box;
+ /* A few px of right gutter so the play area isn't flush to the viewport edge — otherwise
+ overflow:hidden clips the yellow focus outline on the right side. */
+ padding-right: 6px;
overflow: hidden;
gap: 1px;
background-color: var(--bg-panel);