mirror of
https://github.com/kennethreitz/kjvstudy.org.git
synced 2026-06-05 23:00:16 +00:00
f6b5cc54bc
Change verse number links to use pointer cursor instead of help cursor. The help cursor (?) is now only shown on verse reference links that have tooltips, not on the verse numbers themselves in chapter view. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1940 lines
64 KiB
HTML
1940 lines
64 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8"/>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||
|
||
<title>{% block title %}Authorized King James Version Bible{% endblock %}</title>
|
||
|
||
<meta name="description" content="{% block description %}Study the Authorized King James Version Bible{% endblock %}"/>
|
||
|
||
<!-- Canonical URL -->
|
||
<link rel="canonical" href="https://kjvstudy.org{% block canonical_path %}{{ request.url.path }}{% endblock %}"/>
|
||
|
||
<!-- Open Graph / Facebook -->
|
||
<meta property="og:type" content="{% block og_type %}website{% endblock %}"/>
|
||
<meta property="og:url" content="https://kjvstudy.org{{ request.url.path }}"/>
|
||
<meta property="og:title" content="{% block og_title %}{% block title_text %}Authorized King James Version Bible{% endblock %}{% endblock %}"/>
|
||
<meta property="og:description" content="{% block og_description %}{% block description_text %}Study the Authorized King James Version Bible{% endblock %}{% endblock %}"/>
|
||
<meta property="og:site_name" content="KJV Study"/>
|
||
<meta property="og:image" content="{% block og_image %}https://kjvstudy.org/static/og-image.png{% endblock %}"/>
|
||
<meta property="og:image:width" content="1200"/>
|
||
<meta property="og:image:height" content="630"/>
|
||
|
||
<!-- Twitter Card -->
|
||
<meta name="twitter:card" content="summary_large_image"/>
|
||
<meta name="twitter:url" content="https://kjvstudy.org{{ request.url.path }}"/>
|
||
<meta name="twitter:title" content="{% block twitter_title %}{% block title_plain %}Authorized King James Version Bible{% endblock %}{% endblock %}"/>
|
||
<meta name="twitter:description" content="{% block twitter_description %}{% block description_plain %}Study the Authorized King James Version Bible{% endblock %}{% endblock %}"/>
|
||
<meta name="twitter:image" content="{% block twitter_image %}https://kjvstudy.org/static/og-image.png{% endblock %}"/>
|
||
|
||
<link rel="stylesheet" href="/static/tufte.css"/>
|
||
|
||
{% block head %}{% endblock %}
|
||
|
||
<!-- Structured Data (Schema.org) -->
|
||
<script type="application/ld+json">
|
||
{
|
||
"@context": "https://schema.org",
|
||
"@type": "WebSite",
|
||
"name": "KJV Study",
|
||
"url": "https://kjvstudy.org",
|
||
"description": "Study the Authorized King James Version Bible with commentary, study guides, and biblical resources",
|
||
"potentialAction": {
|
||
"@type": "SearchAction",
|
||
"target": "https://kjvstudy.org/search?q={search_term_string}",
|
||
"query-input": "required name=search_term_string"
|
||
}
|
||
}
|
||
</script>
|
||
{% block structured_data %}{% endblock %}
|
||
|
||
<style>
|
||
/* Color scheme variables */
|
||
:root {
|
||
--bg-color: #fffff8;
|
||
--text-color: #111;
|
||
--text-secondary: #666;
|
||
--text-tertiary: #888;
|
||
--text-quaternary: #999;
|
||
--border-color: #eee;
|
||
--border-color-dark: #ddd;
|
||
--border-color-darker: #ccc;
|
||
--link-color: #333;
|
||
--link-hover: #000;
|
||
--code-bg: #f5f5f5;
|
||
}
|
||
|
||
[data-theme="dark"] {
|
||
--bg-color: #1a1a1a;
|
||
--text-color: #e0e0e0;
|
||
--text-secondary: #b0b0b0;
|
||
--text-tertiary: #909090;
|
||
--text-quaternary: #707070;
|
||
--border-color: #333;
|
||
--border-color-dark: #444;
|
||
--border-color-darker: #555;
|
||
--link-color: #d0d0d0;
|
||
--link-hover: #fff;
|
||
--code-bg: #2a2a2a;
|
||
}
|
||
|
||
/* Override Tufte CSS sidenote constraints */
|
||
.sidenote,
|
||
.marginnote {
|
||
max-height: none !important;
|
||
}
|
||
|
||
label.sidenote-number {
|
||
max-height: none !important;
|
||
}
|
||
|
||
/* Verse tooltip styles */
|
||
/* Links to verses get help cursor (they show tooltips) */
|
||
a[href*="/book/"][href*="/chapter/"][href*="/verse/"]:not(.verse-number-link),
|
||
a[href*="/book/"][href*="/chapter/"][href*="#verse-"]:not(.verse-number-link) {
|
||
cursor: help;
|
||
}
|
||
|
||
/* Verse numbers get normal pointer cursor */
|
||
.verse-number-link {
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* But not in search dropdowns */
|
||
.search-results-dropdown a,
|
||
.search-results-dropdown a[href*="/book/"],
|
||
.search-dropdown a,
|
||
.search-dropdown a[href*="/book/"],
|
||
.lookup-results-dropdown a,
|
||
.lookup-results-dropdown a[href*="/book/"],
|
||
.story-search-dropdown a,
|
||
.story-search-dropdown a[href*="/book/"] {
|
||
cursor: pointer !important;
|
||
}
|
||
|
||
.verse-tooltip {
|
||
position: absolute;
|
||
background: var(--bg-color);
|
||
border: 2px solid var(--border-color-darker);
|
||
border-radius: 6px;
|
||
padding: 1rem;
|
||
max-width: 400px;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||
z-index: 9999;
|
||
font-size: 0.95rem;
|
||
line-height: 1.6;
|
||
color: var(--text-color);
|
||
pointer-events: none;
|
||
opacity: 0;
|
||
transition: opacity 0.2s ease-in-out;
|
||
}
|
||
|
||
.verse-tooltip.show {
|
||
opacity: 1;
|
||
}
|
||
|
||
.verse-tooltip-reference {
|
||
font-weight: 600;
|
||
color: var(--link-color);
|
||
margin-bottom: 0.5rem;
|
||
display: block;
|
||
}
|
||
|
||
.verse-tooltip-text {
|
||
font-style: italic;
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
.verse-tooltip-loading {
|
||
color: var(--text-tertiary);
|
||
}
|
||
|
||
[data-theme="dark"] .verse-tooltip {
|
||
background: #2a2a2a;
|
||
border-color: #555;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
||
}
|
||
|
||
@media (prefers-color-scheme: dark) {
|
||
.verse-tooltip:not([data-theme]) {
|
||
background: #2a2a2a;
|
||
border-color: #555;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
||
}
|
||
}
|
||
|
||
/* Enhanced typography and spacing */
|
||
body {
|
||
counter-reset: sidenote-counter;
|
||
background-color: var(--bg-color);
|
||
color: var(--text-color);
|
||
transition: background-color 0.3s ease, color 0.3s ease;
|
||
}
|
||
|
||
article {
|
||
padding: 2rem 5%;
|
||
}
|
||
|
||
h1, h2, h3 {
|
||
font-weight: 400;
|
||
font-style: normal;
|
||
}
|
||
|
||
h1 {
|
||
font-size: 2.8rem;
|
||
line-height: 1.2;
|
||
margin-top: 3rem;
|
||
margin-bottom: 1.5rem;
|
||
letter-spacing: -0.02em;
|
||
}
|
||
|
||
h2 {
|
||
font-size: 2rem;
|
||
line-height: 1.3;
|
||
margin-top: 3rem;
|
||
margin-bottom: 1rem;
|
||
font-style: italic;
|
||
}
|
||
|
||
p {
|
||
font-size: 1.4rem;
|
||
line-height: 2;
|
||
margin-top: 1.4rem;
|
||
}
|
||
|
||
/* Drop cap for opening paragraphs */
|
||
.newthought {
|
||
font-variant: small-caps;
|
||
letter-spacing: 0.05em;
|
||
}
|
||
|
||
/* Refined breadcrumb navigation */
|
||
.breadcrumb {
|
||
margin: 2rem 0 3rem 0;
|
||
font-size: 0.95rem;
|
||
color: var(--text-secondary);
|
||
font-style: italic;
|
||
border-bottom: 1px solid var(--border-color);
|
||
padding-bottom: 1rem;
|
||
}
|
||
|
||
.breadcrumb a {
|
||
color: var(--link-color);
|
||
text-decoration: none;
|
||
transition: color 0.2s;
|
||
}
|
||
|
||
.breadcrumb a:hover {
|
||
color: var(--link-hover);
|
||
}
|
||
|
||
.breadcrumb-separator {
|
||
margin: 0 0.75rem;
|
||
color: var(--text-quaternary);
|
||
}
|
||
|
||
/* Enhanced link styling */
|
||
a {
|
||
color: var(--link-color);
|
||
text-decoration: none;
|
||
border-bottom: 1px solid var(--border-color-dark);
|
||
transition: all 0.2s;
|
||
}
|
||
|
||
a:hover {
|
||
color: var(--link-hover);
|
||
border-bottom-color: var(--link-hover);
|
||
}
|
||
|
||
/* Section dividers */
|
||
section {
|
||
margin-top: 3rem;
|
||
padding-top: 2rem;
|
||
}
|
||
|
||
/* Ornamental breaks */
|
||
.ornament {
|
||
text-align: center;
|
||
margin: 3rem 0;
|
||
color: var(--text-quaternary);
|
||
font-size: 1.5rem;
|
||
letter-spacing: 1rem;
|
||
}
|
||
|
||
/* Floating Navigation Sidebar */
|
||
.nav-sidebar {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 140px;
|
||
height: 100vh;
|
||
overflow-y: auto;
|
||
background: var(--bg-color);
|
||
padding: 1.5rem 0.75rem 1rem 0.75rem;
|
||
font-size: 0.7rem;
|
||
line-height: 1.3;
|
||
z-index: 100;
|
||
border-right: 1px solid var(--border-color);
|
||
direction: rtl;
|
||
}
|
||
|
||
.nav-sidebar > * {
|
||
direction: ltr;
|
||
}
|
||
|
||
.nav-sidebar::-webkit-scrollbar {
|
||
width: 4px;
|
||
}
|
||
|
||
.nav-sidebar::-webkit-scrollbar-track {
|
||
background: transparent;
|
||
}
|
||
|
||
.nav-sidebar::-webkit-scrollbar-thumb {
|
||
background: #ddd;
|
||
border-radius: 2px;
|
||
}
|
||
|
||
.nav-sidebar h3 {
|
||
font-size: 0.65rem;
|
||
font-weight: 600;
|
||
font-style: italic;
|
||
margin: 0 0 0.3rem 0;
|
||
padding-bottom: 0.25rem;
|
||
border-bottom: 1px solid var(--border-color);
|
||
color: var(--text-secondary);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.05em;
|
||
}
|
||
|
||
.nav-sidebar ul {
|
||
list-style: none;
|
||
padding: 0;
|
||
margin: 0 0 0.75rem 0;
|
||
}
|
||
|
||
.nav-sidebar li {
|
||
margin: 0.15rem 0;
|
||
}
|
||
|
||
.nav-sidebar a {
|
||
color: var(--text-secondary);
|
||
text-decoration: none;
|
||
border-bottom: none;
|
||
display: block;
|
||
padding: 0.15rem 0;
|
||
transition: color 0.2s;
|
||
font-size: 0.85rem;
|
||
}
|
||
|
||
.nav-sidebar a:hover {
|
||
color: var(--link-hover);
|
||
}
|
||
|
||
.nav-sidebar a.current {
|
||
color: var(--link-hover);
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* Book type color indicators in sidebar */
|
||
.nav-sidebar .book-list a {
|
||
border-left: 3px solid transparent;
|
||
padding-left: 0.3rem;
|
||
}
|
||
|
||
.nav-sidebar .book-list a.law {
|
||
border-left-color: rgba(59, 130, 246, 0.6);
|
||
}
|
||
|
||
.nav-sidebar .book-list a.historical {
|
||
border-left-color: rgba(34, 197, 94, 0.6);
|
||
}
|
||
|
||
.nav-sidebar .book-list a.wisdom {
|
||
border-left-color: rgba(168, 85, 247, 0.6);
|
||
}
|
||
|
||
.nav-sidebar .book-list a.major-prophets {
|
||
border-left-color: rgba(249, 115, 22, 0.6);
|
||
}
|
||
|
||
.nav-sidebar .book-list a.minor-prophets {
|
||
border-left-color: rgba(239, 68, 68, 0.6);
|
||
}
|
||
|
||
.nav-sidebar .book-list a.gospels {
|
||
border-left-color: rgba(234, 179, 8, 0.6);
|
||
}
|
||
|
||
.nav-sidebar .book-list a.acts {
|
||
border-left-color: rgba(20, 184, 166, 0.6);
|
||
}
|
||
|
||
.nav-sidebar .book-list a.pauline {
|
||
border-left-color: rgba(99, 102, 241, 0.6);
|
||
}
|
||
|
||
.nav-sidebar .book-list a.general {
|
||
border-left-color: rgba(236, 72, 153, 0.6);
|
||
}
|
||
|
||
.nav-sidebar .book-list a.apocalyptic {
|
||
border-left-color: rgba(220, 38, 38, 0.6);
|
||
}
|
||
|
||
.nav-sidebar .testament-section {
|
||
margin-bottom: 0.75rem;
|
||
}
|
||
|
||
.nav-sidebar .testament-title {
|
||
font-size: 0.7rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.08em;
|
||
color: var(--text-tertiary);
|
||
margin-bottom: 0.3rem;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.nav-sidebar details {
|
||
margin-bottom: 0.75rem;
|
||
}
|
||
|
||
.nav-sidebar summary {
|
||
cursor: pointer;
|
||
font-size: 0.7rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.08em;
|
||
color: var(--text-tertiary);
|
||
margin-bottom: 0.3rem;
|
||
font-weight: 600;
|
||
list-style: none;
|
||
user-select: none;
|
||
transition: color 0.2s;
|
||
}
|
||
|
||
.nav-sidebar summary:hover {
|
||
color: var(--text-secondary);
|
||
}
|
||
|
||
.nav-sidebar summary::-webkit-details-marker {
|
||
display: none;
|
||
}
|
||
|
||
.nav-sidebar summary::before {
|
||
content: '▸ ';
|
||
display: inline-block;
|
||
transition: transform 0.2s ease;
|
||
margin-right: 0.2rem;
|
||
}
|
||
|
||
.nav-sidebar details[open] summary::before {
|
||
transform: rotate(90deg);
|
||
}
|
||
|
||
/* Smooth expand/collapse animation */
|
||
.nav-sidebar details > ul {
|
||
animation: slideDown 0.2s ease-out;
|
||
}
|
||
|
||
@keyframes slideDown {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(-5px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
/* Smooth scrolling */
|
||
.nav-sidebar {
|
||
scroll-behavior: smooth;
|
||
}
|
||
|
||
.nav-sidebar .book-list {
|
||
font-size: 0.7rem;
|
||
}
|
||
|
||
/* Sidebar search box */
|
||
.sidebar-search {
|
||
margin-bottom: 0.75rem;
|
||
position: relative;
|
||
}
|
||
|
||
.sidebar-search input {
|
||
width: 90%;
|
||
padding: 0.4rem 0.5rem;
|
||
border: 1px solid var(--border-color-dark);
|
||
border-radius: 3px;
|
||
font-size: 0.75rem;
|
||
background: var(--bg-color);
|
||
color: var(--text-color);
|
||
transition: border-color 0.2s;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.sidebar-search input:focus {
|
||
outline: none;
|
||
border-color: var(--text-tertiary);
|
||
}
|
||
|
||
/* Universal search dropdown */
|
||
.search-results-dropdown {
|
||
position: absolute;
|
||
top: 100%;
|
||
left: 0;
|
||
right: 0;
|
||
background: var(--bg-color);
|
||
border: 1px solid var(--border-color-dark);
|
||
border-top: none;
|
||
border-radius: 0 0 3px 3px;
|
||
max-height: 400px;
|
||
overflow-y: auto;
|
||
z-index: 1000;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||
display: none;
|
||
}
|
||
|
||
.search-results-dropdown.show {
|
||
display: block;
|
||
}
|
||
|
||
.search-results-category {
|
||
padding: 0.5rem;
|
||
border-bottom: 1px solid var(--border-color);
|
||
}
|
||
|
||
.search-results-category:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.search-results-category-title {
|
||
font-size: 0.6rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.08em;
|
||
color: var(--text-tertiary);
|
||
margin-bottom: 0.3rem;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.search-result-item {
|
||
display: block;
|
||
padding: 0.3rem 0.4rem;
|
||
font-size: 0.75rem;
|
||
color: var(--text-color);
|
||
text-decoration: none;
|
||
border-bottom: none;
|
||
border-radius: 2px;
|
||
transition: background-color 0.15s;
|
||
}
|
||
|
||
.search-result-item:hover,
|
||
.search-result-item.selected {
|
||
background: var(--border-color);
|
||
color: var(--link-hover);
|
||
}
|
||
|
||
.search-result-item .result-title {
|
||
display: block;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.search-result-item .result-meta {
|
||
font-size: 0.65rem;
|
||
color: var(--text-tertiary);
|
||
display: block;
|
||
margin-top: 0.1rem;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.search-no-results {
|
||
padding: 0.75rem;
|
||
text-align: center;
|
||
color: var(--text-tertiary);
|
||
font-size: 0.75rem;
|
||
font-style: italic;
|
||
}
|
||
|
||
.search-loading {
|
||
padding: 0.75rem;
|
||
text-align: center;
|
||
color: var(--text-tertiary);
|
||
font-size: 0.75rem;
|
||
}
|
||
|
||
.search-view-all {
|
||
display: block;
|
||
padding: 0.5rem;
|
||
text-align: center;
|
||
font-size: 0.7rem;
|
||
background: var(--border-color);
|
||
color: var(--text-secondary);
|
||
text-decoration: none;
|
||
border-bottom: none;
|
||
}
|
||
|
||
.search-view-all:hover {
|
||
background: var(--border-color-dark);
|
||
color: var(--link-hover);
|
||
}
|
||
|
||
[data-theme="dark"] .search-results-dropdown {
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
|
||
}
|
||
|
||
/* Resource grouping */
|
||
.resource-group {
|
||
margin-bottom: 1.5rem;
|
||
}
|
||
|
||
.resource-group summary {
|
||
cursor: pointer;
|
||
font-size: 0.7rem;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.05em;
|
||
color: var(--text-tertiary);
|
||
font-weight: 600;
|
||
margin: 1rem 0 0.5rem 0;
|
||
padding-top: 0.5rem;
|
||
border-top: 1px solid var(--border-color);
|
||
user-select: none;
|
||
}
|
||
|
||
.resource-group:first-of-type summary {
|
||
border-top: none;
|
||
margin-top: 0;
|
||
padding-top: 0;
|
||
}
|
||
|
||
.resource-group summary:hover {
|
||
color: var(--text-color);
|
||
}
|
||
|
||
/* Sidebar flourish */
|
||
.sidebar-flourish {
|
||
text-align: center;
|
||
margin: 2rem 0 1rem 0;
|
||
padding-top: 1.5rem;
|
||
border-top: 1px solid var(--border-color);
|
||
color: var(--text-tertiary);
|
||
font-size: 1rem;
|
||
letter-spacing: 0.5em;
|
||
opacity: 0.6;
|
||
}
|
||
|
||
/* Sidebar collapse functionality */
|
||
#sidebar-toggle {
|
||
display: none;
|
||
}
|
||
|
||
.sidebar-toggle-container {
|
||
position: fixed;
|
||
top: 1rem;
|
||
left: 0.75rem;
|
||
z-index: 101;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
|
||
.sidebar-toggle-btn {
|
||
width: auto;
|
||
min-width: 20px;
|
||
height: 20px;
|
||
padding: 0 0.4rem;
|
||
cursor: pointer;
|
||
background: var(--bg-color);
|
||
border: 1px solid var(--border-color-darker);
|
||
border-radius: 3px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 0.7rem;
|
||
color: var(--text-secondary);
|
||
transition: all 0.2s;
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.sidebar-toggle-btn:hover {
|
||
border-color: var(--text-tertiary);
|
||
color: var(--link-hover);
|
||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
|
||
}
|
||
|
||
/* Dark mode toggle */
|
||
.dark-mode-toggle {
|
||
position: fixed;
|
||
top: 2rem;
|
||
right: 2rem;
|
||
z-index: 101;
|
||
margin: -25px 0 0 0;
|
||
padding: 0;
|
||
}
|
||
|
||
.dark-mode-btn {
|
||
width: 24px;
|
||
height: 24px;
|
||
cursor: pointer;
|
||
background: transparent;
|
||
border: 1px solid var(--border-color-darker);
|
||
border-radius: 3px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 0.85rem;
|
||
color: var(--text-secondary);
|
||
transition: all 0.3s;
|
||
}
|
||
|
||
.dark-mode-btn:hover {
|
||
border-color: var(--text-tertiary);
|
||
color: var(--link-hover);
|
||
}
|
||
|
||
.dark-mode-btn::before {
|
||
content: '☀';
|
||
}
|
||
|
||
[data-theme="dark"] .dark-mode-btn::before {
|
||
content: '☾';
|
||
}
|
||
|
||
.nav-sidebar {
|
||
transform: translateX(-100%);
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.sidebar-toggle-container {
|
||
left: 0.75rem;
|
||
}
|
||
|
||
.sidebar-toggle-btn::before {
|
||
content: 'Menu';
|
||
font-size: 0.65rem;
|
||
font-weight: 600;
|
||
letter-spacing: 0.03em;
|
||
text-transform: uppercase;
|
||
}
|
||
|
||
#sidebar-toggle:checked ~ .nav-sidebar {
|
||
transform: translateX(0);
|
||
opacity: 1;
|
||
pointer-events: auto;
|
||
}
|
||
|
||
#sidebar-toggle:checked ~ .sidebar-toggle-container {
|
||
left: 0.75rem;
|
||
}
|
||
|
||
#sidebar-toggle:checked ~ .sidebar-toggle-container .sidebar-toggle-btn::before {
|
||
content: '×';
|
||
font-size: 1.2rem;
|
||
font-weight: 400;
|
||
}
|
||
|
||
/* Responsive design for tablets and mobile */
|
||
@media (max-width: 1200px) {
|
||
.nav-sidebar {
|
||
width: 140px;
|
||
left: -140px;
|
||
top: 0;
|
||
bottom: 0;
|
||
max-height: 100vh;
|
||
border-radius: 0;
|
||
border-left: none;
|
||
padding-top: 4rem;
|
||
}
|
||
|
||
#sidebar-toggle:checked ~ .nav-sidebar {
|
||
left: 0;
|
||
}
|
||
|
||
.sidebar-toggle-container {
|
||
display: block;
|
||
top: 1rem;
|
||
left: 1rem;
|
||
}
|
||
|
||
.sidebar-toggle-btn {
|
||
width: 36px;
|
||
height: 36px;
|
||
font-size: 1.2rem;
|
||
background: var(--bg-color);
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||
}
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
/* iOS-specific optimizations */
|
||
body {
|
||
-webkit-text-size-adjust: 100%;
|
||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
/* Keep dark mode toggle on mobile, just reposition */
|
||
.dark-mode-toggle {
|
||
top: 1rem;
|
||
right: 1rem;
|
||
margin: 0;
|
||
min-width: 44px;
|
||
min-height: 44px;
|
||
}
|
||
|
||
/* Adjust article width for mobile */
|
||
article {
|
||
width: 95%;
|
||
padding: 1rem;
|
||
}
|
||
|
||
/* Optimize typography for mobile with better contrast */
|
||
body {
|
||
font-size: 16px;
|
||
}
|
||
|
||
h1 {
|
||
font-size: 2.2rem;
|
||
line-height: 2.4rem;
|
||
font-weight: 800;
|
||
color: #000;
|
||
letter-spacing: -0.02em;
|
||
}
|
||
|
||
[data-theme="dark"] h1 {
|
||
color: #fff;
|
||
}
|
||
|
||
h2 {
|
||
font-size: 1.65rem;
|
||
line-height: 1.85rem;
|
||
font-weight: 700;
|
||
color: #000;
|
||
font-style: normal;
|
||
}
|
||
|
||
[data-theme="dark"] h2 {
|
||
color: #fff;
|
||
}
|
||
|
||
h3 {
|
||
font-size: 1.3rem;
|
||
font-weight: 700;
|
||
color: #000;
|
||
}
|
||
|
||
[data-theme="dark"] h3 {
|
||
color: #fff;
|
||
}
|
||
|
||
p {
|
||
font-size: 1rem;
|
||
line-height: 1.8;
|
||
color: var(--text-color);
|
||
}
|
||
|
||
/* Enhanced link visibility for mobile - strong contrast */
|
||
a {
|
||
border-bottom: 2px solid #999;
|
||
padding-bottom: 1px;
|
||
color: #000;
|
||
font-weight: 500;
|
||
}
|
||
|
||
[data-theme="dark"] a {
|
||
border-bottom-color: #666;
|
||
color: #e0e0e0;
|
||
}
|
||
|
||
a:hover, a:active {
|
||
border-bottom-color: #333;
|
||
}
|
||
|
||
[data-theme="dark"] a:hover,
|
||
[data-theme="dark"] a:active {
|
||
border-bottom-color: #999;
|
||
}
|
||
|
||
/* Touch target sizing only for interactive elements, not inline text links */
|
||
button, .btn, input[type="submit"], .quick-link-btn {
|
||
min-height: 44px;
|
||
min-width: 44px;
|
||
}
|
||
|
||
/* Make max-width sections full width on mobile */
|
||
section p[style*="max-width"],
|
||
section div[style*="max-width"],
|
||
.intro-text,
|
||
.plan-overview,
|
||
.topic-overview,
|
||
.verse-lookup,
|
||
.share-container,
|
||
.sample-days,
|
||
.subtopics-container,
|
||
.plan-stats {
|
||
max-width: 100% !important;
|
||
}
|
||
|
||
/* Optimize sidenotes for mobile with strong contrast */
|
||
.sidenote,
|
||
.marginnote {
|
||
display: block;
|
||
float: none;
|
||
width: 100%;
|
||
margin: 1rem 0 1rem 1.5rem;
|
||
padding: 0.75rem 0 0.75rem 1rem;
|
||
border-left: 4px solid #999;
|
||
font-size: 0.95rem;
|
||
line-height: 1.6;
|
||
color: #444 !important;
|
||
background-color: transparent !important;
|
||
font-weight: 400;
|
||
}
|
||
|
||
[data-theme="dark"] .sidenote,
|
||
[data-theme="dark"] .marginnote {
|
||
border-left-color: #666;
|
||
color: #aaa !important;
|
||
background-color: #151515 !important;
|
||
}
|
||
|
||
@media (prefers-color-scheme: dark) {
|
||
.sidenote:not([data-theme]),
|
||
.marginnote:not([data-theme]) {
|
||
color: #aaa !important;
|
||
background-color: #151515 !important;
|
||
}
|
||
}
|
||
|
||
.sidenote-number,
|
||
.margin-toggle {
|
||
display: inline;
|
||
}
|
||
|
||
/* Stack plan stats vertically */
|
||
.plan-stats {
|
||
flex-direction: column;
|
||
gap: 1rem;
|
||
}
|
||
|
||
/* Optimize grids for mobile */
|
||
.book-grid,
|
||
.plan-grid,
|
||
.topic-grid {
|
||
grid-template-columns: 1fr !important;
|
||
gap: 1rem;
|
||
max-width: 100% !important;
|
||
}
|
||
|
||
/* Optimize verse lookup form */
|
||
.lookup-form {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.lookup-input,
|
||
.lookup-btn {
|
||
width: 100%;
|
||
}
|
||
|
||
/* Optimize share buttons */
|
||
.share-buttons {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.share-btn {
|
||
width: 100%;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* Optimize breadcrumbs with strong contrast */
|
||
.breadcrumb {
|
||
font-size: 0.95rem;
|
||
flex-wrap: wrap;
|
||
border-bottom: 3px solid #999;
|
||
padding-bottom: 0.75rem;
|
||
}
|
||
|
||
[data-theme="dark"] .breadcrumb {
|
||
border-bottom-color: #666;
|
||
}
|
||
|
||
.breadcrumb a {
|
||
font-weight: 600;
|
||
border-bottom: 2px solid #999;
|
||
color: #000;
|
||
}
|
||
|
||
[data-theme="dark"] .breadcrumb a {
|
||
border-bottom-color: #666;
|
||
color: #e0e0e0;
|
||
}
|
||
|
||
/* Improve button visibility on mobile with strong contrast */
|
||
button, .btn, input[type="submit"] {
|
||
min-height: 44px;
|
||
min-width: 44px;
|
||
padding: 0.75rem 1.25rem;
|
||
font-size: 1rem;
|
||
font-weight: 700;
|
||
border: 3px solid #111;
|
||
background: #111;
|
||
color: #fff;
|
||
cursor: pointer;
|
||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
[data-theme="dark"] button,
|
||
[data-theme="dark"] .btn,
|
||
[data-theme="dark"] input[type="submit"] {
|
||
border-color: #ddd;
|
||
background: #ddd;
|
||
color: #111;
|
||
}
|
||
|
||
/* Improve section dividers with strong contrast */
|
||
/* Optimize verse text */
|
||
.verse-text {
|
||
font-size: 1.4rem;
|
||
line-height: 2rem;
|
||
}
|
||
|
||
/* Make tables responsive */
|
||
table {
|
||
display: block;
|
||
overflow-x: auto;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
/* Optimize epigraph */
|
||
.epigraph {
|
||
margin: 2rem 0;
|
||
}
|
||
|
||
.epigraph blockquote {
|
||
padding: 1rem;
|
||
font-size: 1.1rem;
|
||
}
|
||
}
|
||
|
||
/* Extra small screens (phones in portrait) */
|
||
@media (max-width: 480px) {
|
||
article {
|
||
width: 100%;
|
||
padding: 0.5rem;
|
||
transition: transform 0.3s ease;
|
||
}
|
||
|
||
#sidebar-toggle:checked ~ article {
|
||
transform: translateX(140px);
|
||
}
|
||
|
||
h1 {
|
||
font-size: 1.75rem;
|
||
}
|
||
|
||
h2 {
|
||
font-size: 1.3rem;
|
||
}
|
||
|
||
.verse-text {
|
||
font-size: 1.2rem;
|
||
line-height: 1.8rem;
|
||
}
|
||
|
||
.dark-mode-toggle,
|
||
.sidebar-toggle-container {
|
||
top: 0.5rem;
|
||
}
|
||
|
||
.dark-mode-toggle {
|
||
right: 0.5rem;
|
||
}
|
||
|
||
#sidebar-toggle:checked ~ .dark-mode-toggle {
|
||
transform: translateX(140px);
|
||
}
|
||
}
|
||
|
||
/* Print styles for beautiful printed pages */
|
||
@media print {
|
||
/* Use light colors for print */
|
||
:root {
|
||
--bg-color: white;
|
||
--text-color: black;
|
||
--text-secondary: #333;
|
||
--border-color: #ccc;
|
||
}
|
||
|
||
body {
|
||
background: white;
|
||
color: black;
|
||
font-size: 12pt;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
/* Hide navigation elements */
|
||
.nav-sidebar,
|
||
.sidebar-toggle-container,
|
||
.dark-mode-toggle,
|
||
.breadcrumb {
|
||
display: none !important;
|
||
}
|
||
|
||
/* Expand article to full width */
|
||
article {
|
||
width: 100% !important;
|
||
max-width: 100% !important;
|
||
padding: 0;
|
||
margin: 0;
|
||
}
|
||
|
||
/* Optimize typography for print */
|
||
h1 {
|
||
font-size: 24pt;
|
||
margin-top: 0;
|
||
page-break-after: avoid;
|
||
}
|
||
|
||
h2 {
|
||
font-size: 18pt;
|
||
page-break-after: avoid;
|
||
}
|
||
|
||
h3 {
|
||
font-size: 14pt;
|
||
page-break-after: avoid;
|
||
}
|
||
|
||
p {
|
||
font-size: 12pt;
|
||
orphans: 3;
|
||
widows: 3;
|
||
}
|
||
|
||
/* Avoid breaking inside elements */
|
||
section,
|
||
.verse-item,
|
||
.angel-entry,
|
||
.prophet-entry,
|
||
.name-entry,
|
||
.parable-entry,
|
||
.covenant-entry,
|
||
.apostle-entry,
|
||
.woman-entry,
|
||
.festival-entry {
|
||
page-break-inside: avoid;
|
||
}
|
||
|
||
/* Make sidenotes visible in print */
|
||
.sidenote,
|
||
.marginnote {
|
||
display: block !important;
|
||
float: none !important;
|
||
width: 100% !important;
|
||
margin: 0.5rem 0 0.5rem 2rem !important;
|
||
padding: 0.5rem;
|
||
border-left: 2px solid #ccc;
|
||
font-size: 10pt;
|
||
color: #333;
|
||
}
|
||
|
||
/* Hide sidenote toggles */
|
||
.margin-toggle {
|
||
display: none !important;
|
||
}
|
||
|
||
/* Show URLs for links */
|
||
a[href^="http"]:after {
|
||
content: " (" attr(href) ")";
|
||
font-size: 10pt;
|
||
color: #666;
|
||
}
|
||
|
||
/* Don't show URLs for internal links */
|
||
a[href^="/"]:after {
|
||
content: "";
|
||
}
|
||
|
||
/* Optimize verse display */
|
||
.verse-item {
|
||
margin: 0.5rem 0;
|
||
padding-left: 1rem;
|
||
}
|
||
|
||
.verse-ref {
|
||
font-weight: bold;
|
||
}
|
||
|
||
.verse-text {
|
||
max-width: 100%;
|
||
}
|
||
|
||
/* Remove link underlines for cleaner print */
|
||
a {
|
||
color: black;
|
||
text-decoration: none;
|
||
border-bottom: none;
|
||
}
|
||
|
||
/* Page breaks */
|
||
h1, h2 {
|
||
page-break-before: auto;
|
||
}
|
||
|
||
/* Add chapter/verse numbers in margin for reference */
|
||
@page {
|
||
margin: 2cm;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<input type="checkbox" id="sidebar-toggle" aria-hidden="true">
|
||
<p class="sidebar-toggle-container">
|
||
<label for="sidebar-toggle" class="sidebar-toggle-btn" title="Toggle sidebar" aria-label="Toggle navigation sidebar"></label>
|
||
</p>
|
||
<p class="dark-mode-toggle">
|
||
<button class="dark-mode-btn" title="Toggle dark mode" onclick="toggleDarkMode()" aria-label="Toggle dark mode"></button>
|
||
</p>
|
||
<article role="main">
|
||
{% if breadcrumbs %}
|
||
<nav class="breadcrumb" aria-label="Breadcrumb">
|
||
{% for crumb in breadcrumbs %}
|
||
{% if not loop.last %}
|
||
<a href="{{ crumb.url }}">{{ crumb.text }}</a>
|
||
<span class="breadcrumb-separator">></span>
|
||
{% else %}
|
||
<span>{{ crumb.text }}</span>
|
||
{% endif %}
|
||
{% endfor %}
|
||
</nav>
|
||
{% endif %}
|
||
|
||
{% block content %}{% endblock %}
|
||
</article>
|
||
|
||
<!-- Floating Navigation Sidebar -->
|
||
<nav class="nav-sidebar" role="navigation" aria-label="Primary navigation">
|
||
<!-- Universal Search Box -->
|
||
<div class="sidebar-search" role="search">
|
||
<input type="text" id="sidebar-search-input" placeholder="Search everything..." autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" aria-label="Search Bible, topics, and resources">
|
||
<div id="search-results-dropdown" class="search-results-dropdown" role="listbox" aria-live="polite"></div>
|
||
</div>
|
||
|
||
<!-- Quick Access -->
|
||
<h3>Quick Access</h3>
|
||
<ul>
|
||
<li><a href="/" {% if request.url.path == "/" %}class="current"{% endif %}>Home</a></li>
|
||
<li><a href="/books" {% if request.url.path == "/books" %}class="current"{% endif %}>Books</a></li>
|
||
<li><a href="/search">Search</a></li>
|
||
</ul>
|
||
|
||
<!-- Bible Books -->
|
||
{% if books %}
|
||
<h3>Bible Books</h3>
|
||
<details id="old-testament" aria-label="Old Testament books">
|
||
<summary aria-expanded="false">Old Testament</summary>
|
||
<ul class="book-list">
|
||
{% set book_types = {'Genesis': 'law', 'Exodus': 'law', 'Leviticus': 'law', 'Numbers': 'law', 'Deuteronomy': 'law', 'Joshua': 'historical', 'Judges': 'historical', 'Ruth': 'historical', '1 Samuel': 'historical', '2 Samuel': 'historical', '1 Kings': 'historical', '2 Kings': 'historical', '1 Chronicles': 'historical', '2 Chronicles': 'historical', 'Ezra': 'historical', 'Nehemiah': 'historical', 'Esther': 'historical', 'Job': 'wisdom', 'Psalms': 'wisdom', 'Proverbs': 'wisdom', 'Ecclesiastes': 'wisdom', 'Song of Solomon': 'wisdom', 'Isaiah': 'major-prophets', 'Jeremiah': 'major-prophets', 'Lamentations': 'major-prophets', 'Ezekiel': 'major-prophets', 'Daniel': 'major-prophets', 'Hosea': 'minor-prophets', 'Joel': 'minor-prophets', 'Amos': 'minor-prophets', 'Obadiah': 'minor-prophets', 'Jonah': 'minor-prophets', 'Micah': 'minor-prophets', 'Nahum': 'minor-prophets', 'Habakkuk': 'minor-prophets', 'Zephaniah': 'minor-prophets', 'Haggai': 'minor-prophets', 'Zechariah': 'minor-prophets', 'Malachi': 'minor-prophets'} %}
|
||
{% for book in ['Genesis', 'Exodus', 'Leviticus', 'Numbers', 'Deuteronomy', 'Joshua', 'Judges', 'Ruth', '1 Samuel', '2 Samuel', '1 Kings', '2 Kings', '1 Chronicles', '2 Chronicles', 'Ezra', 'Nehemiah', 'Esther', 'Job', 'Psalms', 'Proverbs', 'Ecclesiastes', 'Song of Solomon', 'Isaiah', 'Jeremiah', 'Lamentations', 'Ezekiel', 'Daniel', 'Hosea', 'Joel', 'Amos', 'Obadiah', 'Jonah', 'Micah', 'Nahum', 'Habakkuk', 'Zephaniah', 'Haggai', 'Zechariah', 'Malachi'] %}
|
||
{% if book in books %}
|
||
<li><a href="/book/{{ book }}" class="{{ book_types[book] }}{% if current_book == book %} current{% endif %}">{{ book }}</a></li>
|
||
{% endif %}
|
||
{% endfor %}
|
||
</ul>
|
||
</details>
|
||
|
||
<details id="new-testament" aria-label="New Testament books">
|
||
<summary aria-expanded="false">New Testament</summary>
|
||
<ul class="book-list">
|
||
{% set nt_book_types = {'Matthew': 'gospels', 'Mark': 'gospels', 'Luke': 'gospels', 'John': 'gospels', 'Acts': 'acts', 'Romans': 'pauline', '1 Corinthians': 'pauline', '2 Corinthians': 'pauline', 'Galatians': 'pauline', 'Ephesians': 'pauline', 'Philippians': 'pauline', 'Colossians': 'pauline', '1 Thessalonians': 'pauline', '2 Thessalonians': 'pauline', '1 Timothy': 'pauline', '2 Timothy': 'pauline', 'Titus': 'pauline', 'Philemon': 'pauline', 'Hebrews': 'general', 'James': 'general', '1 Peter': 'general', '2 Peter': 'general', '1 John': 'general', '2 John': 'general', '3 John': 'general', 'Jude': 'general', 'Revelation': 'apocalyptic'} %}
|
||
{% for book in ['Matthew', 'Mark', 'Luke', 'John', 'Acts', 'Romans', '1 Corinthians', '2 Corinthians', 'Galatians', 'Ephesians', 'Philippians', 'Colossians', '1 Thessalonians', '2 Thessalonians', '1 Timothy', '2 Timothy', 'Titus', 'Philemon', 'Hebrews', 'James', '1 Peter', '2 Peter', '1 John', '2 John', '3 John', 'Jude', 'Revelation'] %}
|
||
{% if book in books %}
|
||
<li><a href="/book/{{ book }}" class="{{ nt_book_types[book] }}{% if current_book == book %} current{% endif %}">{{ book }}</a></li>
|
||
{% endif %}
|
||
{% endfor %}
|
||
</ul>
|
||
</details>
|
||
{% endif %}
|
||
|
||
<!-- Daily Reading -->
|
||
<details class="resource-group" open aria-label="Daily reading resources">
|
||
<summary aria-expanded="true">Daily Reading</summary>
|
||
<ul>
|
||
<li><a href="/verse-of-the-day">Verse of the Day</a></li>
|
||
<li><a href="/random-verse">Random Verse</a></li>
|
||
<li><a href="/reading-plans">Reading Plans</a></li>
|
||
</ul>
|
||
</details>
|
||
|
||
<!-- Study Resources -->
|
||
<details class="resource-group" open aria-label="Study resources">
|
||
<summary aria-expanded="true">Study Resources</summary>
|
||
<ul>
|
||
<li><a href="/study-guides">Study Guides</a></li>
|
||
<li><a href="/stories">Bible Stories</a></li>
|
||
<li><a href="/topics">Topics</a></li>
|
||
<li><a href="/resources">Resources</a></li>
|
||
</ul>
|
||
</details>
|
||
|
||
<!-- Reference Tools -->
|
||
<details class="resource-group" open aria-label="Reference tools">
|
||
<summary aria-expanded="true">Reference Tools</summary>
|
||
<ul>
|
||
<li><a href="/concordance">Concordance</a></li>
|
||
<li><a href="/interlinear">Interlinear</a></li>
|
||
</ul>
|
||
</details>
|
||
|
||
<!-- Source Code -->
|
||
<div style="margin-top: 2rem; padding-top: 1rem; border-top: 1px solid var(--border-color);">
|
||
<p style="font-size: 0.85rem; color: var(--text-tertiary); text-align: center;">
|
||
<a href="https://github.com/kennethreitz/kjvstudy.org" target="_blank" rel="noopener" style="color: var(--text-tertiary); text-decoration: none; border-bottom: 1px dotted var(--border-color-dark);">View Source Code</a>
|
||
</p>
|
||
</div>
|
||
|
||
<!-- Flourish -->
|
||
<div class="sidebar-flourish">⁂</div>
|
||
</nav>
|
||
|
||
<script type="text/javascript">
|
||
// Dark mode functionality
|
||
(function() {
|
||
// Check for saved theme preference or default to light mode
|
||
const currentTheme = localStorage.getItem('theme') || 'light';
|
||
document.documentElement.setAttribute('data-theme', currentTheme);
|
||
})();
|
||
|
||
function toggleDarkMode() {
|
||
const currentTheme = document.documentElement.getAttribute('data-theme');
|
||
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
||
document.documentElement.setAttribute('data-theme', newTheme);
|
||
localStorage.setItem('theme', newTheme);
|
||
}
|
||
|
||
// Sidebar collapse state persistence
|
||
(function() {
|
||
var toggle = document.getElementById('sidebar-toggle');
|
||
var expanded = localStorage.getItem('sidebarExpanded') === 'true';
|
||
if (expanded) {
|
||
toggle.checked = true;
|
||
}
|
||
toggle.addEventListener('change', function() {
|
||
localStorage.setItem('sidebarExpanded', toggle.checked);
|
||
});
|
||
})();
|
||
|
||
// Details elements (subsections) collapse state persistence
|
||
(function() {
|
||
// Get all details elements in sidebar
|
||
var detailsElements = document.querySelectorAll('.nav-sidebar details');
|
||
|
||
// Restore saved states
|
||
detailsElements.forEach(function(details) {
|
||
var id = details.id || details.querySelector('summary')?.textContent.trim();
|
||
if (id) {
|
||
var savedState = localStorage.getItem('sidebar-details-' + id);
|
||
if (savedState === 'open') {
|
||
details.open = true;
|
||
} else if (savedState === 'closed') {
|
||
details.open = false;
|
||
}
|
||
}
|
||
});
|
||
|
||
// Save state on toggle
|
||
detailsElements.forEach(function(details) {
|
||
details.addEventListener('toggle', function() {
|
||
var id = this.id || this.querySelector('summary')?.textContent.trim();
|
||
if (id) {
|
||
localStorage.setItem('sidebar-details-' + id, this.open ? 'open' : 'closed');
|
||
}
|
||
});
|
||
});
|
||
})();
|
||
|
||
// Universal search functionality with smart verse navigation
|
||
(function() {
|
||
var searchInput = document.getElementById('sidebar-search-input');
|
||
var dropdown = document.getElementById('search-results-dropdown');
|
||
if (!searchInput || !dropdown) return;
|
||
|
||
var searchTimeout = null;
|
||
var selectedIndex = -1;
|
||
var currentResults = [];
|
||
|
||
// Book name mapping (same as homepage)
|
||
var bookMap = {
|
||
'genesis': 'Genesis', 'exodus': 'Exodus', 'leviticus': 'Leviticus', 'numbers': 'Numbers',
|
||
'deuteronomy': 'Deuteronomy', 'joshua': 'Joshua', 'judges': 'Judges', 'ruth': 'Ruth',
|
||
'1 samuel': '1 Samuel', '2 samuel': '2 Samuel', '1 kings': '1 Kings', '2 kings': '2 Kings',
|
||
'1 chronicles': '1 Chronicles', '2 chronicles': '2 Chronicles', 'ezra': 'Ezra', 'nehemiah': 'Nehemiah',
|
||
'esther': 'Esther', 'job': 'Job', 'psalms': 'Psalms', 'psalm': 'Psalms', 'proverbs': 'Proverbs',
|
||
'ecclesiastes': 'Ecclesiastes', 'song of solomon': 'Song of Solomon', 'isaiah': 'Isaiah',
|
||
'jeremiah': 'Jeremiah', 'lamentations': 'Lamentations', 'ezekiel': 'Ezekiel', 'daniel': 'Daniel',
|
||
'hosea': 'Hosea', 'joel': 'Joel', 'amos': 'Amos', 'obadiah': 'Obadiah', 'jonah': 'Jonah',
|
||
'micah': 'Micah', 'nahum': 'Nahum', 'habakkuk': 'Habakkuk', 'zephaniah': 'Zephaniah',
|
||
'haggai': 'Haggai', 'zechariah': 'Zechariah', 'malachi': 'Malachi', 'matthew': 'Matthew',
|
||
'mark': 'Mark', 'luke': 'Luke', 'john': 'John', 'acts': 'Acts', 'romans': 'Romans',
|
||
'1 corinthians': '1 Corinthians', '2 corinthians': '2 Corinthians', 'galatians': 'Galatians',
|
||
'ephesians': 'Ephesians', 'philippians': 'Philippians', 'colossians': 'Colossians',
|
||
'1 thessalonians': '1 Thessalonians', '2 thessalonians': '2 Thessalonians',
|
||
'1 timothy': '1 Timothy', '2 timothy': '2 Timothy', 'titus': 'Titus', 'philemon': 'Philemon',
|
||
'hebrews': 'Hebrews', 'james': 'James', '1 peter': '1 Peter', '2 peter': '2 Peter',
|
||
'1 john': '1 John', '2 john': '2 John', '3 john': '3 John', 'jude': 'Jude', 'revelation': 'Revelation',
|
||
'gen': 'Genesis', 'ex': 'Exodus', 'lev': 'Leviticus', 'num': 'Numbers', 'deut': 'Deuteronomy',
|
||
'josh': 'Joshua', 'judg': 'Judges', 'ru': 'Ruth', '1sam': '1 Samuel', '2sam': '2 Samuel',
|
||
'1ki': '1 Kings', '2ki': '2 Kings', '1chr': '1 Chronicles', '2chr': '2 Chronicles',
|
||
'neh': 'Nehemiah', 'est': 'Esther', 'ps': 'Psalms', 'prov': 'Proverbs', 'eccl': 'Ecclesiastes',
|
||
'isa': 'Isaiah', 'jer': 'Jeremiah', 'lam': 'Lamentations', 'ezek': 'Ezekiel', 'dan': 'Daniel',
|
||
'hos': 'Hosea', 'mic': 'Micah', 'hab': 'Habakkuk', 'zech': 'Zechariah', 'mal': 'Malachi',
|
||
'matt': 'Matthew', 'mk': 'Mark', 'lk': 'Luke', 'jn': 'John', 'rom': 'Romans',
|
||
'1cor': '1 Corinthians', '2cor': '2 Corinthians', 'gal': 'Galatians', 'eph': 'Ephesians',
|
||
'phil': 'Philippians', 'col': 'Colossians', '1thess': '1 Thessalonians', '2thess': '2 Thessalonians',
|
||
'1tim': '1 Timothy', '2tim': '2 Timothy', 'tit': 'Titus', 'heb': 'Hebrews', 'jas': 'James',
|
||
'1pet': '1 Peter', '2pet': '2 Peter', '1jn': '1 John', '2jn': '2 John', '3jn': '3 John', 'rev': 'Revelation'
|
||
};
|
||
|
||
function capitalizeBook(name) {
|
||
return bookMap[name.toLowerCase()] || name;
|
||
}
|
||
|
||
// Try to parse as verse reference and return URL, or null
|
||
function parseVerseReference(input) {
|
||
// Book Chapter:Verse
|
||
var match = input.match(/^(.+)\s+(\d+):(\d+)$/i);
|
||
if (match) {
|
||
var book = capitalizeBook(match[1].trim());
|
||
return '/book/' + encodeURIComponent(book) + '/chapter/' + match[2] + '/verse/' + match[3];
|
||
}
|
||
// Book Chapter
|
||
match = input.match(/^(.+)\s+(\d+)$/i);
|
||
if (match) {
|
||
var book = capitalizeBook(match[1].trim());
|
||
return '/book/' + encodeURIComponent(book) + '/chapter/' + match[2];
|
||
}
|
||
return null;
|
||
}
|
||
|
||
// Category labels
|
||
var categoryLabels = {
|
||
books: 'Books',
|
||
verses: 'Verses',
|
||
topics: 'Topics',
|
||
resources: 'Resources',
|
||
stories: 'Stories',
|
||
plans: 'Reading Plans'
|
||
};
|
||
|
||
// Render search results
|
||
function renderResults(data) {
|
||
var results = data.results;
|
||
var html = '';
|
||
currentResults = [];
|
||
|
||
// Check if query looks like a verse reference
|
||
var verseUrl = parseVerseReference(data.query);
|
||
if (verseUrl) {
|
||
html += '<div class="search-results-category">';
|
||
html += '<div class="search-results-category-title">Go to</div>';
|
||
currentResults.push(verseUrl);
|
||
html += '<a href="' + verseUrl + '" class="search-result-item selected">';
|
||
html += '<span class="result-title">' + data.query + '</span>';
|
||
html += '<span class="result-meta">Press Enter to navigate</span>';
|
||
html += '</a></div>';
|
||
selectedIndex = 0;
|
||
}
|
||
|
||
if (Object.keys(results).length === 0 && !verseUrl) {
|
||
html = '<div class="search-no-results">No results found</div>';
|
||
} else {
|
||
// Render categories in specific order: books, topics, resources, stories, plans, verses
|
||
var categoryOrder = ['books', 'topics', 'resources', 'stories', 'plans', 'verses'];
|
||
categoryOrder.forEach(function(category) {
|
||
if (results[category] && results[category].length > 0) {
|
||
html += '<div class="search-results-category">';
|
||
html += '<div class="search-results-category-title">' + (categoryLabels[category] || category) + '</div>';
|
||
|
||
results[category].forEach(function(item) {
|
||
var title = item.name || item.title || item.reference;
|
||
var meta = '';
|
||
if (item.text) meta = item.text;
|
||
else if (item.category) meta = item.category;
|
||
|
||
currentResults.push(item.url);
|
||
html += '<a href="' + item.url + '" class="search-result-item">';
|
||
html += '<span class="result-title">' + title + '</span>';
|
||
if (meta) html += '<span class="result-meta">' + meta + '</span>';
|
||
html += '</a>';
|
||
});
|
||
|
||
html += '</div>';
|
||
}
|
||
});
|
||
|
||
// Add "View all results" link
|
||
html += '<a href="/search?q=' + encodeURIComponent(data.query) + '" class="search-view-all">View all verse results →</a>';
|
||
}
|
||
|
||
dropdown.innerHTML = html;
|
||
dropdown.classList.add('show');
|
||
if (!verseUrl) selectedIndex = -1;
|
||
}
|
||
|
||
// Perform search
|
||
function doSearch(query) {
|
||
if (query.length < 2) {
|
||
dropdown.classList.remove('show');
|
||
return;
|
||
}
|
||
|
||
dropdown.innerHTML = '<div class="search-loading">Searching...</div>';
|
||
dropdown.classList.add('show');
|
||
|
||
fetch('/api/universal-search?q=' + encodeURIComponent(query) + '&limit=4')
|
||
.then(function(r) { return r.json(); })
|
||
.then(renderResults)
|
||
.catch(function() {
|
||
dropdown.innerHTML = '<div class="search-no-results">Search error</div>';
|
||
});
|
||
}
|
||
|
||
// Input handler with debounce
|
||
searchInput.addEventListener('input', function() {
|
||
var query = this.value.trim();
|
||
clearTimeout(searchTimeout);
|
||
|
||
if (query.length < 2) {
|
||
dropdown.classList.remove('show');
|
||
return;
|
||
}
|
||
|
||
searchTimeout = setTimeout(function() {
|
||
doSearch(query);
|
||
}, 150);
|
||
});
|
||
|
||
// Keyboard navigation
|
||
searchInput.addEventListener('keydown', function(e) {
|
||
var items = dropdown.querySelectorAll('.search-result-item');
|
||
|
||
if (e.key === 'ArrowDown') {
|
||
e.preventDefault();
|
||
selectedIndex = Math.min(selectedIndex + 1, items.length - 1);
|
||
updateSelection(items);
|
||
} else if (e.key === 'ArrowUp') {
|
||
e.preventDefault();
|
||
selectedIndex = Math.max(selectedIndex - 1, -1);
|
||
updateSelection(items);
|
||
} else if (e.key === 'Enter') {
|
||
e.preventDefault();
|
||
if (selectedIndex >= 0 && currentResults[selectedIndex]) {
|
||
window.location.href = currentResults[selectedIndex];
|
||
} else {
|
||
// Try verse reference first, then search
|
||
var verseUrl = parseVerseReference(this.value.trim());
|
||
if (verseUrl) {
|
||
window.location.href = verseUrl;
|
||
} else if (this.value.trim()) {
|
||
window.location.href = '/search?q=' + encodeURIComponent(this.value.trim());
|
||
}
|
||
}
|
||
} else if (e.key === 'Escape') {
|
||
dropdown.classList.remove('show');
|
||
this.blur();
|
||
}
|
||
});
|
||
|
||
function updateSelection(items) {
|
||
items.forEach(function(item, i) {
|
||
item.classList.toggle('selected', i === selectedIndex);
|
||
});
|
||
}
|
||
|
||
// Close dropdown when clicking outside
|
||
document.addEventListener('click', function(e) {
|
||
if (!e.target.closest('.sidebar-search')) {
|
||
dropdown.classList.remove('show');
|
||
}
|
||
});
|
||
|
||
// Reopen on focus if there's a query
|
||
searchInput.addEventListener('focus', function() {
|
||
if (this.value.trim().length >= 2) {
|
||
doSearch(this.value.trim());
|
||
}
|
||
});
|
||
})();
|
||
|
||
// Keyboard shortcuts
|
||
document.addEventListener('keydown', function(e) {
|
||
// Don't trigger if user is typing in an input field
|
||
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') {
|
||
// Allow Escape to clear focus
|
||
if (e.key === 'Escape') {
|
||
e.target.blur();
|
||
}
|
||
return;
|
||
}
|
||
|
||
// Cmd/Ctrl + D: Toggle dark mode
|
||
if ((e.metaKey || e.ctrlKey) && e.key === 'd') {
|
||
e.preventDefault();
|
||
toggleDarkMode();
|
||
}
|
||
|
||
// Cmd/Ctrl + B: Toggle sidebar
|
||
if ((e.metaKey || e.ctrlKey) && e.key === 'b') {
|
||
e.preventDefault();
|
||
var toggle = document.getElementById('sidebar-toggle');
|
||
if (toggle) {
|
||
toggle.checked = !toggle.checked;
|
||
toggle.dispatchEvent(new Event('change'));
|
||
}
|
||
}
|
||
|
||
// Cmd/Ctrl + K or /: Focus search
|
||
if (((e.metaKey || e.ctrlKey) && e.key === 'k') || e.key === '/') {
|
||
e.preventDefault();
|
||
window.location.href = '/search';
|
||
}
|
||
|
||
// g: Quick verse lookup
|
||
if (e.key === 'g') {
|
||
e.preventDefault();
|
||
showVerseLookup();
|
||
}
|
||
|
||
// r: Random verse
|
||
if (e.key === 'r') {
|
||
e.preventDefault();
|
||
window.location.href = '/random-verse';
|
||
}
|
||
|
||
// ?: Show keyboard shortcuts help
|
||
if (e.key === '?' && !e.shiftKey) {
|
||
showKeyboardHelp();
|
||
}
|
||
});
|
||
|
||
// Quick verse lookup
|
||
function showVerseLookup() {
|
||
var reference = prompt('Enter verse reference (e.g., John 3:16, Psalm 23, Genesis 1):');
|
||
if (!reference) return;
|
||
|
||
reference = reference.trim();
|
||
|
||
// Try to match: Book Chapter:Verse
|
||
var match = reference.match(/^(.+?)\s+(\d+):(\d+)$/i);
|
||
if (match) {
|
||
var book = match[1].trim();
|
||
var chapter = match[2];
|
||
var verse = match[3];
|
||
window.location.href = '/book/' + encodeURIComponent(book) + '/chapter/' + chapter + '/verse/' + verse;
|
||
return;
|
||
}
|
||
|
||
// Try to match: Book Chapter
|
||
match = reference.match(/^(.+?)\s+(\d+)$/i);
|
||
if (match) {
|
||
var book = match[1].trim();
|
||
var chapter = match[2];
|
||
window.location.href = '/book/' + encodeURIComponent(book) + '/chapter/' + chapter;
|
||
return;
|
||
}
|
||
|
||
// Try to match: Book
|
||
match = reference.match(/^(.+)$/i);
|
||
if (match) {
|
||
var book = match[1].trim();
|
||
window.location.href = '/book/' + encodeURIComponent(book);
|
||
return;
|
||
}
|
||
}
|
||
|
||
// Keyboard shortcuts help modal
|
||
function showKeyboardHelp() {
|
||
var helpText = 'Keyboard Shortcuts:\\n\\n' +
|
||
'g - Quick verse lookup\\n' +
|
||
'r - Random verse\\n' +
|
||
'Cmd/Ctrl + D - Toggle dark mode\\n' +
|
||
'Cmd/Ctrl + B - Toggle sidebar\\n' +
|
||
'Cmd/Ctrl + K - Go to search\\n' +
|
||
'/ - Go to search\\n' +
|
||
'? - Show this help\\n' +
|
||
'Esc - Clear focus';
|
||
alert(helpText);
|
||
}
|
||
|
||
// Verse tooltip functionality
|
||
(function() {
|
||
// Create tooltip element
|
||
var tooltip = document.createElement('div');
|
||
tooltip.className = 'verse-tooltip';
|
||
document.body.appendChild(tooltip);
|
||
|
||
// Cache for fetched verses
|
||
var verseCache = {};
|
||
|
||
// Parse verse URL to extract book, chapter, and verse
|
||
function parseVerseUrl(url) {
|
||
// Try to match single verse URL: /book/John/chapter/3/verse/16
|
||
var match = url.match(/\/book\/([^\/]+)\/chapter\/(\d+)\/verse\/(\d+)/);
|
||
if (match) {
|
||
return {
|
||
book: decodeURIComponent(match[1]),
|
||
chapter: match[2],
|
||
verse: match[3],
|
||
verseEnd: null,
|
||
cacheKey: match[1] + '_' + match[2] + '_' + match[3],
|
||
isRange: false
|
||
};
|
||
}
|
||
|
||
// Try to match verse range URL: /book/Proverbs/chapter/31#verse-26-28
|
||
match = url.match(/\/book\/([^\/]+)\/chapter\/(\d+)#verse-(\d+)-(\d+)/);
|
||
if (match) {
|
||
return {
|
||
book: decodeURIComponent(match[1]),
|
||
chapter: match[2],
|
||
verse: match[3],
|
||
verseEnd: match[4],
|
||
cacheKey: match[1] + '_' + match[2] + '_' + match[3] + '-' + match[4],
|
||
isRange: true
|
||
};
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
// Fetch verse text from server using API
|
||
async function fetchVerseText(book, chapter, verse, verseEnd, cacheKey) {
|
||
// Check cache first
|
||
if (verseCache[cacheKey]) {
|
||
return verseCache[cacheKey];
|
||
}
|
||
|
||
try {
|
||
var url;
|
||
|
||
if (verseEnd) {
|
||
// Use verse range API endpoint
|
||
url = '/api/verse-range/' + encodeURIComponent(book) + '/' + chapter + '/' + verse + '/' + verseEnd;
|
||
} else {
|
||
// Use single verse API endpoint
|
||
url = '/api/verse/' + encodeURIComponent(book) + '/' + chapter + '/' + verse;
|
||
}
|
||
|
||
var response = await fetch(url);
|
||
if (!response.ok) throw new Error('Failed to fetch verse');
|
||
|
||
var data = await response.json();
|
||
|
||
// Cache the result
|
||
verseCache[cacheKey] = {
|
||
reference: data.reference,
|
||
text: data.text
|
||
};
|
||
|
||
return verseCache[cacheKey];
|
||
} catch (error) {
|
||
console.error('Error fetching verse:', error);
|
||
return {
|
||
reference: verseEnd ? book + ' ' + chapter + ':' + verse + '-' + verseEnd : book + ' ' + chapter + ':' + verse,
|
||
text: 'Error loading verse'
|
||
};
|
||
}
|
||
}
|
||
|
||
// Show tooltip
|
||
function showTooltip(verseData, mouseX, mouseY) {
|
||
tooltip.innerHTML =
|
||
'<span class="verse-tooltip-reference">' + verseData.reference + '</span>' +
|
||
'<span class="verse-tooltip-text">' + verseData.text + '</span>';
|
||
|
||
// Position tooltip
|
||
var tooltipRect = tooltip.getBoundingClientRect();
|
||
var x = mouseX + 15;
|
||
var y = mouseY + 15;
|
||
|
||
// Adjust if tooltip goes off right edge
|
||
if (x + tooltipRect.width > window.innerWidth) {
|
||
x = mouseX - tooltipRect.width - 15;
|
||
}
|
||
|
||
// Adjust if tooltip goes off bottom edge
|
||
if (y + tooltipRect.height > window.innerHeight) {
|
||
y = mouseY - tooltipRect.height - 15;
|
||
}
|
||
|
||
tooltip.style.left = x + 'px';
|
||
tooltip.style.top = y + 'px';
|
||
tooltip.classList.add('show');
|
||
}
|
||
|
||
// Hide tooltip
|
||
function hideTooltip() {
|
||
tooltip.classList.remove('show');
|
||
}
|
||
|
||
// Event delegation for verse links
|
||
document.addEventListener('mouseover', function(e) {
|
||
var target = e.target;
|
||
|
||
// Check if target is a link or inside a link
|
||
if (target.tagName !== 'A') {
|
||
target = target.closest('a');
|
||
}
|
||
|
||
if (!target || !target.href) return;
|
||
|
||
// Skip if this is a cross-reference link (has its own tooltip system)
|
||
if (target.classList.contains('cross-ref-link')) return;
|
||
|
||
// Skip if this is a verse number link (the number at the start of each verse)
|
||
if (target.classList.contains('verse-number-link')) return;
|
||
|
||
// Skip links in search dropdowns
|
||
if (target.closest('.search-results-dropdown') || target.closest('.search-dropdown') ||
|
||
target.closest('.lookup-results-dropdown') || target.closest('.story-search-dropdown')) return;
|
||
|
||
var verseInfo = parseVerseUrl(target.pathname + target.hash);
|
||
if (!verseInfo) return;
|
||
|
||
// Show loading state
|
||
tooltip.innerHTML = '<span class="verse-tooltip-loading">Loading...</span>';
|
||
tooltip.style.left = (e.pageX + 15) + 'px';
|
||
tooltip.style.top = (e.pageY + 15) + 'px';
|
||
tooltip.classList.add('show');
|
||
|
||
// Fetch and display verse
|
||
fetchVerseText(verseInfo.book, verseInfo.chapter, verseInfo.verse, verseInfo.verseEnd, verseInfo.cacheKey)
|
||
.then(function(verseData) {
|
||
// Only show if still hovering
|
||
if (target.matches(':hover')) {
|
||
showTooltip(verseData, e.pageX, e.pageY);
|
||
}
|
||
});
|
||
|
||
// Track mouse movement for tooltip positioning
|
||
var mouseMoveHandler = function(e) {
|
||
if (tooltip.classList.contains('show')) {
|
||
var x = e.pageX + 15;
|
||
var y = e.pageY + 15;
|
||
tooltip.style.left = x + 'px';
|
||
tooltip.style.top = y + 'px';
|
||
}
|
||
};
|
||
|
||
target.addEventListener('mousemove', mouseMoveHandler);
|
||
|
||
// Hide tooltip on mouse leave
|
||
target.addEventListener('mouseleave', function() {
|
||
hideTooltip();
|
||
target.removeEventListener('mousemove', mouseMoveHandler);
|
||
}, { once: true });
|
||
});
|
||
})();
|
||
|
||
// Site-wide verse linking
|
||
(function() {
|
||
function linkVerseReferences(element) {
|
||
if (!element) return;
|
||
|
||
// Get all text nodes
|
||
const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null, false);
|
||
const textNodes = [];
|
||
let node;
|
||
while (node = walker.nextNode()) {
|
||
textNodes.push(node);
|
||
}
|
||
|
||
textNodes.forEach(function(textNode) {
|
||
let text = textNode.textContent;
|
||
let changed = false;
|
||
|
||
// First, handle comma-separated verse lists like "Psalms 7:17, 9:2, 18:13"
|
||
text = text.replace(/\b(\d?\s?[A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)\s+((?:\d+:\d+(?:-\d+)?(?:\s*,\s*)?)+)/g, function(match, book, verseList) {
|
||
book = book.trim();
|
||
|
||
if (!verseList.includes(',')) {
|
||
return match;
|
||
}
|
||
|
||
changed = true;
|
||
|
||
var verses = verseList.split(/\s*,\s*/);
|
||
var links = verses.map(function(verseRef) {
|
||
verseRef = verseRef.trim();
|
||
var parts = verseRef.match(/^(\d+):(\d+)(?:-(\d+))?$/);
|
||
if (parts) {
|
||
var chapter = parts[1];
|
||
var verseStart = parts[2];
|
||
var verseEnd = parts[3];
|
||
|
||
if (verseEnd) {
|
||
return '<a href="/book/' + book + '/chapter/' + chapter + '#verse-' + verseStart + '-' + verseEnd + '">' + book + ' ' + chapter + ':' + verseStart + '-' + verseEnd + '</a>';
|
||
} else {
|
||
return '<a href="/book/' + book + '/chapter/' + chapter + '/verse/' + verseStart + '">' + book + ' ' + chapter + ':' + verseStart + '</a>';
|
||
}
|
||
}
|
||
return verseRef;
|
||
});
|
||
|
||
return links.join(', ');
|
||
});
|
||
|
||
// Then handle individual verse references like "John 3:16" or "Romans 8:28-29"
|
||
text = text.replace(/\b(\d?\s?[A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)\s+(\d+):(\d+)(?:-(\d+))?\b/g, function(match, book, chapter, verseStart, verseEnd) {
|
||
changed = true;
|
||
book = book.trim();
|
||
if (verseEnd) {
|
||
return '<a href="/book/' + book + '/chapter/' + chapter + '#verse-' + verseStart + '-' + verseEnd + '">' + match + '</a>';
|
||
} else {
|
||
return '<a href="/book/' + book + '/chapter/' + chapter + '/verse/' + verseStart + '">' + match + '</a>';
|
||
}
|
||
});
|
||
|
||
if (changed) {
|
||
const span = document.createElement('span');
|
||
span.innerHTML = text;
|
||
textNode.parentNode.replaceChild(span, textNode);
|
||
while (span.firstChild) {
|
||
span.parentNode.insertBefore(span.firstChild, span);
|
||
}
|
||
span.parentNode.removeChild(span);
|
||
}
|
||
});
|
||
}
|
||
|
||
// Link verses in common content areas
|
||
document.querySelectorAll('.intro-text, .prophet-description, .angel-description, .covenant-description, p').forEach(function(element) {
|
||
// Skip if already processed or if it's in the sidebar
|
||
if (element.closest('.nav-sidebar') || element.dataset.verseLinked) {
|
||
return;
|
||
}
|
||
element.dataset.verseLinked = 'true';
|
||
linkVerseReferences(element);
|
||
});
|
||
})();
|
||
|
||
// Gauges analytics
|
||
var _gauges = _gauges || [];
|
||
(function() {
|
||
var t = document.createElement('script');
|
||
t.type = 'text/javascript';
|
||
t.async = true;
|
||
t.id = 'gauges-tracker';
|
||
t.setAttribute('data-site-id', '6834bd650d851064ae28dc13');
|
||
t.setAttribute('data-track-path', 'https://track.gaug.es/track.gif');
|
||
t.src = 'https://d2fuc4clr7gvcn.cloudfront.net/track.js';
|
||
var s = document.getElementsByTagName('script')[0];
|
||
s.parentNode.insertBefore(t, s);
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|