diff --git a/index.html b/index.html index 5282521..1815519 100644 --- a/index.html +++ b/index.html @@ -983,12 +983,60 @@ Sovereignty and service always.`; // ===== OVERLAY ===== + + // Focus trap: cycle through focusable elements within the crisis overlay + function getOverlayFocusableElements() { + return crisisOverlay.querySelectorAll( + 'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])' + ); + } + + function trapFocusInOverlay(e) { + if (!crisisOverlay.classList.contains('active')) return; + if (e.key !== 'Tab') return; + + var focusable = getOverlayFocusableElements(); + if (focusable.length === 0) return; + + var first = focusable[0]; + var last = focusable[focusable.length - 1]; + + if (e.shiftKey) { + // Shift+Tab: if on first, wrap to last + if (document.activeElement === first) { + e.preventDefault(); + last.focus(); + } + } else { + // Tab: if on last, wrap to first + if (document.activeElement === last) { + e.preventDefault(); + first.focus(); + } + } + } + + // Store the element that had focus before the overlay opened + var _preOverlayFocusElement = null; + function showOverlay() { + // Save current focus for restoration on dismiss + _preOverlayFocusElement = document.activeElement; + crisisOverlay.classList.add('active'); overlayDismissBtn.disabled = true; var countdown = 10; overlayDismissBtn.textContent = 'Continue to chat (' + countdown + 's)'; + // Disable background interaction via inert attribute + var mainApp = document.querySelector('.app'); + if (mainApp) mainApp.setAttribute('inert', ''); + // Also hide from assistive tech + var chatSection = document.getElementById('chat'); + if (chatSection) chatSection.setAttribute('aria-hidden', 'true'); + var footerEl = document.querySelector('footer'); + if (footerEl) footerEl.setAttribute('aria-hidden', 'true'); + if (overlayTimer) clearInterval(overlayTimer); overlayTimer = setInterval(function() { countdown--; @@ -1005,6 +1053,9 @@ Sovereignty and service always.`; overlayDismissBtn.focus(); } + // Register focus trap on document (always listening, gated by class check) + document.addEventListener('keydown', trapFocusInOverlay); + overlayDismissBtn.addEventListener('click', function() { if (!overlayDismissBtn.disabled) { crisisOverlay.classList.remove('active'); @@ -1012,7 +1063,22 @@ Sovereignty and service always.`; clearInterval(overlayTimer); overlayTimer = null; } - msgInput.focus(); + + // Re-enable background interaction + var mainApp = document.querySelector('.app'); + if (mainApp) mainApp.removeAttribute('inert'); + var chatSection = document.getElementById('chat'); + if (chatSection) chatSection.removeAttribute('aria-hidden'); + var footerEl = document.querySelector('footer'); + if (footerEl) footerEl.removeAttribute('aria-hidden'); + + // Restore focus to the element that had it before the overlay opened + if (_preOverlayFocusElement && typeof _preOverlayFocusElement.focus === 'function') { + _preOverlayFocusElement.focus(); + } else { + msgInput.focus(); + } + _preOverlayFocusElement = null; } });