173173 transform : scale (0.95 );
174174 }
175175 </ style >
176+ < style id ="presentation-styles ">
177+ !PRESENTATION_STYLES!
178+ </ style >
176179</ head >
177180< body class ="bg-gray-900 text-gray-100 h-screen flex flex-col ">
178181 <!-- Overlay for mobile drawers -->
@@ -217,8 +220,14 @@ <h1 class="text-base sm:text-lg font-bold text-blue-400 truncate">Bible Cross-Re
217220 class ="w-20 sm:w-24 h-2 bg-gray-700 rounded-lg cursor-pointer ">
218221 < span id ="arc-value " class ="text-xs w-8 "> 500</ span >
219222 </ div >
220- < input type ="text " id ="search-input " placeholder ="Search (e.g., John 3:16, Gen 1:1-3)... "
221- class ="bg-gray-700 text-gray-100 text-xs rounded px-2 py-1 w-24 sm:w-48 focus:outline-none focus:ring-2 focus:ring-blue-500 ">
223+ < button onclick ="openPresentation('creed') " class ="text-xs bg-gray-700 hover:bg-blue-600 px-2 sm:px-3 py-1.5 rounded border border-gray-600 hover:border-blue-500 text-blue-400 hover:text-white transition-colors whitespace-nowrap ">
224+ Nicene Creed
225+ </ button >
226+ < button onclick ="openPresentation('prophecy') " class ="text-xs bg-gray-700 hover:bg-blue-600 px-2 sm:px-3 py-1.5 rounded border border-gray-600 hover:border-blue-500 text-blue-400 hover:text-white transition-colors whitespace-nowrap ">
227+ Prophecies
228+ </ button >
229+ < input type ="text " id ="search-input " placeholder ="Search... "
230+ class ="bg-gray-700 text-gray-100 text-xs rounded px-2 py-1 w-24 sm:w-32 focus:outline-none focus:ring-2 focus:ring-blue-500 ">
222231 < button onclick ="toggleHelp() " class ="text-gray-400 hover:text-blue-300 transition-colors " title ="Help ">
223232 < svg width ="18 " height ="18 " viewBox ="0 0 24 24 " fill ="none " stroke ="currentColor " stroke-width ="2 ">
224233 < circle cx ="12 " cy ="12 " r ="10 "> </ circle >
@@ -246,7 +255,6 @@ <h2 class="text-sm font-semibold text-blue-400">How to Use</h2>
246255 < h3 class ="font-semibold text-gray-100 mb-1 "> What You're Viewing</ h3 >
247256 < p class ="leading-relaxed "> Thousands of Bible cross-references mapped to Rainbow-colored themes. Each arc shows a connection between two verses, colored by the dominant theme of the source verse.</ p >
248257 </ div >
249-
250258 < div >
251259 < h3 class ="font-semibold text-gray-100 mb-1 "> Navigate Visualization</ h3 >
252260 < ul class ="space-y-1 ml-4 list-disc ">
@@ -256,7 +264,6 @@ <h3 class="font-semibold text-gray-100 mb-1">Navigate Visualization</h3>
256264 < li > < strong > Use keyboard arrows</ strong > ← → for quick navigation</ li >
257265 </ ul >
258266 </ div >
259-
260267 < div >
261268 < h3 class ="font-semibold text-gray-100 mb-1 "> View Details</ h3 >
262269 < ul class ="space-y-1 ml-4 list-disc ">
@@ -265,30 +272,41 @@ <h3 class="font-semibold text-gray-100 mb-1">View Details</h3>
265272 < li > < strong > Bible Difficulties</ strong > appear below arcs when scrolled</ li >
266273 </ ul >
267274 </ div >
268-
269275 < div >
270- < h3 class ="font-semibold text-gray-100 mb-1 "> Rainbow Themes</ h3 >
271- < p class ="leading-relaxed "> Each color represents a theological theme (e.g., God=blue, Creation=green, Redemption=purple). Filter by theme using the sidebar.</ p >
276+ < h3 class ="font-semibold text-gray-100 mb-1 "> Presentations</ h3 >
277+ < ul class ="space-y-1 ml-4 list-disc ">
278+ < li > < strong > Nicene Creed</ strong > - 16-slide presentation with correlating KJV scriptures</ li >
279+ < li > < strong > Prophecies</ strong > - 18 messianic prophecies with fulfillment verses</ li >
280+ </ ul >
272281 </ div >
273-
274282 < div >
275283 < h3 class ="font-semibold text-gray-100 mb-1 "> Controls</ h3 >
276284 < ul class ="space-y-1 ml-4 list-disc ">
277285 < li > < strong > Votes slider</ strong > — filter cross-references by community votes</ li >
278286 < li > < strong > Arcs slider</ strong > — limit number of visible arcs</ li >
279- < li > < strong > Search</ strong > — find books (e.g., "Genesis") or verses (e.g., "John 3:16", "Gen 1:1-3")</ li >
280- < li > < strong > Verse search</ strong > — finds verse + all connected cross-references (shows relevant arcs only)</ li >
281- < li > < strong > Source filters</ strong > — toggle Bible difficulties by source</ li >
287+ < li > < strong > Search</ strong > — find books or verses</ li >
282288 </ ul >
283289 </ div >
284-
285290 < div class ="pt-2 border-t border-gray-700 ">
286291 < p class ="text-gray-500 italic "> Use the < kbd class ="bg-gray-700 px-1.5 py-0.5 rounded text-[10px] "> ?</ kbd > button to show/hide this help</ p >
287292 </ div >
288293 </ div >
289294 </ div >
290295 </ div >
291296
297+ <!-- Presentation Overlay -->
298+ < div id ="presentation-overlay " class ="fixed inset-0 bg-black/80 backdrop-blur-sm z-[100] hidden ">
299+ < button onclick ="closePresentation() " class ="absolute top-4 right-4 z-50 w-10 h-10 bg-gray-800/90 hover:bg-gray-700 border border-gray-600 rounded-full flex items-center justify-center text-white transition-all hover:scale-110 " title ="Close presentation ">
300+ < svg width ="20 " height ="20 " viewBox ="0 0 24 24 " fill ="none " stroke ="currentColor " stroke-width ="2 ">
301+ < line x1 ="18 " y1 ="6 " x2 ="6 " y2 ="18 "> </ line >
302+ < line x1 ="6 " y1 ="6 " x2 ="18 " y2 ="18 "> </ line >
303+ </ svg >
304+ </ button >
305+ < div id ="presentation-content " class ="w-full h-full overflow-auto ">
306+ <!-- Presentation content will be injected here -->
307+ </ div >
308+ </ div >
309+
292310 <!-- Mobile Controls Bar -->
293311 < div class ="mobile-only bg-gray-800 border-b border-gray-700 px-3 py-2 flex items-center gap-3 flex-shrink-0 ">
294312 < div class ="flex items-center gap-1 ">
@@ -2848,6 +2866,273 @@ <h4 class="text-xs font-semibold text-gray-400 uppercase mb-1">Cross-References
28482866 requestAnimationFrame ( animate ) ;
28492867 }
28502868 animate ( ) ;
2851- </ script >
2852- </ body >
2869+ </ script >
2870+
2871+ < script src ="presentation_data.js "> </ script >
2872+
2873+ < script >
2874+ ( function ( ) {
2875+ 'use strict' ;
2876+
2877+ // Presentation overlay management
2878+ let presentationContent = '' ;
2879+ let cleanupFunction = null ;
2880+
2881+ function openPresentation ( type ) {
2882+ const overlay = document . getElementById ( 'presentation-overlay' ) ;
2883+ const contentDiv = document . getElementById ( 'presentation-content' ) ;
2884+ const stylesElement = document . getElementById ( 'presentation-styles' ) ;
2885+
2886+ // Show overlay
2887+ overlay . classList . remove ( 'hidden' ) ;
2888+ document . body . style . overflow = 'hidden' ;
2889+
2890+ // Load presentation styles and content
2891+ if ( type === 'creed' ) {
2892+ stylesElement . textContent = PRESENTATION_STYLES ;
2893+ presentationContent = `
2894+ <div class="bg-animation"></div>
2895+ <div class="particles" id="creed-particles"></div>
2896+ <div class="main-container">
2897+ <div class="title">Nicene Creed</div>
2898+ <div class="creed-container">
2899+ <div class="slide-container" id="creed-slideContainer">${ creedSlidesHTML } </div>
2900+ <div class="progress-container" id="creed-progressContainer"></div>
2901+ <div class="nav-buttons">
2902+ <button class="nav-btn" id="creed-prevBtn">← Previous</button>
2903+ <button class="nav-btn pause-btn" id="creed-pauseBtn">Pause</button>
2904+ <button class="nav-btn" id="creed-nextBtn">Next →</button>
2905+ </div>
2906+ <div class="footer">"Jesus answered them, and said, My doctrine is not mine, but his that sent me." - John 7:16</div>
2907+ </div>
2908+ </div>
2909+ ` ;
2910+ contentDiv . innerHTML = presentationContent ;
2911+ initCreedPresentation ( ) ;
2912+ } else if ( type === 'prophecy' ) {
2913+ stylesElement . textContent = PRESENTATION_STYLES ;
2914+ presentationContent = `
2915+ <div class="bg-animation"></div>
2916+ <div class="particles" id="prophecy-particles"></div>
2917+ <div class="main-container">
2918+ <div class="title">Messianic Prophecies</div>
2919+ <div class="creed-container">
2920+ <div class="slide-container" id="prophecy-slideContainer">${ prophecySlidesHTML } </div>
2921+ <div class="progress-container" id="prophecy-progressContainer"></div>
2922+ <div class="nav-buttons">
2923+ <button class="nav-btn" id="prophecy-prevBtn">← Previous</button>
2924+ <button class="nav-btn pause-btn" id="prophecy-pauseBtn">Pause</button>
2925+ <button class="nav-btn" id="prophecy-nextBtn">Next →</button>
2926+ </div>
2927+ <div class="footer">"Search the scriptures; for in them ye think ye have eternal life: and they are they which testify of me." - John 5:39</div>
2928+ </div>
2929+ </div>
2930+ ` ;
2931+ contentDiv . innerHTML = presentationContent ;
2932+ initProphecyPresentation ( ) ;
2933+ }
2934+ }
2935+
2936+ function closePresentation ( ) {
2937+ const overlay = document . getElementById ( 'presentation-overlay' ) ;
2938+ const contentDiv = document . getElementById ( 'presentation-content' ) ;
2939+ const stylesElement = document . getElementById ( 'presentation-styles' ) ;
2940+
2941+ // Clean up presentation interval if exists
2942+ if ( cleanupFunction ) {
2943+ cleanupFunction ( ) ;
2944+ cleanupFunction = null ;
2945+ }
2946+
2947+ // Clear content and styles
2948+ contentDiv . innerHTML = '' ;
2949+ stylesElement . textContent = '' ;
2950+
2951+ // Hide overlay
2952+ overlay . classList . add ( 'hidden' ) ;
2953+ document . body . style . overflow = '' ;
2954+ }
2955+
2956+ // Initialize Nicene Creed presentation
2957+ function initCreedPresentation ( ) {
2958+ initPresentation ( 'creed' ) ;
2959+ }
2960+
2961+ // Initialize Prophecy presentation
2962+ function initProphecyPresentation ( ) {
2963+ initPresentation ( 'prophecy' ) ;
2964+ }
2965+
2966+ // Generic presentation initialization
2967+ function initPresentation ( prefix ) {
2968+ const SLIDE_DURATION = 12000 ;
2969+ let currentSlide = 0 ;
2970+ let slideInterval = null ;
2971+ let isPaused = false ;
2972+
2973+ const prefixLower = prefix . toLowerCase ( ) ;
2974+ const slides = document . getElementById ( prefixLower + '-slideContainer' ) . querySelectorAll ( '.slide' ) ;
2975+ const progressContainer = document . getElementById ( prefixLower + '-progressContainer' ) ;
2976+ const prevBtn = document . getElementById ( prefixLower + '-prevBtn' ) ;
2977+ const nextBtn = document . getElementById ( prefixLower + '-nextBtn' ) ;
2978+ const pauseBtn = document . getElementById ( prefixLower + '-pauseBtn' ) ;
2979+ const particlesContainer = document . getElementById ( prefixLower + '-particles' ) ;
2980+
2981+ if ( ! slides . length ) {
2982+ console . error ( 'No slides found for' , prefix ) ;
2983+ return ;
2984+ }
2985+
2986+ // Create particles
2987+ for ( let i = 0 ; i < 30 ; i ++ ) {
2988+ const particle = document . createElement ( 'div' ) ;
2989+ particle . className = 'particle' ;
2990+ particle . style . left = Math . random ( ) * 100 + '%' ;
2991+ particle . style . animationDelay = Math . random ( ) * 8 + 's' ;
2992+ particle . style . animationDuration = ( 6 + Math . random ( ) * 4 ) + 's' ;
2993+ particlesContainer . appendChild ( particle ) ;
2994+ }
2995+
2996+ // Create progress dots
2997+ slides . forEach ( ( _ , index ) => {
2998+ const dot = document . createElement ( 'div' ) ;
2999+ dot . className = 'progress-dot' + ( index === 0 ? ' active' : '' ) ;
3000+ dot . addEventListener ( 'click' , ( ) => goToSlide ( index ) ) ;
3001+ progressContainer . appendChild ( dot ) ;
3002+ } ) ;
3003+
3004+ function updateProgressDots ( ) {
3005+ const dots = progressContainer . querySelectorAll ( '.progress-dot' ) ;
3006+ dots . forEach ( ( dot , index ) => {
3007+ dot . classList . toggle ( 'active' , index === currentSlide ) ;
3008+ } ) ;
3009+ }
3010+
3011+ function showSlide ( index ) {
3012+ slides . forEach ( ( slide , i ) => {
3013+ slide . classList . toggle ( 'active' , i === index ) ;
3014+ } ) ;
3015+ }
3016+
3017+ function goToSlide ( index ) {
3018+ if ( index < 0 ) index = slides . length - 1 ;
3019+ if ( index >= slides . length ) index = 0 ;
3020+
3021+ currentSlide = index ;
3022+ showSlide ( currentSlide ) ;
3023+ updateProgressDots ( ) ;
3024+
3025+ if ( ! isPaused ) {
3026+ resetInterval ( ) ;
3027+ }
3028+ }
3029+
3030+ function nextSlide ( ) {
3031+ goToSlide ( currentSlide + 1 ) ;
3032+ }
3033+
3034+ function prevSlide ( ) {
3035+ goToSlide ( currentSlide - 1 ) ;
3036+ }
3037+
3038+ function resetInterval ( ) {
3039+ if ( slideInterval ) {
3040+ clearInterval ( slideInterval ) ;
3041+ }
3042+ slideInterval = setInterval ( nextSlide , SLIDE_DURATION ) ;
3043+ }
3044+
3045+ function togglePause ( ) {
3046+ isPaused = ! isPaused ;
3047+ pauseBtn . textContent = isPaused ? 'Play' : 'Pause' ;
3048+ pauseBtn . classList . toggle ( 'paused' , isPaused ) ;
3049+
3050+ if ( isPaused ) {
3051+ clearInterval ( slideInterval ) ;
3052+ } else {
3053+ resetInterval ( ) ;
3054+ }
3055+ }
3056+
3057+ // Event listeners
3058+ const cleanupEvents = [ ] ;
3059+
3060+ const prevHandler = ( ) => { prevSlide ( ) ; } ;
3061+ const nextHandler = ( ) => { nextSlide ( ) ; } ;
3062+ const pauseHandler = ( ) => { togglePause ( ) ; } ;
3063+
3064+ prevBtn . addEventListener ( 'click' , prevHandler ) ;
3065+ nextBtn . addEventListener ( 'click' , nextHandler ) ;
3066+ pauseBtn . addEventListener ( 'click' , pauseHandler ) ;
3067+ cleanupEvents . push ( ( ) => { prevBtn . removeEventListener ( 'click' , prevHandler ) ; } ) ;
3068+ cleanupEvents . push ( ( ) => { nextBtn . removeEventListener ( 'click' , nextHandler ) ; } ) ;
3069+ cleanupEvents . push ( ( ) => { pauseBtn . removeEventListener ( 'click' , pauseHandler ) ; } ) ;
3070+
3071+ // Keyboard navigation
3072+ const keyboardHandler = ( e ) => {
3073+ if ( e . key === 'ArrowRight' || e . key === ' ' ) {
3074+ e . preventDefault ( ) ;
3075+ nextSlide ( ) ;
3076+ } else if ( e . key === 'ArrowLeft' ) {
3077+ e . preventDefault ( ) ;
3078+ prevSlide ( ) ;
3079+ } else if ( e . key === 'p' || e . key === 'P' ) {
3080+ togglePause ( ) ;
3081+ } else if ( e . key === 'Escape' ) {
3082+ closePresentation ( ) ;
3083+ }
3084+ } ;
3085+ document . addEventListener ( 'keydown' , keyboardHandler ) ;
3086+ cleanupEvents . push ( ( ) => { document . removeEventListener ( 'keydown' , keyboardHandler ) ; } ) ;
3087+
3088+ // Touch/swipe support
3089+ let touchStartX = 0 ;
3090+ let touchEndX = 0 ;
3091+
3092+ const touchStartHandler = ( e ) => {
3093+ touchStartX = e . changedTouches [ 0 ] . screenX ;
3094+ } ;
3095+ const touchEndHandler = ( e ) => {
3096+ touchEndX = e . changedTouches [ 0 ] . screenX ;
3097+ handleSwipe ( ) ;
3098+ } ;
3099+
3100+ document . addEventListener ( 'touchstart' , touchStartHandler , { passive : true } ) ;
3101+ document . addEventListener ( 'touchend' , touchEndHandler , { passive : true } ) ;
3102+ cleanupEvents . push ( ( ) => { document . removeEventListener ( 'touchstart' , touchStartHandler ) ; } ) ;
3103+ cleanupEvents . push ( ( ) => { document . removeEventListener ( 'touchend' , touchEndHandler ) ; } ) ;
3104+
3105+ function handleSwipe ( ) {
3106+ const swipeThreshold = 50 ;
3107+ const diff = touchStartX - touchEndX ;
3108+
3109+ if ( Math . abs ( diff ) > swipeThreshold ) {
3110+ if ( diff > 0 ) {
3111+ nextSlide ( ) ;
3112+ } else {
3113+ prevSlide ( ) ;
3114+ }
3115+ }
3116+ }
3117+
3118+ // Initialize
3119+ showSlide ( 0 ) ;
3120+ resetInterval ( ) ;
3121+
3122+ // Cleanup function
3123+ cleanupFunction = ( ) => {
3124+ if ( slideInterval ) {
3125+ clearInterval ( slideInterval ) ;
3126+ }
3127+ cleanupEvents . forEach ( fn => fn ( ) ) ;
3128+ } ;
3129+ }
3130+
3131+ // Make functions globally accessible
3132+ window . openPresentation = openPresentation ;
3133+ window . closePresentation = closePresentation ;
3134+ } ) ( ) ;
3135+
3136+ </ script >
3137+ </ body >
28533138</ html >
0 commit comments