@@ -799,9 +799,9 @@ <h1>StellarMind</h1>
799799 </ div >
800800
801801 <!-- ═══ SECURITY WARNING MODAL ═══ -->
802- < div id ="security-modal " style ="display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.7);z-index:100;display:flex ;align-items:center;justify-content:center; ">
802+ < div id ="security-modal " role =" dialog " aria-modal =" true " aria-labelledby =" security-modal-title " style ="display:none;position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.7);z-index:100;align-items:center;justify-content:center; ">
803803 < div style ="background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:24px;max-width:420px;box-shadow:0 20px 60px rgba(0,0,0,0.5); ">
804- < h3 style ="font-size:16px;font-weight:700;margin-bottom:12px;color:var(--red); "> 🔐 API Key Security Warning</ h3 >
804+ < h3 id =" security-modal-title " style ="font-size:16px;font-weight:700;margin-bottom:12px;color:var(--red); "> 🔐 API Key Security Warning</ h3 >
805805 < div style ="font-size:12px;color:var(--text-secondary);line-height:1.7;margin-bottom:16px; ">
806806 < p style ="margin-bottom:10px; "> < strong > Your API key will be:</ strong > </ p >
807807 < ul style ="margin-left:16px;margin-bottom:10px; ">
@@ -1315,11 +1315,54 @@ <h3 style="font-size:16px;font-weight:700;margin-bottom:12px;color:var(--red);">
13151315 alert ( 'Please enter a valid Anthropic API key starting with sk-ant-' ) ;
13161316 return ;
13171317 }
1318- document . getElementById ( 'security-modal' ) . style . display = 'flex' ;
1318+ const modal = document . getElementById ( 'security-modal' ) ;
1319+ modal . style . display = 'flex' ;
1320+
1321+ // Escape key handler — stored on modal so closeSecurityModal can remove it
1322+ modal . _escHandler = function ( e ) {
1323+ if ( e . key === 'Escape' ) closeSecurityModal ( ) ;
1324+ } ;
1325+ document . addEventListener ( 'keydown' , modal . _escHandler ) ;
1326+
1327+ // Focus trap: collect focusable elements inside the modal
1328+ modal . _trapHandler = function ( e ) {
1329+ if ( e . key !== 'Tab' ) return ;
1330+ const focusable = Array . from ( modal . querySelectorAll (
1331+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
1332+ ) ) . filter ( el => ! el . disabled ) ;
1333+ if ( ! focusable . length ) return ;
1334+ const first = focusable [ 0 ] ;
1335+ const last = focusable [ focusable . length - 1 ] ;
1336+ if ( e . shiftKey ) {
1337+ if ( document . activeElement === first ) { e . preventDefault ( ) ; last . focus ( ) ; }
1338+ } else {
1339+ if ( document . activeElement === last ) { e . preventDefault ( ) ; first . focus ( ) ; }
1340+ }
1341+ } ;
1342+ document . addEventListener ( 'keydown' , modal . _trapHandler ) ;
1343+
1344+ // Focus the Cancel button (first actionable control)
1345+ const cancelBtn = modal . querySelector ( 'button' ) ;
1346+ if ( cancelBtn ) cancelBtn . focus ( ) ;
13191347 }
13201348
13211349 function closeSecurityModal ( ) {
1322- document . getElementById ( 'security-modal' ) . style . display = 'none' ;
1350+ const modal = document . getElementById ( 'security-modal' ) ;
1351+ modal . style . display = 'none' ;
1352+
1353+ // Remove Escape and focus-trap handlers
1354+ if ( modal . _escHandler ) {
1355+ document . removeEventListener ( 'keydown' , modal . _escHandler ) ;
1356+ modal . _escHandler = null ;
1357+ }
1358+ if ( modal . _trapHandler ) {
1359+ document . removeEventListener ( 'keydown' , modal . _trapHandler ) ;
1360+ modal . _trapHandler = null ;
1361+ }
1362+
1363+ // Return focus to the API key input
1364+ const input = document . getElementById ( 'api-key-input' ) ;
1365+ if ( input ) input . focus ( ) ;
13231366 }
13241367
13251368 function confirmApiKeySubmission ( ) {
0 commit comments