Last active
April 2, 2026 06:01
-
-
Save PandaWhoCodes/f5348ecd84f686f9dad84675cefd2fa0 to your computer and use it in GitHub Desktop.
Why Did Jesus Come? — A Topical Analysis of the Four Gospels (29 direct statements from KJV)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Why Did Jesus Come? — A Topical Analysis of the Four Gospels</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Crimson+Pro:ital,wght@0,300;0,400;0,500;0,600;1,300;1,400&family=Overpass+Mono:wght@300;400;500&family=Nunito+Sans:wght@300;400;600&display=swap" rel="stylesheet"> | |
| <style> | |
| * { margin: 0; padding: 0; box-sizing: border-box; } | |
| :root { | |
| --bg: #f7f4ef; | |
| --bg-card: #ffffff; | |
| --bg-verse: #faf8f3; | |
| --text: #2c2a26; | |
| --text-soft: #5c5850; | |
| --text-dim: #9c978d; | |
| --accent: #c0392b; | |
| --accent-gold: #c9a96e; | |
| --accent-dim: rgba(192, 57, 43, 0.08); | |
| --accent-gold-dim: rgba(201, 169, 110, 0.12); | |
| --serif: 'Crimson Pro', Georgia, serif; | |
| --sans: 'Nunito Sans', -apple-system, sans-serif; | |
| --mono: 'Overpass Mono', monospace; | |
| --mt: #c0392b; | |
| --mk: #2980b9; | |
| --lk: #27ae60; | |
| --jn: #8e44ad; | |
| } | |
| body { | |
| background: var(--bg); | |
| color: var(--text); | |
| font-family: var(--serif); | |
| font-size: 20px; | |
| line-height: 1.85; | |
| min-height: 100vh; | |
| -webkit-font-smoothing: antialiased; | |
| } | |
| /* Parchment texture */ | |
| body::after { | |
| content: ''; | |
| position: fixed; | |
| inset: 0; | |
| background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.03'/%3E%3C/svg%3E"); | |
| pointer-events: none; | |
| z-index: 9999; | |
| } | |
| .page { | |
| max-width: 680px; | |
| margin: 0 auto; | |
| padding: 4rem 1.5rem 3rem; | |
| } | |
| /* Header */ | |
| .header { text-align: center; margin-bottom: 3.5rem; } | |
| .header .day { | |
| font-family: var(--mono); | |
| font-size: 0.58rem; | |
| letter-spacing: 0.22em; | |
| text-transform: uppercase; | |
| color: var(--accent); | |
| margin-bottom: 1.5rem; | |
| display: block; | |
| } | |
| .header h1 { | |
| font-family: var(--serif); | |
| font-size: clamp(2.2rem, 6vw, 3rem); | |
| font-weight: 300; | |
| color: var(--text); | |
| line-height: 1.15; | |
| letter-spacing: -0.02em; | |
| margin-bottom: 1rem; | |
| } | |
| .header .subtitle { | |
| font-family: var(--sans); | |
| font-size: 0.82rem; | |
| color: var(--text-dim); | |
| font-weight: 300; | |
| max-width: 460px; | |
| margin: 0 auto; | |
| line-height: 1.7; | |
| } | |
| /* Ribbon divider */ | |
| .ribbon { | |
| width: 2px; height: 60px; | |
| background: var(--accent); | |
| margin: 3rem auto; | |
| opacity: 0.3; | |
| position: relative; | |
| } | |
| .ribbon::after { | |
| content: ''; | |
| position: absolute; | |
| bottom: -8px; left: -4px; | |
| width: 10px; height: 10px; | |
| background: var(--accent); | |
| opacity: 0.5; | |
| border-radius: 50%; | |
| } | |
| .ribbon-gold { | |
| width: 2px; height: 40px; | |
| background: var(--accent-gold); | |
| margin: 2.5rem auto; | |
| opacity: 0.4; | |
| } | |
| .dot-break { | |
| text-align: center; | |
| color: var(--text-dim); | |
| font-size: 1.2rem; | |
| letter-spacing: 0.5em; | |
| margin: 2.5rem 0; | |
| } | |
| /* Prose */ | |
| .prose p { | |
| margin-bottom: 1.4rem; | |
| color: var(--text-soft); | |
| } | |
| .prose p.lead::first-letter { | |
| font-size: 3.5rem; | |
| float: left; | |
| line-height: 0.8; | |
| padding-right: 0.12em; | |
| padding-top: 0.08em; | |
| color: var(--accent); | |
| font-weight: 600; | |
| } | |
| .prose em { font-style: italic; color: var(--text); } | |
| /* Stats strip */ | |
| .stats-strip { | |
| display: flex; | |
| justify-content: center; | |
| gap: 2.5rem; | |
| margin: 2rem 0; | |
| flex-wrap: wrap; | |
| } | |
| .stat { text-align: center; } | |
| .stat-num { | |
| font-family: var(--serif); | |
| font-size: 2.6rem; | |
| font-weight: 300; | |
| color: var(--accent); | |
| line-height: 1; | |
| } | |
| .stat-label { | |
| font-family: var(--mono); | |
| font-size: 0.5rem; | |
| letter-spacing: 0.15em; | |
| text-transform: uppercase; | |
| color: var(--text-dim); | |
| margin-top: 0.3rem; | |
| } | |
| /* Section headers */ | |
| .section-head { | |
| font-family: var(--serif); | |
| font-size: 1.7rem; | |
| font-weight: 300; | |
| color: var(--text); | |
| margin-bottom: 0.4rem; | |
| text-align: center; | |
| } | |
| .section-note { | |
| font-family: var(--sans); | |
| font-size: 0.78rem; | |
| color: var(--text-dim); | |
| text-align: center; | |
| margin-bottom: 2rem; | |
| } | |
| /* === CSS-ONLY CHARTS === */ | |
| /* Horizontal bar chart */ | |
| .bar-chart { margin: 2rem 0; } | |
| .bar-row { | |
| display: flex; | |
| align-items: center; | |
| margin-bottom: 0.6rem; | |
| gap: 0.8rem; | |
| } | |
| .bar-label { | |
| font-family: var(--sans); | |
| font-size: 0.7rem; | |
| color: var(--text-soft); | |
| width: 140px; | |
| text-align: right; | |
| flex-shrink: 0; | |
| } | |
| @media (max-width: 500px) { | |
| .bar-label { width: 100px; font-size: 0.62rem; } | |
| } | |
| .bar-track { | |
| flex: 1; | |
| height: 14px; | |
| background: rgba(0,0,0,0.03); | |
| border-radius: 2px; | |
| overflow: hidden; | |
| position: relative; | |
| } | |
| .bar-fill { | |
| height: 100%; | |
| border-radius: 2px; | |
| transition: width 1.5s cubic-bezier(0.25, 0.46, 0.45, 0.94); | |
| } | |
| .bar-value { | |
| font-family: var(--mono); | |
| font-size: 0.55rem; | |
| color: var(--text-dim); | |
| width: 24px; | |
| flex-shrink: 0; | |
| } | |
| /* Proportion strip (replaces doughnut) */ | |
| .proportion-strip { | |
| display: flex; | |
| height: 8px; | |
| border-radius: 4px; | |
| overflow: hidden; | |
| margin: 1.5rem 0 0.8rem; | |
| } | |
| .proportion-seg { | |
| transition: width 1.5s ease; | |
| } | |
| .proportion-legend { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 0.6rem 1.2rem; | |
| margin-bottom: 2rem; | |
| } | |
| .legend-item { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.4rem; | |
| font-family: var(--sans); | |
| font-size: 0.65rem; | |
| color: var(--text-dim); | |
| } | |
| .legend-dot { | |
| width: 8px; height: 8px; | |
| border-radius: 50%; | |
| flex-shrink: 0; | |
| } | |
| /* Gospel tiles */ | |
| .gospel-row { | |
| display: grid; | |
| grid-template-columns: repeat(4, 1fr); | |
| gap: 0.8rem; | |
| margin: 2rem 0; | |
| } | |
| @media (max-width: 560px) { | |
| .gospel-row { grid-template-columns: 1fr 1fr; } | |
| } | |
| .gospel-tile { | |
| text-align: center; | |
| padding: 1.3rem 0.8rem; | |
| background: var(--bg-card); | |
| border: 1px solid rgba(0,0,0,0.04); | |
| border-radius: 4px; | |
| border-top: 3px solid var(--accent-gold); | |
| } | |
| .gospel-tile.mt { border-top-color: var(--mt); } | |
| .gospel-tile.mk { border-top-color: var(--mk); } | |
| .gospel-tile.lk { border-top-color: var(--lk); } | |
| .gospel-tile.jn { border-top-color: var(--jn); } | |
| .gospel-tile h4 { | |
| font-family: var(--serif); | |
| font-size: 1.15rem; | |
| font-weight: 400; | |
| margin-bottom: 0.15rem; | |
| } | |
| .gospel-tile .count { | |
| font-family: var(--serif); | |
| font-size: 2rem; | |
| font-weight: 300; | |
| color: var(--accent); | |
| } | |
| .gospel-tile .count-label { | |
| font-family: var(--mono); | |
| font-size: 0.48rem; | |
| letter-spacing: 0.15em; | |
| text-transform: uppercase; | |
| color: var(--text-dim); | |
| } | |
| .gospel-tile .unique { | |
| font-family: var(--sans); | |
| font-size: 0.68rem; | |
| color: var(--text-dim); | |
| margin-top: 0.6rem; | |
| line-height: 1.5; | |
| font-style: italic; | |
| } | |
| /* Verse cards */ | |
| .verse-card { | |
| background: var(--bg-verse); | |
| border-left: 3px solid var(--accent-gold); | |
| padding: 1.1rem 1.4rem; | |
| margin: 1rem 0; | |
| font-size: 0.92rem; | |
| line-height: 1.7; | |
| color: var(--text-soft); | |
| border-radius: 0 4px 4px 0; | |
| } | |
| .verse-card .ref { | |
| display: block; | |
| font-family: var(--mono); | |
| font-size: 0.55rem; | |
| letter-spacing: 0.15em; | |
| text-transform: uppercase; | |
| color: var(--accent-gold); | |
| margin-top: 0.5rem; | |
| } | |
| /* Theme blocks */ | |
| .theme-block { margin-bottom: 3rem; } | |
| .theme-header { | |
| display: flex; | |
| align-items: baseline; | |
| gap: 0.8rem; | |
| margin-bottom: 0.2rem; | |
| flex-wrap: wrap; | |
| } | |
| .theme-number { | |
| font-family: var(--mono); | |
| font-size: 0.58rem; | |
| color: var(--accent); | |
| letter-spacing: 0.1em; | |
| opacity: 0.5; | |
| } | |
| .theme-title { | |
| font-family: var(--serif); | |
| font-size: 1.45rem; | |
| font-weight: 400; | |
| color: var(--text); | |
| } | |
| .theme-essence { | |
| font-family: var(--serif); | |
| font-size: 0.95rem; | |
| color: var(--text-soft); | |
| font-style: italic; | |
| margin-bottom: 0.8rem; | |
| } | |
| .theme-meta { | |
| display: flex; | |
| gap: 0.6rem; | |
| flex-wrap: wrap; | |
| margin-bottom: 0.8rem; | |
| } | |
| .meta-chip { | |
| font-family: var(--mono); | |
| font-size: 0.5rem; | |
| letter-spacing: 0.1em; | |
| text-transform: uppercase; | |
| color: var(--text-dim); | |
| background: var(--accent-gold-dim); | |
| padding: 0.2em 0.6em; | |
| border-radius: 3px; | |
| } | |
| .meta-chip.gospel { background: var(--accent-dim); color: var(--accent); } | |
| .evidence-track { | |
| height: 3px; | |
| background: rgba(0,0,0,0.04); | |
| border-radius: 2px; | |
| margin: 0.6rem 0; | |
| overflow: hidden; | |
| } | |
| .evidence-fill { | |
| height: 100%; | |
| background: linear-gradient(90deg, var(--accent-gold), var(--accent)); | |
| border-radius: 2px; | |
| } | |
| .tension-note { | |
| font-family: var(--sans); | |
| font-size: 0.75rem; | |
| color: var(--text-dim); | |
| background: var(--accent-dim); | |
| padding: 0.7rem 1rem; | |
| border-radius: 4px; | |
| margin-top: 0.8rem; | |
| line-height: 1.6; | |
| } | |
| .tension-note::before { content: '⚡ '; } | |
| /* Footer */ | |
| .footer { | |
| margin-top: 4rem; | |
| padding-top: 2rem; | |
| border-top: 1px solid rgba(0,0,0,0.06); | |
| text-align: center; | |
| } | |
| .footer p { | |
| font-family: var(--sans); | |
| font-size: 0.7rem; | |
| color: var(--text-dim); | |
| margin-bottom: 0.3rem; | |
| } | |
| /* Scroll fade-in */ | |
| .fade-in { | |
| opacity: 0; | |
| transform: translateY(16px); | |
| transition: opacity 0.7s ease, transform 0.7s ease; | |
| } | |
| .fade-in.visible { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="page"> | |
| <div class="header"> | |
| <span class="day">A Topical Analysis · April 2026</span> | |
| <h1>Why Did Jesus Come?</h1> | |
| <p class="subtitle">Twenty-nine direct statements from the four Gospels. Not what theologians say He came to do — what <em>He</em> said He came to do.</p> | |
| </div> | |
| <div class="ribbon"></div> | |
| <div class="prose"> | |
| <p class="lead">There are a lot of things we <em>think</em> Jesus came to do. Heal the sick. Perform miracles. Start a religion. But the Gospels record something more specific — moments where Jesus Himself says, in plain words, why He is here. "I am come to…" appears again and again across Matthew, Mark, Luke, and John.</p> | |
| <p>This analysis extracts only those direct statements — no inferred themes, no theological interpretation. Just His words. We fed the full KJV text of all four Gospels through Grok and asked a strict question: <em>find every passage where Jesus — or God, or an angel speaking on His behalf — directly states the purpose of His coming.</em></p> | |
| <p>The result: 29 statements. 26 spoken by Jesus Himself. Clustering into 8 distinct purposes.</p> | |
| </div> | |
| <div class="stats-strip fade-in"> | |
| <div class="stat"><div class="stat-num">29</div><div class="stat-label">Direct Statements</div></div> | |
| <div class="stat"><div class="stat-num">26</div><div class="stat-label">By Jesus Himself</div></div> | |
| <div class="stat"><div class="stat-num">8</div><div class="stat-label">Distinct Purposes</div></div> | |
| <div class="stat"><div class="stat-num">4/4</div><div class="stat-label">Gospels Agree on #1</div></div> | |
| </div> | |
| <div class="ribbon-gold"></div> | |
| <!-- CHARTS SECTION --> | |
| <h2 class="section-head fade-in">The Shape of His Mission</h2> | |
| <p class="section-note">How 29 statements distribute across purpose and Gospel</p> | |
| <!-- Bar chart: by purpose --> | |
| <div class="bar-chart fade-in" id="purpose-bars"></div> | |
| <div class="dot-break">· · ·</div> | |
| <!-- Proportion strip --> | |
| <p class="section-note">Share of all statements by purpose</p> | |
| <div class="proportion-strip fade-in" id="proportion-strip"></div> | |
| <div class="proportion-legend fade-in" id="proportion-legend"></div> | |
| <div class="ribbon-gold"></div> | |
| <!-- Gospel tiles --> | |
| <h2 class="section-head fade-in">Four Writers, One Person</h2> | |
| <p class="section-note">Each Gospel records different facets of the same mission</p> | |
| <div class="gospel-row fade-in"> | |
| <div class="gospel-tile mt"> | |
| <h4>Matthew</h4> | |
| <div class="count">7</div> | |
| <div class="count-label">Statements</div> | |
| <div class="unique">Fulfillment of law. Lost sheep of Israel.</div> | |
| </div> | |
| <div class="gospel-tile mk"> | |
| <h4>Mark</h4> | |
| <div class="count">3</div> | |
| <div class="count-label">Statements</div> | |
| <div class="unique">Servant who ransoms. Preacher who moves on.</div> | |
| </div> | |
| <div class="gospel-tile lk"> | |
| <h4>Luke</h4> | |
| <div class="count">7</div> | |
| <div class="count-label">Statements</div> | |
| <div class="unique">Fire on earth. Save, not destroy.</div> | |
| </div> | |
| <div class="gospel-tile jn"> | |
| <h4>John</h4> | |
| <div class="count">12</div> | |
| <div class="count-label">Statements</div> | |
| <div class="unique">Light. Life. The Father's will. Most "I came" statements.</div> | |
| </div> | |
| </div> | |
| <!-- Bar chart: by gospel --> | |
| <div class="bar-chart fade-in" id="gospel-bars"></div> | |
| <div class="ribbon"></div> | |
| <!-- THEMES SECTION --> | |
| <h2 class="section-head fade-in">The Eight Purposes</h2> | |
| <p class="section-note">Every direct "I came to…" statement, grouped by theme</p> | |
| <div id="themes-container"></div> | |
| <div class="footer"> | |
| <p>Source: King James Version — Matthew, Mark, Luke, John</p> | |
| <p>Topic extraction: Grok (xAI) · Strict "direct statements only" criteria</p> | |
| <p>Built by Claw 🐾 for Ashish · April 2026</p> | |
| </div> | |
| </div> | |
| <script> | |
| const themes = [ | |
| { theme:"To Save and Redeem", essence:"Jesus came to save humanity from sin and offer eternal life to believers.", weight:8, gospels:["Matthew","Mark","Luke","John"], color:"#c0392b", | |
| statements:[ | |
| {quote:"And she shall bring forth a son, and thou shalt call his name JESUS: for he shall save his people from their sins.",ref:"Matthew 1:21"}, | |
| {quote:"For the Son of man is come to save that which was lost.",ref:"Matthew 18:11"}, | |
| {quote:"For even the Son of man came not to be ministered unto, but to minister, and to give his life a ransom for many.",ref:"Mark 10:45"}, | |
| {quote:"For the Son of man is not come to destroy men\u2019s lives, but to save them.",ref:"Luke 9:56"}, | |
| {quote:"For unto you is born this day in the city of David a Saviour, which is Christ the Lord.",ref:"Luke 2:11"}, | |
| {quote:"For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish, but have everlasting life.",ref:"John 3:16"}, | |
| {quote:"For God sent not his Son into the world to condemn the world; but that the world through him might be saved.",ref:"John 3:17"}, | |
| {quote:"And if any man hear my words, and believe not, I judge him not: for I came not to judge the world, but to save the world.",ref:"John 12:47"} | |
| ]}, | |
| { theme:"To Bring Division and Judgment", essence:"Jesus came to bring division and spiritual judgment, challenging earthly peace and norms.", weight:5, gospels:["Matthew","Luke","John"], color:"#8e44ad", | |
| tension:"The mission of division and judgment contrasts sharply with the common expectation of a Messiah bringing universal peace.", | |
| statements:[ | |
| {quote:"Think not that I am come to send peace on earth: I came not to send peace, but a sword.",ref:"Matthew 10:34"}, | |
| {quote:"For I am come to set a man at variance against his father, and the daughter against her mother, and the daughter in law against her mother in law.",ref:"Matthew 10:35"}, | |
| {quote:"I am come to send fire on the earth; and what will I if it be already kindled?",ref:"Luke 12:49"}, | |
| {quote:"Suppose ye that I am come to give peace on earth? I tell you, Nay; but rather division.",ref:"Luke 12:51"}, | |
| {quote:"For judgment I am come into this world, that they which see not might see; and that they which see might be made blind.",ref:"John 9:39"} | |
| ]}, | |
| { theme:"To Call Sinners to Repentance", essence:"Jesus came to call sinners — not the righteous — focusing on those who know they need healing.", weight:3, gospels:["Matthew","Mark","Luke"], color:"#c9a96e", | |
| statements:[ | |
| {quote:"For I am not come to call the righteous, but sinners to repentance.",ref:"Matthew 9:13"}, | |
| {quote:"They that are whole have no need of the physician, but they that are sick: I came not to call the righteous, but sinners to repentance.",ref:"Mark 2:17"}, | |
| {quote:"I came not to call the righteous, but sinners to repentance.",ref:"Luke 5:32"} | |
| ]}, | |
| { theme:"To Preach and Proclaim", essence:"Jesus came to preach the gospel and proclaim the kingdom of God — and then move on to the next town.", weight:3, gospels:["Mark","Luke"], color:"#2980b9", | |
| statements:[ | |
| {quote:"Let us go into the next towns, that I may preach there also: for therefore came I forth.",ref:"Mark 1:38"}, | |
| {quote:"The Spirit of the Lord is upon me, because he hath anointed me to preach the gospel to the poor; he hath sent me to heal the brokenhearted, to preach deliverance to the captives, and recovering of sight to the blind, to set at liberty them that are bruised, To preach the acceptable year of the Lord.",ref:"Luke 4:18\u201319"}, | |
| {quote:"I must preach the kingdom of God to other cities also: for therefore am I sent.",ref:"Luke 4:43"} | |
| ]}, | |
| { theme:"To Fulfill God\u2019s Will and Law", essence:"Jesus came not to abolish but to fulfill — aligning every step with the Father\u2019s purpose.", weight:3, gospels:["Matthew","John"], color:"#27ae60", | |
| statements:[ | |
| {quote:"Think not that I am come to destroy the law, or the prophets: I am not come to destroy, but to fulfil.",ref:"Matthew 5:17"}, | |
| {quote:"My meat is to do the will of him that sent me, and to finish his work.",ref:"John 4:34"}, | |
| {quote:"For I came down from heaven, not to do mine own will, but the will of him that sent me.",ref:"John 6:38"} | |
| ]}, | |
| { theme:"To Represent and Reveal the Father", essence:"Jesus came in the Father\u2019s name, from the Father, to make God known.", weight:3, gospels:["John"], color:"#e67e22", | |
| statements:[ | |
| {quote:"I am come in my Father\u2019s name, and ye receive me not: if another shall come in his own name, him ye will receive.",ref:"John 5:43"}, | |
| {quote:"If God were your Father, ye would love me: for I proceeded forth and came from God; neither came I of myself, but he sent me.",ref:"John 8:42"}, | |
| {quote:"I came forth from the Father, and am come into the world: again, I leave the world, and go to the Father.",ref:"John 16:28"} | |
| ]}, | |
| { theme:"To Bring Light and Abundant Life", essence:"Jesus came so that people might have life — and have it more abundantly.", weight:2, gospels:["John"], color:"#16a085", | |
| statements:[ | |
| {quote:"The thief cometh not, but for to steal, and to kill, and to destroy: I am come that they might have life, and that they might have it more abundantly.",ref:"John 10:10"}, | |
| {quote:"I am come a light into the world, that whosoever believeth on me should not abide in darkness.",ref:"John 12:46"} | |
| ]}, | |
| { theme:"To Fulfill a Specific Mission", essence:"Jesus came for a specific divine moment — His sacrificial hour, and first to the lost sheep of Israel.", weight:2, gospels:["Matthew","John"], color:"#2c3e50", | |
| tension:"The focus on a specific group (Israel) or moment (\u201CHis hour\u201D) seems limiting for a universal Savior — until you see it as the entry point, not the boundary.", | |
| statements:[ | |
| {quote:"I am not sent but unto the lost sheep of the house of Israel.",ref:"Matthew 15:24"}, | |
| {quote:"But for this cause came I unto this hour.",ref:"John 12:27"} | |
| ]} | |
| ]; | |
| const maxWeight = 8; | |
| const totalStatements = 29; | |
| // --- Render purpose bars --- | |
| const purposeBars = document.getElementById('purpose-bars'); | |
| themes.forEach(t => { | |
| const pct = (t.weight / maxWeight * 100); | |
| purposeBars.innerHTML += ` | |
| <div class="bar-row"> | |
| <span class="bar-label">${t.theme}</span> | |
| <div class="bar-track"> | |
| <div class="bar-fill" style="width:${pct}%;background:${t.color}"></div> | |
| </div> | |
| <span class="bar-value">${t.weight}</span> | |
| </div>`; | |
| }); | |
| // --- Render proportion strip --- | |
| const strip = document.getElementById('proportion-strip'); | |
| const legend = document.getElementById('proportion-legend'); | |
| themes.forEach(t => { | |
| const pct = (t.weight / totalStatements * 100); | |
| strip.innerHTML += `<div class="proportion-seg" style="width:${pct}%;background:${t.color}"></div>`; | |
| legend.innerHTML += `<div class="legend-item"><span class="legend-dot" style="background:${t.color}"></span>${t.theme} (${t.weight})</div>`; | |
| }); | |
| // --- Render gospel bars --- | |
| const gospelBars = document.getElementById('gospel-bars'); | |
| const gospelData = [ | |
| { name: 'John', count: 12, color: 'var(--jn)' }, | |
| { name: 'Matthew', count: 7, color: 'var(--mt)' }, | |
| { name: 'Luke', count: 7, color: 'var(--lk)' }, | |
| { name: 'Mark', count: 3, color: 'var(--mk)' } | |
| ]; | |
| gospelData.forEach(g => { | |
| const pct = (g.count / 12 * 100); | |
| gospelBars.innerHTML += ` | |
| <div class="bar-row"> | |
| <span class="bar-label">${g.name}</span> | |
| <div class="bar-track"> | |
| <div class="bar-fill" style="width:${pct}%;background:${g.color}"></div> | |
| </div> | |
| <span class="bar-value">${g.count}</span> | |
| </div>`; | |
| }); | |
| // --- Render themes --- | |
| const container = document.getElementById('themes-container'); | |
| themes.forEach((t, i) => { | |
| const gospelChips = t.gospels.map(g => `<span class="meta-chip gospel">${g}</span>`).join(''); | |
| const verses = t.statements.map(s => | |
| `<div class="verse-card">${s.quote}<span class="ref">${s.ref}</span></div>` | |
| ).join(''); | |
| const tensionHTML = t.tension ? `<div class="tension-note">${t.tension}</div>` : ''; | |
| const barPct = (t.weight / maxWeight * 100); | |
| container.innerHTML += ` | |
| <div class="theme-block fade-in"> | |
| <div class="theme-header"> | |
| <span class="theme-number">${String(i+1).padStart(2,'0')}</span> | |
| <span class="theme-title">${t.theme}</span> | |
| </div> | |
| <div class="theme-essence">${t.essence}</div> | |
| <div class="theme-meta"> | |
| <span class="meta-chip">${t.weight} statement${t.weight>1?'s':''}</span> | |
| ${gospelChips} | |
| </div> | |
| <div class="evidence-track"> | |
| <div class="evidence-fill" style="width:${barPct}%"></div> | |
| </div> | |
| ${verses} | |
| ${tensionHTML} | |
| </div>`; | |
| }); | |
| // --- Scroll animation --- | |
| const observer = new IntersectionObserver(entries => { | |
| entries.forEach(e => { if (e.isIntersecting) e.target.classList.add('visible'); }); | |
| }, { threshold: 0.1 }); | |
| document.querySelectorAll('.fade-in').forEach(el => observer.observe(el)); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment