rename

D David Veksler · 1 year ago 23015287e4a61f513a9c331482924db38aed53cb
Parent: e6b1b76bf

2 files changed +212 −93

Diff

diff --git a/emanuel_transcript.json b/emanuel_transcript.json
index 843f74f..4cf5f6a 100644
--- a/emanuel_transcript.json
+++ b/emanuel_transcript.json
@@ -1,5 +1,5 @@
 {
-  "traditionName": "Temple Emanuel (Apr 4, 2025)",
+  "traditionName": "(Reform) Temple Emanuel (Apr 4, 2025)",
   "serviceOrder": [
     {
       "id": "opening_music",
diff --git a/shabbat-services-cheatsheet.html b/shabbat_cheatsheet.html
similarity index 54%
rename from shabbat-services-cheatsheet.html
rename to shabbat_cheatsheet.html
index f1f4d8e..cdb7731 100644
--- a/shabbat-services-cheatsheet.html
+++ b/shabbat_cheatsheet.html
@@ -1,26 +1,34 @@
 <!DOCTYPE html>
 <html lang="en">
-  <head>
+<head>
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>Shabbat Evening Service Cheatsheet</title>
     <meta
       name="description"
-      content="An interactive, customizable guide to the Shabbat Evening Service (Kabbalat Shabbat & Ma'ariv), outlining key prayers, structure, themes, and including Hebrew/English texts for various traditions."
+      content="An interactive, customizable guide to the Shabbat Evening Service (Kabbalat Shabbat & Ma'ariv), outlining key prayers, structure, themes, and including Hebrew/English texts for various Jewish traditions."
     />
-    <!-- Add canonical URL if deploying -->
-    <!-- <link rel="canonical" href="[YOUR-URL-HERE]/shabbat-services-cheatsheet.html" /> -->
+    <link rel="canonical" href="https://cheatsheets.davidveksler.com/shabbat-cheatsheet.html" />
 
-    <!-- Social Media Metadata (Optional) -->
+    <!-- Social Media Metadata -->
     <meta property="og:title" content="Shabbat Evening Service Cheatsheet" />
     <meta
       property="og:description"
       content="Interactive guide to Friday night prayers: structure, themes, Hebrew/English texts, customizable by tradition (Reform, Conservative, Orthodox, etc.)."
     />
     <meta property="og:type" content="article" />
-    <!-- <meta property="og:url" content="[YOUR-URL-HERE]/shabbat-services-cheatsheet.html" /> -->
-    <!-- <meta property="og:image" content="[YOUR-IMAGE-URL-HERE]/shabbat-preview.png"> -->
-    <meta name="twitter:card" content="summary" />
+    <meta property="og:url" content="https://cheatsheets.davidveksler.com/shabbat-cheatsheet.html" />
+    <!-- Replace with your actual image URL -->
+    <!-- <meta property="og:image" content="[YOUR-IMAGE-URL-HERE]/shabbat-preview.png" /> -->
+    <meta name="twitter:card" content="summary_large_image" /> <!-- Use summary_large_image if you have an image -->
+    <meta name="twitter:title" content="Shabbat Evening Service Cheatsheet" />
+    <meta
+      name="twitter:description"
+      content="Interactive guide to Friday night prayers: structure, themes, Hebrew/English texts, customizable by tradition."
+    />
+     <!-- Replace with your actual image URL -->
+    <!-- <meta name="twitter:image" content="[YOUR-IMAGE-URL-HERE]/shabbat-preview.png" /> -->
+
 
     <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css" />
@@ -70,6 +78,9 @@
         font-size: 1.1rem;
         color: rgba(255, 255, 255, 0.9);
         margin-top: 0.5rem;
+        max-width: 700px;
+        margin-left: auto;
+        margin-right: auto;
       }
        .controls-container {
          display: flex;
@@ -94,6 +105,11 @@
            padding: 0.4rem 0.8rem;
            border-radius: 20px;
            font-size: 0.95em;
+           cursor: pointer;
+       }
+       .tradition-selector-container select:focus {
+           outline: none;
+           box-shadow: 0 0 0 2px var(--shabbat-accent);
        }
        .tradition-selector-container select option {
            background-color: var(--shabbat-primary);
@@ -113,11 +129,34 @@
         border-color: var(--shabbat-accent);
         margin-top: 0; /* Reset margin if needed */
         margin-right: 0.5rem;
+        cursor: pointer;
       }
       .hebrew-toggle-container .form-check-input:checked {
         background-color: var(--shabbat-accent);
         border-color: var(--shabbat-secondary);
       }
+      .intro-section {
+          background-color: #fff;
+          padding: 2rem 1.5rem;
+          margin-bottom: 2.5rem;
+          border-radius: 0.5rem;
+          box-shadow: 0 3px 10px rgba(0, 0, 0, 0.05);
+          border: 1px solid #eee;
+          border-left: 5px solid var(--shabbat-primary);
+      }
+       .intro-section h3 {
+           font-family: var(--heading-font);
+           color: var(--shabbat-primary);
+           font-weight: 700;
+           margin-bottom: 1rem;
+       }
+       .intro-section p {
+           font-size: 1rem;
+           line-height: 1.7;
+           color: #444;
+       }
+        .intro-section strong { color: var(--shabbat-primary); }
+
       .section-title {
         font-family: var(--heading-font);
         color: var(--shabbat-primary);
@@ -128,10 +167,10 @@
         letter-spacing: 0.05em;
         border-bottom: 2px solid var(--shabbat-accent);
         padding-bottom: 0.5rem;
-        display: inline-block; /* Center alignment helper */
+        display: inline-block;
       }
       .section-title-container {
-        text-align: center; /* Center the inline-block title */
+        text-align: center;
         min-height: 50px; /* Prevent layout jump when title changes */
       }
       .info-card {
@@ -144,7 +183,7 @@
         display: flex;
         flex-direction: column;
         transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
-        margin-bottom: 2rem; /* Add margin between cards */
+        margin-bottom: 2rem;
       }
       .info-card:hover {
         transform: translateY(-3px);
@@ -171,8 +210,9 @@
       }
       .info-card h5 .bi {
         color: var(--shabbat-accent);
-        font-size: 1.5em; /* Make icon larger */
-        margin-right: 0.3rem;
+        font-size: 1.6em; /* Made icon slightly larger */
+        margin-right: 0.4rem;
+        vertical-align: -0.15em;
       }
       .info-card .description {
         font-size: 0.95rem;
@@ -188,7 +228,7 @@
       }
       .toggle-term .en,
       .toggle-term .he {
-        display: inline; /* Default display */
+        display: inline;
       }
       footer {
         padding-top: 3rem;
@@ -204,7 +244,7 @@
         border-top: 1px solid var(--shabbat-secondary);
         padding-top: 1rem;
         margin-top: 1rem;
-        background-color: #f8f5fa; /* Slightly different background for details */
+        background-color: #f8f5fa;
         border-radius: 0 0 0.5rem 0.5rem;
         padding: 1rem;
       }
@@ -227,28 +267,28 @@
         margin-top: 1rem;
         font-size: 1rem;
         line-height: 1.8;
-        white-space: pre-wrap; /* Allows wrapping and preserves line breaks */
+        white-space: pre-wrap;
       }
       .prayer-text .hebrew {
          font-family: var(--hebrew-font);
          font-size: 1.2em;
          color: var(--shabbat-primary);
-         display: block; /* Ensure Hebrew is on its own lines */
+         display: block;
          margin-bottom: 0.5rem;
-         direction: rtl; /* Set text direction for Hebrew */
-         text-align: right; /* Align Hebrew text to the right */
+         direction: rtl;
+         text-align: right;
       }
       .prayer-text .english-translit {
          font-family: var(--english-font);
          font-style: italic;
          color: #444;
-         display: block; /* Ensure English is on its own lines */
-         margin-bottom: 0.5rem; /* Smaller margin before translation */
+         display: block;
+         margin-bottom: 0.5rem;
          margin-top: 0.3rem;
       }
       .prayer-text .english-translate {
          font-family: var(--english-font);
-         color: #555; /* Slightly different color for translation */
+         color: #555;
          display: block;
          margin-bottom: 1rem;
       }
@@ -275,7 +315,6 @@
         vertical-align: -0.1em;
         transition: transform 0.2s ease-in-out;
       }
-      /* Updated selector for chevron toggle based on Bootstrap 5 events */
        .details-toggle .bi-chevron-down { transition: transform 0.35s ease; }
        .details-toggle[aria-expanded="true"] .bi-chevron-down { transform: rotate(180deg); }
 
@@ -304,7 +343,7 @@
          margin-bottom: 0.5rem;
        }
         .notes {
-            background-color: #fffadd; /* Light yellow background for notes */
+            background-color: #fffadd;
             border-left: 3px solid var(--shabbat-accent);
             padding: 0.8rem;
             margin-top: 1rem;
@@ -312,20 +351,22 @@
             border-radius: 0 4px 4px 0;
         }
         .notes h6 { margin-top: 0; }
+        .notes p:last-child { margin-bottom: 0; } /* Remove extra space in notes */
+
     </style>
-  </head>
-  <body>
+</head>
+<body>
     <header class="page-header">
-      <h1 class="display-5"><i class="bi bi-candle"></i> Shabbat Evening Service</h1>
+      <h1 class="display-5"><i class="bi bi-calendar-check"></i> Shabbat Evening Service</h1>
       <p class="lead">An Interactive Guide to Welcoming Shabbat Through Prayer</p>
       <div class="controls-container">
           <div class="tradition-selector-container">
-              <label for="tradition-selector">Select Tradition:</label>
+              <label for="tradition-selector">View Service Flow:</label>
               <select id="tradition-selector" class="form-select-sm">
                   <option value="reform" selected>Reform</option>
                   <option value="conservative">Conservative</option>
                   <option value="orthodox">Orthodox</option>
-                  <option value="emanuel_transcript">Temple Emanuel (Apr 4, 2025)</option>
+                  <option value="emanuel_transcript">Specific Example (Temple Emanuel, Apr 4 '25)</option>
                   <!-- Add more options here as you create more JSON files -->
               </select>
           </div>
@@ -337,28 +378,61 @@
     </header>
 
     <div class="container">
-      <div class="section-title-container">
-          <h2 class="section-title" id="current-tradition-title">Service Flow</h2>
-      </div>
-      <div id="service-content" class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
-          <!-- Service steps will be loaded here by JavaScript -->
-          <div class="col">
-              <div class="info-card">
-                  <div class="card-body">
-                      <h5>Loading...</h5>
-                      <p class="description">Please select a tradition to view the service details.</p>
-                  </div>
-              </div>
-          </div>
-      </div>
+
+        <!-- Introduction Section -->
+        <section class="intro-section">
+            <h3>Welcoming Shabbat: An Overview</h3>
+            <p>
+                The Shabbat evening service, typically held on Friday night, marks the transition from the ordinary weekday to the sacred time of Shabbat. It's a time for community gathering, spiritual reflection, and joyfully welcoming the 'Sabbath Queen' or 'Sabbath Bride'.
+            </p>
+            <p>
+                The service generally consists of two main parts:
+                <ul>
+                    <li><strong>Kabbalat Shabbat ("Receiving Shabbat"):</strong> A series of Psalms and the poem <em>Lecha Dodi</em>, introduced relatively recently (16th century) by mystics to create a spiritual gateway into Shabbat.</li>
+                    <li><strong>Ma'ariv (Evening Service):</strong> The standard evening prayer service, including the <em>Shema</em> and its blessings, and the <em>Amidah</em> (standing prayer), adapted specifically for Shabbat.</li>
+                </ul>
+            </p>
+            <p>
+                <strong>Exploring Traditions:</strong> Different Jewish movements approach the liturgy with varying emphases.
+                <strong>Orthodox</strong> services adhere closely to traditional texts and structures, primarily in Hebrew.
+                <strong>Conservative (Masorti)</strong> services also follow traditional structures but allow for some textual adaptations (like including Matriarchs) and greater use of instrumental music or egalitarian practices than Orthodoxy.
+                <strong>Reform (Liberal/Progressive)</strong> services prioritize thematic relevance and accessibility, often using significant amounts of English, contemporary readings, abbreviated texts, and embracing full egalitarianism and diverse musical styles.
+                <strong>Reconstructionist</strong> services view tradition as evolving and emphasize democratic community values, often resulting in creative and adaptive liturgy.
+            </p>
+            <p>
+                Use the dropdown menu above to explore the typical flow and key prayers within different traditions, or view a specific example service.
+            </p>
+        </section>
+
+        <!-- Dynamic Service Flow Section -->
+        <div class="section-title-container">
+            <h2 class="section-title" id="current-tradition-title">Service Flow</h2>
+        </div>
+        <div id="service-content" class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
+            <!-- Service steps will be loaded here by JavaScript -->
+            <div class="col">
+                <div class="info-card">
+                    <div class="card-body text-center">
+                        <h5 class="text-muted"><i class="bi bi-hourglass-split"></i> Loading...</h5>
+                        <p class="description text-muted">Please select a tradition above to view the service details.</p>
+                    </div>
+                </div>
+            </div>
+        </div>
+
     </div><!-- /.container -->
 
     <footer class="container text-center pb-3">
       <p class="mb-2">
-        © 2025 [Your Name/Organization] · This cheatsheet provides a general overview. Consult a Siddur (prayer book) and local custom for definitive practice. Texts may be adapted or shortened for brevity. Initial text data often sourced from public domain resources like Sefaria.org.
+        © 2025 David Veksler · This cheatsheet provides a general overview. Liturgy, order, and customs can vary significantly between movements and individual congregations. Consult a Siddur (prayer book) and local custom for definitive practice. Texts may be adapted or shortened for brevity. Initial text data often sourced from public domain resources like Sefaria.org.
       </p>
       <div>
-        <!-- Add relevant links here if desired -->
+         <a href="https://github.com/DavidVeksler/Cheatsheets" title="View Source on GitHub" target="_blank" rel="noopener noreferrer" class="mx-2 link-secondary">
+            <i class="bi bi-github"></i> GitHub
+        </a>
+        <a href="https://cheatsheets.davidveksler.com/" title="Browse All Cheatsheets" class="mx-2 link-secondary">
+            <i class="bi bi-collection"></i> All Cheatsheets
+        </a>
       </div>
     </footer>
 
@@ -371,68 +445,91 @@
 
         const applyLang = () => {
             const showHe = hebrewToggle.checked;
-            const terms = serviceContent.querySelectorAll('.toggle-term');
+            const terms = serviceContent.querySelectorAll('.toggle-term'); // Query within serviceContent
             terms.forEach(t => {
                 const en = t.querySelector('.en');
                 const he = t.querySelector('.he');
                 if (en && he) {
+                    // Ensure elements exist before accessing style
                     en.style.display = showHe ? 'none' : 'inline';
                     he.style.display = showHe ? 'inline' : 'none';
                 }
             });
+
+            // Also apply to any static toggle terms if needed (none currently outside dynamic area)
+            const staticTerms = document.querySelectorAll('.intro-section .toggle-term'); // Example if needed
+             staticTerms.forEach(t => {
+                 const en = t.querySelector('.en');
+                 const he = t.querySelector('.he');
+                 if (en && he) {
+                     en.style.display = showHe ? 'none' : 'inline';
+                     he.style.display = showHe ? 'inline' : 'none';
+                 }
+             });
         };
 
         const renderService = (serviceData) => {
             serviceContent.innerHTML = ''; // Clear previous content
             currentTraditionTitle.textContent = `${serviceData.traditionName} Service Flow`;
 
+            if (!serviceData.serviceOrder || serviceData.serviceOrder.length === 0) {
+                 serviceContent.innerHTML = `<div class="col"><div class="alert alert-warning" role="alert">No service steps defined for "${serviceData.traditionName}".</div></div>`;
+                 return;
+            }
+
             serviceData.serviceOrder.forEach(step => {
                 const cardCol = document.createElement('div');
-                // Determine column class - maybe make it dynamic later or stick to 3?
-                cardCol.className = 'col'; // Let Bootstrap handle wrapping
+                cardCol.className = 'col'; // Use Bootstrap's column system
 
-                const collapseId = `collapse-${step.id}`;
+                const collapseId = `collapse-${step.id}-${Math.random().toString(36).substring(2, 7)}`; // Add random suffix for absolute uniqueness if needed
 
-                let detailsHtml = `
-                    <h6>Background</h6>
-                    <p>${step.details.background || 'No background available.'}</p>
-                `;
-
-                if (step.details.full_text_he || step.details.full_text_en_translit || step.details.full_text_en_translate) {
-                    detailsHtml += `<h6>Text</h6><div class="prayer-text">`;
-                    if (step.details.full_text_he) {
-                        detailsHtml += `<div class="hebrew">${step.details.full_text_he}</div>`;
+                let detailsHtml = '';
+                if(step.details) { // Check if details object exists
+                    if(step.details.background) {
+                        detailsHtml += `<h6>Background</h6><p>${step.details.background}</p>`;
                     }
-                    if (step.details.full_text_en_translit) {
-                        detailsHtml += `<div class="english-translit">${step.details.full_text_en_translit}</div>`;
+
+                    if (step.details.full_text_he || step.details.full_text_en_translit || step.details.full_text_en_translate) {
+                        detailsHtml += `<h6>Text</h6><div class="prayer-text">`;
+                        if (step.details.full_text_he) {
+                            detailsHtml += `<div class="hebrew">${step.details.full_text_he}</div>`;
+                        }
+                        if (step.details.full_text_en_translit) {
+                            detailsHtml += `<div class="english-translit">${step.details.full_text_en_translit}</div>`;
+                        }
+                        if (step.details.full_text_en_translate) {
+                            detailsHtml += `<div class="english-translate">${step.details.full_text_en_translate}</div>`;
+                        }
+                        detailsHtml += `</div>`; // Close prayer-text
                     }
-                    if (step.details.full_text_en_translate) {
-                        detailsHtml += `<div class="english-translate">${step.details.full_text_en_translate}</div>`;
+
+                    let notesContent = '';
+                    if(step.details.notes) notesContent += `<p><strong>Notes:</strong> ${step.details.notes}</p>`;
+                    if(step.details.transcript_notes) notesContent += `<p><strong>Transcript Specifics:</strong> ${step.details.transcript_notes}</p>`;
+
+                    if(notesContent) {
+                        detailsHtml += `<div class="notes">${notesContent}</div>`;
                     }
-                    detailsHtml += `</div>`;
+                } else {
+                     detailsHtml = '<p><em>No further details available for this step.</em></p>';
                 }
 
-                if (step.details.notes || step.details.transcript_notes) {
-                    detailsHtml += `<div class="notes">`;
-                     if(step.details.notes) detailsHtml += `<p><strong>Notes:</strong> ${step.details.notes}</p>`;
-                     if(step.details.transcript_notes) detailsHtml += `<p><strong>Transcript Specifics:</strong> ${step.details.transcript_notes}</p>`;
-                    detailsHtml += `</div>`;
-                }
 
-                const hebrewName = step.name_he || step.name_en; // Fallback to English if no Hebrew
+                const hebrewName = step.name_he || step.name_en; // Fallback
 
                 cardCol.innerHTML = `
                     <div class="info-card">
                         <div class="card-body">
                             ${step.timestamp ? `<span class="timestamp">(${step.timestamp})</span>` : ''}
                             <h5>
-                                <i class="bi bi-${getIconForStep(step.id)}"></i> <!-- Dynamic Icon -->
+                                <i class="bi bi-${getIconForStep(step.id, step.name_en)}"></i>
                                 <span class="toggle-term">
                                     <span class="en">${step.name_en}</span>
                                     <span class="he">${hebrewName}</span>
                                 </span>
                             </h5>
-                            <p class="description">${step.summary}</p>
+                            <p class="description">${step.summary || '...'}</p>
+                            ${step.details ? `
                             <button
                                 class="btn btn-sm details-toggle mt-auto"
                                 type="button"
@@ -446,47 +543,58 @@
                             <div class="collapse collapse-content" id="${collapseId}">
                                 ${detailsHtml}
                             </div>
+                            ` : ''}
                         </div>
                     </div>
                 `;
                 serviceContent.appendChild(cardCol);
             });
 
-            applyLang(); // Apply language toggle to newly rendered content
-            // Re-initialize or ensure collapse functionality works (Bootstrap usually handles this automatically via attributes)
+            applyLang(); // Apply language toggle initially
         };
 
-        // Simple function to assign icons - expand as needed
-        const getIconForStep = (stepId) => {
-            if (stepId.includes('candle')) return 'brightness-high';
-            if (stepId.includes('kabbalat') || stepId.includes('welcome') || stepId.includes('dodi')) return 'door-open';
-            if (stepId.includes('barchu')) return 'megaphone';
-            if (stepId.includes('shema')) return 'ear';
+        // Expanded function to assign icons
+        const getIconForStep = (stepId, stepNameEn) => {
+            stepId = stepId.toLowerCase();
+            stepNameEn = stepNameEn.toLowerCase();
+
+            if (stepId.includes('candle')) return 'brightness-high-fill'; // Filled candle
+            if (stepId.includes('kabbalat') || stepId.includes('welcome') || stepId.includes('intro') || stepId.includes('dodi')) return 'door-open-fill';
+            if (stepId.includes('barchu')) return 'megaphone-fill';
+            if (stepId.includes('shema')) return 'ear-fill';
             if (stepId.includes('amidah') || stepId.includes('tefillah')) return 'person-arms-up';
             if (stepId.includes('aleinu')) return 'globe-americas';
-            if (stepId.includes('kaddish')) return 'person-heart';
+            if (stepId.includes('kaddish') || stepNameEn.includes('mourner')) return 'calendar-heart-fill'; // Yahrzeit/Mourning
             if (stepId.includes('kiddush')) return 'cup-straw';
-            if (stepId.includes('psalm') || stepId.includes('hymn') || stepId.includes('song') || stepId.includes('music')) return 'music-note-beamed';
-            if (stepId.includes('sermon') || stepId.includes('reading') || stepId.includes('blessing') || stepId.includes('tribute')) return 'book';
-            if (stepId.includes('intro') || stepId.includes('announce')) return 'info-circle';
-            if (stepId.includes('board') || stepId.includes('member') || stepId.includes('install')) return 'person-badge';
-            if (stepId.includes('healing') || stepId.includes('prayer_for')) return 'heart-pulse'; // For Mi Sheberach etc.
-            return 'star'; // Default icon
+            if (stepId.includes('psalm') || stepId.includes('hymn') || stepId.includes('song') || stepId.includes('music') || stepId.includes('dayenu')) return 'music-note-beamed';
+            if (stepId.includes('sermon') || stepId.includes('reading') || stepId.includes('response') || stepId.includes('tribute')) return 'book-half'; // Reading/Speech
+            if (stepId.includes('announce')) return 'info-circle-fill';
+            if (stepId.includes('board') || stepId.includes('member') || stepId.includes('install')) return 'person-badge-fill';
+            if (stepId.includes('healing') || stepId.includes('prayer_for') || stepId.includes('hostage')) return 'heart-pulse-fill'; // Healing/Concern
+            if (stepId.includes('blessing')) return 'stars'; // General blessing
+             if (stepId.includes('silent')) return 'pause-circle-fill';
+             if (stepId.includes('shalom')) return 'peace-fill'; // For Oseh Shalom
+            return 'check-circle'; // Default checkmark
         }
 
 
         const loadService = async (traditionKey) => {
+             serviceContent.innerHTML = `<div class="col"><div class="info-card"><div class="card-body text-center"><h5 class="text-muted"><i class="bi bi-hourglass-split"></i> Loading ${traditionSelector.options[traditionSelector.selectedIndex].text}...</h5></div></div></div>`; // Loading message
+             currentTraditionTitle.textContent = `Loading...`;
             try {
-                // Assuming JSON files are in the same directory as the HTML file
+                // Ensure JSON files are in the same directory or provide correct path
                 const response = await fetch(`./${traditionKey}.json`);
                 if (!response.ok) {
-                    throw new Error(`HTTP error! status: ${response.status}`);
+                     // Try to provide a more specific error message if possible
+                     const errorText = await response.text();
+                     console.error(`HTTP error! status: ${response.status}, message: ${errorText}`);
+                    throw new Error(`Could not fetch ${traditionKey}.json. Status: ${response.status}`);
                 }
                 const serviceData = await response.json();
                 renderService(serviceData);
             } catch (error) {
-                console.error('Error loading service data:', error);
-                serviceContent.innerHTML = `<div class="col"><div class="alert alert-danger" role="alert">Could not load service data for "${traditionKey}". Please ensure the file exists and is valid JSON.</div></div>`;
+                console.error('Error loading or rendering service data:', error);
+                serviceContent.innerHTML = `<div class="col"><div class="alert alert-danger" role="alert"><strong>Error:</strong> Could not load service data for "${traditionSelector.options[traditionSelector.selectedIndex].text}".<br><small>Please ensure the file "${traditionKey}.json" exists in the same directory as this HTML file and is valid JSON.</small></div></div>`;
                 currentTraditionTitle.textContent = `Error Loading Data`;
             }
         };
@@ -501,8 +609,19 @@
         // Initial Load
         document.addEventListener('DOMContentLoaded', () => {
             loadService(traditionSelector.value); // Load default selected tradition
+             // Also apply language toggle to static intro section on load
+             const staticTerms = document.querySelectorAll('.intro-section .toggle-term');
+             const showHe = hebrewToggle.checked;
+             staticTerms.forEach(t => {
+                 const en = t.querySelector('.en');
+                 const he = t.querySelector('.he');
+                 if (en && he) {
+                     en.style.display = showHe ? 'none' : 'inline';
+                     he.style.display = showHe ? 'inline' : 'none';
+                 }
+             });
         });
 
     </script>
-  </body>
+</body>
 </html>
\ No newline at end of file