mirror of
https://github.com/kennethreitz/kjvstudy.org.git
synced 2026-10-24 14:29:14 +00:00
Soup up the book landing pages (Joel et al.): Old/New Testament kicker, letterspaced-caps book title matching the chapter pages, gold-tipped Chapters heading, and key verses as gilt scripture plates with bronze references and quiet significance notes. Then a full sweep of the 32 remaining templates, applying the shared patterns (gold-tipped small-caps apparatus headings, elevated cards, chip buttons, gilt scripture plates, bronze micro-labels, token-only colors, dark mode from tokens alone): - about, about_claude, accessibility (system TOC cards, gilt CTA plate) - resources, resource_index (elevated cards, bronze counts; fixed a featured-card style built on raw gold hex) - names_of_god, tetragrammaton (scripture plates, chip actions) - biblical_angels, biblical_covenants, biblical_festivals - biblical_prophets, twelve_apostles, women_of_the_bible, fruits_of_spirit - parables, interlinear_landing - family_tree_person, family_tree_search (muted gender inks, gold for the messianic line) - family_tree_ancestors, _descendants, _generation, _lineage - search (scripture-plate results, gold-washed <mark> highlights), stars (star/gilt tokens), stats (stat-card grids in old-style numerals) - commentary_index, cross_references_index (in-place TOC variants), error (404/500 rebuilt as a framed plate with the lost-sheep parable rubricated — Luke 15:4) - reading_plan_detail (accent progress UI), topic_detail (scripture plates), strongs_language_index, stories_kids_index (~190 lines of purple dark-mode CSS removed) Also fixed the last stragglers the sweep verifier found: raw #4a7c59 JS outlines in story_detail and the shared tree keyboard-nav partial, and an undefined --border-color-light variable in stories_index. All 976 tests pass; data validation 9/9; every template compiles. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
371 lines
10 KiB
HTML
371 lines
10 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}{{ language }} Strong's Numbers - Strong's Concordance{% endblock %}
|
|
|
|
{% block description %}Browse all {{ total }} {{ language }} words in Strong's Exhaustive Concordance with definitions and KJV translations.{% endblock %}
|
|
|
|
{% block head %}
|
|
<style>
|
|
.strongs-index-page {
|
|
max-width: 900px;
|
|
}
|
|
|
|
.index-header {
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.index-stats {
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.14em;
|
|
color: var(--bronze);
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.entries-grid {
|
|
display: grid;
|
|
gap: 0.75rem;
|
|
}
|
|
|
|
.entry-card {
|
|
display: block;
|
|
background: var(--bg-elevated);
|
|
border: 1px solid var(--border-color-dark);
|
|
border-radius: 8px;
|
|
padding: 0.875rem 1rem;
|
|
text-decoration: none;
|
|
color: inherit;
|
|
transition: border-color 0.2s, box-shadow 0.2s, transform 0.2s;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.entry-card:hover {
|
|
border-color: var(--accent);
|
|
transform: translateY(-2px);
|
|
box-shadow: var(--shadow-soft);
|
|
}
|
|
|
|
.entry-card-inner {
|
|
display: grid;
|
|
grid-template-columns: auto 1fr;
|
|
gap: 0.75rem 1rem;
|
|
align-items: start;
|
|
}
|
|
|
|
.entry-number {
|
|
font-family: monospace;
|
|
font-size: 0.8rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
color: var(--bronze);
|
|
font-weight: 600;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.entry-content {
|
|
min-width: 0;
|
|
}
|
|
|
|
.entry-word-row {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 0.5rem;
|
|
margin-bottom: 0.25rem;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.entry-word {
|
|
font-size: 1.25rem;
|
|
color: var(--text-strong);
|
|
}
|
|
|
|
.entry-word.hebrew {
|
|
direction: rtl;
|
|
font-family: "SBL Hebrew", "Ezra SIL", "Times New Roman", serif;
|
|
}
|
|
|
|
.entry-word.greek {
|
|
font-family: "SBL Greek", "Gentium Plus", "Times New Roman", serif;
|
|
}
|
|
|
|
.entry-translit {
|
|
font-size: 0.9rem;
|
|
color: var(--text-secondary);
|
|
font-style: italic;
|
|
}
|
|
|
|
.entry-definition {
|
|
font-size: 0.9rem;
|
|
color: var(--text-color);
|
|
margin: 0;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
/* Pagination */
|
|
.pagination {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
margin: 2rem 0;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.page-btn {
|
|
padding: 0.5rem 0.875rem;
|
|
font-size: 0.9rem;
|
|
background: var(--bg-elevated);
|
|
border: 1px solid var(--border-color-dark);
|
|
border-radius: 6px;
|
|
text-decoration: none;
|
|
color: var(--text-secondary);
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.page-btn:hover {
|
|
background: var(--accent-softer);
|
|
border-color: var(--accent);
|
|
color: var(--accent-strong);
|
|
}
|
|
|
|
.page-btn.active {
|
|
background: var(--accent-fill);
|
|
border-color: var(--accent-fill);
|
|
color: var(--on-accent);
|
|
}
|
|
|
|
.page-btn.disabled {
|
|
opacity: 0.5;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.page-ellipsis {
|
|
padding: 0.5rem 0.25rem;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.page-info {
|
|
font-size: 0.9rem;
|
|
color: var(--text-secondary);
|
|
margin-left: 1rem;
|
|
}
|
|
|
|
/* Back link */
|
|
.back-link {
|
|
display: inline-block;
|
|
margin-bottom: 1.5rem;
|
|
padding: 0.45rem 0.9rem;
|
|
background: var(--bg-elevated);
|
|
border: 1px solid var(--border-color-dark);
|
|
border-radius: 6px;
|
|
color: var(--text-secondary);
|
|
text-decoration: none;
|
|
font-size: 0.9rem;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.back-link:hover {
|
|
background: var(--accent-softer);
|
|
border-color: var(--accent);
|
|
color: var(--accent-strong);
|
|
text-decoration: none;
|
|
}
|
|
|
|
/* Dark mode is handled entirely by the shared design tokens in base.html. */
|
|
|
|
@media (max-width: 600px) {
|
|
.entry-card-inner {
|
|
grid-template-columns: 1fr;
|
|
gap: 0.25rem;
|
|
}
|
|
|
|
.pagination {
|
|
gap: 0.25rem;
|
|
}
|
|
|
|
.page-btn {
|
|
padding: 0.4rem 0.6rem;
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
.page-info {
|
|
width: 100%;
|
|
text-align: center;
|
|
margin: 0.5rem 0 0 0;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="strongs-index-page">
|
|
<a href="/strongs" class="back-link">← Back to Strong's Concordance</a>
|
|
|
|
<div class="index-header">
|
|
<h1>{{ language }} Strong's Numbers</h1>
|
|
<p class="index-stats">
|
|
{{ total }} entries total — Page {{ page }} of {{ total_pages }}
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Pagination at top -->
|
|
{% if total_pages > 1 %}
|
|
<nav class="pagination">
|
|
{% if page > 1 %}
|
|
<a href="/strongs/{{ language_code }}?page=1" class="page-btn">First</a>
|
|
<a href="/strongs/{{ language_code }}?page={{ page - 1 }}" class="page-btn">← Prev</a>
|
|
{% else %}
|
|
<span class="page-btn disabled">First</span>
|
|
<span class="page-btn disabled">← Prev</span>
|
|
{% endif %}
|
|
|
|
{% set start_page = [1, page - 2]|max %}
|
|
{% set end_page = [total_pages, page + 2]|min %}
|
|
|
|
{% if start_page > 1 %}
|
|
<span class="page-ellipsis">...</span>
|
|
{% endif %}
|
|
|
|
{% for p in range(start_page, end_page + 1) %}
|
|
<a href="/strongs/{{ language_code }}?page={{ p }}" class="page-btn {% if p == page %}active{% endif %}">{{ p }}</a>
|
|
{% endfor %}
|
|
|
|
{% if end_page < total_pages %}
|
|
<span class="page-ellipsis">...</span>
|
|
{% endif %}
|
|
|
|
{% if page < total_pages %}
|
|
<a href="/strongs/{{ language_code }}?page={{ page + 1 }}" class="page-btn">Next →</a>
|
|
<a href="/strongs/{{ language_code }}?page={{ total_pages }}" class="page-btn">Last</a>
|
|
{% else %}
|
|
<span class="page-btn disabled">Next →</span>
|
|
<span class="page-btn disabled">Last</span>
|
|
{% endif %}
|
|
</nav>
|
|
{% endif %}
|
|
|
|
<div class="entries-grid">
|
|
{% for entry in entries %}
|
|
<a href="/strongs/{{ entry.strongs }}" class="entry-card">
|
|
<div class="entry-card-inner">
|
|
<span class="entry-number">{{ entry.strongs }}</span>
|
|
<div class="entry-content">
|
|
<div class="entry-word-row">
|
|
<span class="entry-word {% if language == 'Hebrew' %}hebrew{% else %}greek{% endif %}">{{ entry.word }}</span>
|
|
{% if entry.transliteration %}
|
|
<span class="entry-translit">({{ entry.transliteration }})</span>
|
|
{% endif %}
|
|
</div>
|
|
<p class="entry-definition">{{ entry.definition }}{% if entry.definition|length >= 147 %}...{% endif %}</p>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<!-- Pagination at bottom -->
|
|
{% if total_pages > 1 %}
|
|
<nav class="pagination">
|
|
{% if page > 1 %}
|
|
<a href="/strongs/{{ language_code }}?page=1" class="page-btn">First</a>
|
|
<a href="/strongs/{{ language_code }}?page={{ page - 1 }}" class="page-btn">← Prev</a>
|
|
{% else %}
|
|
<span class="page-btn disabled">First</span>
|
|
<span class="page-btn disabled">← Prev</span>
|
|
{% endif %}
|
|
|
|
{% set start_page = [1, page - 2]|max %}
|
|
{% set end_page = [total_pages, page + 2]|min %}
|
|
|
|
{% if start_page > 1 %}
|
|
<span class="page-ellipsis">...</span>
|
|
{% endif %}
|
|
|
|
{% for p in range(start_page, end_page + 1) %}
|
|
<a href="/strongs/{{ language_code }}?page={{ p }}" class="page-btn {% if p == page %}active{% endif %}">{{ p }}</a>
|
|
{% endfor %}
|
|
|
|
{% if end_page < total_pages %}
|
|
<span class="page-ellipsis">...</span>
|
|
{% endif %}
|
|
|
|
{% if page < total_pages %}
|
|
<a href="/strongs/{{ language_code }}?page={{ page + 1 }}" class="page-btn">Next →</a>
|
|
<a href="/strongs/{{ language_code }}?page={{ total_pages }}" class="page-btn">Last</a>
|
|
{% else %}
|
|
<span class="page-btn disabled">Next →</span>
|
|
<span class="page-btn disabled">Last</span>
|
|
{% endif %}
|
|
|
|
<span class="page-info">Page {{ page }} of {{ total_pages }}</span>
|
|
</nav>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<script>
|
|
(function() {
|
|
const entries = Array.from(document.querySelectorAll('.entry-card'));
|
|
if (entries.length === 0) return;
|
|
|
|
let selectedIndex = -1;
|
|
|
|
function selectEntry(index) {
|
|
if (selectedIndex >= 0 && selectedIndex < entries.length) {
|
|
entries[selectedIndex].style.outline = '';
|
|
entries[selectedIndex].style.outlineOffset = '';
|
|
entries[selectedIndex].classList.remove('selected');
|
|
}
|
|
selectedIndex = Math.max(0, Math.min(index, entries.length - 1));
|
|
entries[selectedIndex].style.outline = '2px solid var(--accent)';
|
|
entries[selectedIndex].style.outlineOffset = '2px';
|
|
entries[selectedIndex].classList.add('selected');
|
|
entries[selectedIndex].scrollIntoView({ behavior: 'auto', block: 'center' });
|
|
}
|
|
|
|
document.addEventListener('keydown', function(e) {
|
|
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
|
|
if (KJVNav.sidebarActive) return;
|
|
|
|
if (e.key === 'ArrowDown' || e.key === 'j') {
|
|
e.preventDefault();
|
|
if (KJVNav.isSelectionOffScreen(entries, selectedIndex)) {
|
|
selectEntry(KJVNav.findFirstVisibleIndex(entries));
|
|
} else {
|
|
selectEntry(selectedIndex < 0 ? 0 : selectedIndex + 1);
|
|
}
|
|
} else if (e.key === 'ArrowUp' || e.key === 'k') {
|
|
e.preventDefault();
|
|
if (KJVNav.isSelectionOffScreen(entries, selectedIndex)) {
|
|
selectEntry(KJVNav.findFirstVisibleIndex(entries));
|
|
} else if (selectedIndex <= 0) {
|
|
selectEntry(0);
|
|
} else {
|
|
selectEntry(selectedIndex - 1);
|
|
}
|
|
} else if (e.key === 'ArrowLeft' || e.key === 'h') {
|
|
e.preventDefault();
|
|
history.back();
|
|
} else if (e.key === 'ArrowRight' || e.key === 'l') {
|
|
// Next page
|
|
const nextBtn = document.querySelector('.pagination .page-btn:not(.disabled):not(.active)');
|
|
const nextLink = document.querySelector('a.page-btn[href*="page={{ page + 1 }}"]');
|
|
if (nextLink) window.location.href = nextLink.href;
|
|
} else if (e.key === 'Enter' && selectedIndex >= 0) {
|
|
e.preventDefault();
|
|
// Card is now the link itself
|
|
window.location.href = entries[selectedIndex].href;
|
|
} else if (e.key === 'Escape') {
|
|
e.preventDefault();
|
|
if (selectedIndex >= 0 && selectedIndex < entries.length) {
|
|
entries[selectedIndex].style.outline = '';
|
|
entries[selectedIndex].style.outlineOffset = '';
|
|
entries[selectedIndex].classList.remove('selected');
|
|
}
|
|
selectedIndex = -1;
|
|
}
|
|
});
|
|
})();
|
|
</script>
|
|
{% endblock %}
|