diff --git a/kjvstudy_org/templates/family_tree_interactive.html b/kjvstudy_org/templates/family_tree_interactive.html index e499de4..775c7f1 100644 --- a/kjvstudy_org/templates/family_tree_interactive.html +++ b/kjvstudy_org/templates/family_tree_interactive.html @@ -99,14 +99,14 @@ /* Tree container */ .tree-container { - max-width: 55%; + max-width: 80%; margin: 2rem 0; } /* Tree nodes */ .tree-node { - margin: 0.5rem 0 0.5rem 1.5rem; - border-left: 2px solid #ddd; + margin: 1rem 0 1rem 2rem; + border-left: 2px solid #ccc; padding-left: 1rem; } @@ -117,16 +117,9 @@ } .tree-node.selected { - background: rgba(74, 124, 89, 0.1); - margin-left: calc(1.5rem - 4px); - padding-left: calc(1rem + 2px); - border-left: 4px solid #4a7c59; -} - -.tree-node-root.selected { - margin-left: -4px; - padding-left: 6px; - border-left: 4px solid #4a7c59; + background: rgba(74, 124, 89, 0.08); + outline: 2px solid #4a7c59; + outline-offset: 4px; } .tree-node.kekule { @@ -134,38 +127,14 @@ } .tree-node.kekule.selected { - border-left-color: #d4af37; - background: rgba(212, 175, 55, 0.1); -} - -.person-row { - display: flex; - align-items: baseline; - gap: 0.5rem; - padding: 0.25rem 0; -} - -.expand-toggle { - font-family: monospace; - font-size: 1rem; - width: 1.2rem; - color: #666; - cursor: pointer; - user-select: none; - flex-shrink: 0; -} - -.expand-toggle:hover { - color: #4a7c59; -} - -.expand-toggle.empty { - visibility: hidden; + background: rgba(212, 175, 55, 0.08); + outline-color: #d4af37; } .person-name { font-size: 1.1rem; font-weight: 600; + margin-bottom: 0.25rem; } .person-name a { @@ -177,38 +146,17 @@ text-decoration: underline; } -.person-meta { - font-size: 0.9rem; - color: #666; -} - -.person-spouse { +.person-name .expand-toggle { + font-family: monospace; font-size: 0.9rem; color: #888; - font-style: italic; + cursor: pointer; + user-select: none; + margin-left: 0.5rem; } -.person-spouse a { - color: #888; - text-decoration: none; -} - -.person-spouse a:hover { - text-decoration: underline; -} - -.person-verse { - font-size: 0.85rem; - color: #888; -} - -.person-verse a { - color: var(--link-color); - text-decoration: none; -} - -.person-verse a:hover { - text-decoration: underline; +.person-name .expand-toggle:hover { + color: #4a7c59; } .kekule-badge { @@ -221,6 +169,30 @@ margin-left: 0.5rem; } +.person-meta { + font-size: 0.95rem; + color: #666; + margin-bottom: 0.25rem; +} + +.person-details { + font-size: 0.9rem; + color: #888; +} + +.person-details a { + color: #888; + text-decoration: none; +} + +.person-details a:hover { + text-decoration: underline; +} + +.person-verse a { + color: var(--link-color); +} + .children-container { display: block; } @@ -418,50 +390,43 @@ function buildTreeHTML(personId, depth = 0, visited = new Set(), isRoot = false) let html = `
`; - // Person row - html += '
'; - - // Expand toggle - if (hasChildren) { - html += `${isCollapsed ? '▶' : '▼'}`; - } else { - html += '·'; - } - - // Name - html += `${person.name}`; - - // Kekulé badge + // Name line with expand toggle showing child count + html += '
'; + html += `${person.name}`; if (hasKekule) { html += `#${person.kekule_number}`; } + if (hasChildren) { + html += `${isCollapsed ? '+' : '−'}`; + } + html += '
'; - // Meta info - let meta = []; - if (person.generation) meta.push(`Gen ${person.generation}`); + // Generation line + if (person.generation) { + html += `
Generation ${person.generation} from Adam
`; + } + + // Details line (lifespan, children, spouse, verse) + let details = []; // Extract lifespan from death_year if it contains "Lived X years" const lifespanMatch = person.death_year && person.death_year.match(/Lived (\d+) years/); if (lifespanMatch) { - meta.push(`${lifespanMatch[1]} yrs`); + details.push(`Lived ${lifespanMatch[1]} years`); } // Number of children if (children.length > 0) { - meta.push(`${children.length} child${children.length > 1 ? 'ren' : ''}`); + details.push(`${children.length} ${children.length > 1 ? 'children' : 'child'}`); } - if (meta.length > 0) { - html += `(${meta.join(', ')})`; - } - - // Spouse (try to link if they exist in data) + // Spouse if (person.spouse) { const spouseId = findPersonId(person.spouse); if (spouseId) { - html += `${person.spouse}`; + details.push(`∞ ${person.spouse}`); } else { - html += `∞ ${person.spouse}`; + details.push(`∞ ${person.spouse}`); } } @@ -474,11 +439,13 @@ function buildTreeHTML(personId, depth = 0, visited = new Set(), isRoot = false) const chapter = refMatch[2]; const verseNum = refMatch[3]; const verseUrl = `/book/${encodeURIComponent(book)}/chapter/${chapter}#verse-${verseNum}`; - html += `${verse.reference}`; + details.push(`${verse.reference}`); } } - html += '
'; + if (details.length > 0) { + html += `
${details.join(' · ')}
`; + } // Children if (hasChildren) { @@ -509,46 +476,44 @@ function buildAncestorsHTML(personId, depth = 0, visited = new Set(), isRoot = f let html = `
`; - html += '
'; - - if (hasParents) { - html += `${isCollapsed ? '▶' : '▼'}`; - } else { - html += '·'; - } - - html += `${person.name}`; - + // Name line with expand toggle showing parent count + html += '
'; + html += `${person.name}`; if (hasKekule) { html += `#${person.kekule_number}`; } + if (hasParents) { + html += `${isCollapsed ? '+' : '−'}`; + } + html += '
'; - let meta = []; - if (person.generation) meta.push(`Gen ${person.generation}`); + // Generation line + if (person.generation) { + html += `
Generation ${person.generation} from Adam
`; + } + + // Details line (lifespan, children count, spouse, verse) + let details = []; // Extract lifespan from death_year if it contains "Lived X years" const lifespanMatch = person.death_year && person.death_year.match(/Lived (\d+) years/); if (lifespanMatch) { - meta.push(`${lifespanMatch[1]} yrs`); + details.push(`Lived ${lifespanMatch[1]} years`); } - // Number of children (for ancestors view, show children count) + // Number of children const children = person.children || []; if (children.length > 0) { - meta.push(`${children.length} child${children.length > 1 ? 'ren' : ''}`); + details.push(`${children.length} ${children.length > 1 ? 'children' : 'child'}`); } - if (meta.length > 0) { - html += `(${meta.join(', ')})`; - } - - // Spouse (try to link if they exist in data) + // Spouse if (person.spouse) { const spouseId = findPersonId(person.spouse); if (spouseId) { - html += `${person.spouse}`; + details.push(`∞ ${person.spouse}`); } else { - html += `∞ ${person.spouse}`; + details.push(`∞ ${person.spouse}`); } } @@ -561,11 +526,13 @@ function buildAncestorsHTML(personId, depth = 0, visited = new Set(), isRoot = f const chapter = refMatch[2]; const verseNum = refMatch[3]; const verseUrl = `/book/${encodeURIComponent(book)}/chapter/${chapter}#verse-${verseNum}`; - html += `${verse.reference}`; + details.push(`${verse.reference}`); } } - html += '
'; + if (details.length > 0) { + html += `
${details.join(' · ')}
`; + } if (hasParents) { html += `
`; @@ -650,7 +617,7 @@ function toggleNode(personId) { // Update the UI if (toggle && children) { const shouldCollapse = !isCurrentlyCollapsed; - toggle.textContent = shouldCollapse ? '▶' : '▼'; + toggle.textContent = shouldCollapse ? '+' : '−'; children.classList.toggle('collapsed', shouldCollapse); }