diff --git a/kjvstudy_org/static/manifest.json b/kjvstudy_org/static/manifest.json
new file mode 100644
index 0000000..4948f25
--- /dev/null
+++ b/kjvstudy_org/static/manifest.json
@@ -0,0 +1,9 @@
+{
+ "name": "KJV Study",
+ "short_name": "KJV Study",
+ "description": "Study the King James Bible with AI-powered commentary, Strong's Concordance, and interlinear analysis",
+ "start_url": "/",
+ "display": "standalone",
+ "background_color": "#fffff8",
+ "theme_color": "#4a7c59"
+}
diff --git a/kjvstudy_org/templates/accessibility.html b/kjvstudy_org/templates/accessibility.html
index 4ed924e..96aaf4e 100644
--- a/kjvstudy_org/templates/accessibility.html
+++ b/kjvstudy_org/templates/accessibility.html
@@ -289,6 +289,38 @@
+
Strong's Concordance Pages
+
+
+
+ | Key |
+ Action |
+
+
+
+
+ | [ |
+ Previous Strong's number |
+
+
+ | ] |
+ Next Strong's number |
+
+
+ | j or ↓ |
+ Select next card (info, related, occurrence) |
+
+
+ | k or ↑ |
+ Select previous card |
+
+
+ | Enter |
+ Follow link on selected card |
+
+
+
+
Navigation keys are inspired by Vim conventions (hjkl) for users familiar with that paradigm, while also supporting standard arrow keys for everyone else.
A Note on Keyboard Navigation
diff --git a/kjvstudy_org/templates/strongs_entry.html b/kjvstudy_org/templates/strongs_entry.html
index 5feb5dd..32326ff 100644
--- a/kjvstudy_org/templates/strongs_entry.html
+++ b/kjvstudy_org/templates/strongs_entry.html
@@ -121,6 +121,13 @@
border: 1px solid var(--border-color);
border-radius: 10px;
padding: 1.5rem;
+ transition: all 0.15s;
+}
+
+.info-card.selected {
+ border-color: var(--link-color);
+ box-shadow: 0 0 0 2px rgba(74, 124, 89, 0.3);
+ background: #f8fff8;
}
.info-card h2 {
@@ -230,6 +237,12 @@
box-shadow: 0 1px 4px rgba(0,0,0,0.05);
}
+.related-entry-card.selected {
+ border-color: var(--link-color);
+ box-shadow: 0 0 0 2px rgba(74, 124, 89, 0.3);
+ background: #f8fff8;
+}
+
.related-entry-header {
display: flex;
align-items: baseline;
@@ -270,6 +283,11 @@
border-color: #333;
}
+[data-theme="dark"] .related-entry-card.selected {
+ background: #1a2a1a;
+ box-shadow: 0 0 0 2px rgba(107, 155, 122, 0.3);
+}
+
[data-theme="dark"] .related-entry-header a {
color: #6495ED;
}
@@ -480,6 +498,11 @@
border-color: #333;
}
+[data-theme="dark"] .info-card.selected {
+ background: #1a2a1a;
+ box-shadow: 0 0 0 2px rgba(107, 155, 122, 0.3);
+}
+
[data-theme="dark"] .kjv-tag {
background: #2a2a2a;
border-color: #444;
@@ -551,9 +574,9 @@
{{ entry.strongs }}
{{ entry.language }}
- {{ entry.word }}
- {{ entry.transliteration }}{% if entry.pronunciation %} ({{ entry.pronunciation }}){% endif %}
- Definition: {{ entry.definition }}
+ {{ entry.word }}
+ {{ entry.transliteration }}{% if entry.pronunciation %} ({{ entry.pronunciation }}){% endif %}
+ {{ entry.definition }}
@@ -661,24 +684,23 @@ function showMoreOccurrences() {
}
(function() {
- const allCards = document.querySelectorAll('.occurrence-card');
- const visibleCards = document.querySelectorAll('.occurrence-card:not(.hidden)');
- if (visibleCards.length === 0) return;
+ // Include info cards, related entries, and occurrence cards in keyboard nav
+ function getAllNavigableCards() {
+ const infoCards = document.querySelectorAll('.info-card');
+ const related = document.querySelectorAll('.related-entry-card');
+ const occurrences = document.querySelectorAll('.occurrence-card:not(.hidden)');
+ return [...infoCards, ...related, ...occurrences];
+ }
let selectedIndex = -1;
- function getVisibleCards() {
- return document.querySelectorAll('.occurrence-card:not(.hidden)');
- }
-
function selectCard(index) {
- const cards = getVisibleCards();
+ const cards = getAllNavigableCards();
+ if (cards.length === 0) return;
// Remove previous selection
- if (selectedIndex >= 0) {
- const prevCard = document.querySelector('.occurrence-card.selected');
- if (prevCard) prevCard.classList.remove('selected');
- }
+ const prevCard = document.querySelector('.info-card.selected, .related-entry-card.selected, .occurrence-card.selected');
+ if (prevCard) prevCard.classList.remove('selected');
// Update index with bounds checking
selectedIndex = Math.max(0, Math.min(index, cards.length - 1));
@@ -698,7 +720,8 @@ function showMoreOccurrences() {
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
if (typeof KJVNav !== 'undefined' && KJVNav.sidebarActive) return;
- const cards = getVisibleCards();
+ const cards = getAllNavigableCards();
+ if (cards.length === 0) return;
if (e.key === 'ArrowDown' || e.key === 'j') {
e.preventDefault();
@@ -708,18 +731,27 @@ function showMoreOccurrences() {
selectCard(selectedIndex - 1);
} else if (e.key === 'Enter' && selectedIndex >= 0 && selectedIndex < cards.length) {
e.preventDefault();
- const link = cards[selectedIndex].querySelector('.occ-reference');
+ // Check for link in any card type
+ const link = cards[selectedIndex].querySelector('.occ-reference, .related-entry-header a, .strongs-ref');
if (link) window.location.href = link.href;
+ } else if (e.key === '[') {
+ // Navigate to previous Strong's number
+ const prevLink = document.querySelector('.nav-btn[rel="prev"]');
+ if (prevLink) window.location.href = prevLink.href;
+ } else if (e.key === ']') {
+ // Navigate to next Strong's number
+ const nextLink = document.querySelector('.nav-btn[rel="next"]');
+ if (nextLink) window.location.href = nextLink.href;
}
});
- // Click to select
- allCards.forEach((card, index) => {
+ // Click to select - attach to all card types
+ document.querySelectorAll('.info-card, .related-entry-card, .occurrence-card').forEach((card) => {
card.addEventListener('click', function(e) {
if (e.target.tagName !== 'A') {
- const visCards = getVisibleCards();
- const visIndex = Array.from(visCards).indexOf(card);
- if (visIndex >= 0) selectCard(visIndex);
+ const allCards = getAllNavigableCards();
+ const cardIndex = allCards.indexOf(card);
+ if (cardIndex >= 0) selectCard(cardIndex);
}
});
});