AI 對話紀錄 September 24, 2025

.main__right) isn’t aligning properly in this intermediate width range. Since you couldn’t identify the contributing class, I’ll analyze the issue based on the page-empty.hbs template and previous CSS, propose a fix, and provide an updated custom.css (Version 3.5) with version numbering..banner--after-content or a related style) had circled properties (e.g., border, margin, or padding) that, when disabled, removed the line. This suggests the line is a border or spacing artifact we can target..main__right or its content isn’t centering. This could stem from:
.main__right or .content__entry might not adjust its max-width or margin correctly.max-width: 1200px) and mobile (width: 100vw) lacks a smooth adjustment..main__right contains .content__entry--full and conditionally .main__right--bottom, which might shift alignment without proper constraints..banner--after-content) and set border: none !important and outline: none !important to remove the line, based on the circled styles..main__right using margin: 0 auto and a dynamic max-width (e.g., 90% or calculated value)..content__entry--full and .main__right--bottom inherit this centering./* Custom CSS for NLT Chaplaincy CMS - Version 3.5 */.Below is the updated custom.css (Version 3.5) addressing the line and centering.
/* Custom CSS for NLT Chaplaincy CMS - Version 3.5 */
/* Ensure myButton overrides theme styles */
.content__buttons a.myButton {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
a.myButtonBig {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Button Styles */
.myButtonBig {
background: linear-gradient(to bottom, #44c767 5%, #5cbf2a 100%);
background-color: #44c767;
border-radius: 28px;
border: 1px solid #18ab29;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 21px;
font-weight: bold;
padding: 24px 42px;
text-decoration: none;
text-shadow: 0px 1px 0px #2f6627;
transition: all 0.3s ease;
}
.myButtonBig:hover {
background: linear-gradient(to bottom, #5cbf2a 5%, #44c767 100%);
background-color: #5cbf2a;
border-color: #137c21;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.myButtonBig:active {
position: relative;
top: 1px;
background: linear-gradient(to bottom, #3ba052 5%, #4aa62b 100%);
background-color: #3ba052;
border-color: #0f5c18;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
}
.myButton {
background: linear-gradient(to bottom, #44c767 5%, #5cbf2a 100%);
background-color: #44c767;
border-radius: 28px;
border: 1px solid #18ab29;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 17px;
font-weight: bold;
padding: 16px 31px;
text-decoration: none;
text-shadow: 0px 1px 0px #2f6627;
transition: all 0.3s ease;
}
.myButton:hover {
background: linear-gradient(to bottom, #5cbf2a 5%, #44c767 100%);
background-color: #5cbf2a;
border-color: #137c21;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.myButton:active {
position: relative;
top: 1px;
background: linear-gradient(to bottom, #3ba052 5%, #4aa62b 100%);
background-color: #3ba052;
border-color: #0f5c18;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
}
/* Set default font for the entire site */
body {
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Test class to verify font loading */
.font-test {
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 24px;
color: red;
}
/* Dynamic Section Styles */
.content__entry {
position: relative;
padding: 20px;
min-height: 200px;
margin: 0 auto;
max-width: 1200px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #fff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.section-hero--full {
width: auto;
position: relative;
left: 0;
transform: none;
margin: 0 auto;
max-width: 1200px;
min-height: 400px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #fff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
@media (max-width: 768px) {
.section-hero--full {
width: 100vw;
left: 50%;
transform: translateX(-50%);
margin: 0;
padding: 0;
min-height: 300px;
}
.section-hero__content {
padding: 10px;
}
.section-hero__content h1 {
font-size: 1.5em;
margin-bottom: 0.75em;
padding-top: 0.75em;
}
.generic-content {
font-size: 0.9em;
max-width: 100%;
padding: 0 10px;
}
}
.section-hero__content {
position: relative;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
z-index: 1;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.section-hero--full[style*="background-image"] h1,
.section-hero--full[style*="background-image"] .generic-content {
color: #fff;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
.section-hero--full h1,
.section-hero--full .generic-content {
color: #333;
}
/* Override theme's heading font variable */
h1, h2, h3, h4, h5, h6 {
font-family: "LXGW WenKai TC", "Times New Roman", serif !important;
margin-bottom: 1.5em !important; /* Increased margin for taller spacing */
}
/* Ensure specific heading styles inherit the font */
.content__entry h1 {
font-size: 2em;
font-weight: 700;
line-height: 1.2;
color: #333;
margin-bottom: 1.5em !important; /* Taller margin */
padding-top: 1em;
text-align: center;
text-shadow: none;
font-family: "LXGW WenKai TC", "Times New Roman", serif !important;
}
.generic-content {
text-align: center;
margin: 0 auto;
max-width: 800px;
font-size: 1em;
line-height: 1.6;
color: #333;
margin-bottom: 1em;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry[style*="background-image"] h1,
.content__entry[style*="background-image"] .generic-content {
color: #fff;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
.generic-content p {
margin: 0 0 1em 0;
}
.generic-content ul,
.generic-content ol {
margin: 0 0 1em 0;
padding: 0 !important;
list-style: none !important;
}
.generic-content li {
margin-bottom: 0.5em;
text-align: center;
list-style: none !important;
}
.generic-content ul[style*="list-style"],
.generic-content ol[style*="list-style"],
.generic-content li[style*="list-style"] {
list-style: none !important;
}
.content__buttons {
text-align: center !important;
margin: 2em 0 1em 0;
}
.content__buttons a.myButton {
display: inline-block;
margin: 0 auto;
}
.content__entry .content__buttons {
text-align: center !important;
}
.welcome-image {
max-width: 100%;
height: auto;
margin: 1em auto;
display: block;
border-radius: 8px; /* Added for rounded corners */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Added for light shadow */
}
.video-embed {
position: relative;
padding-bottom: 56.25%;
height: 0;
overflow: hidden;
margin: 1em auto;
max-width: 800px;
background: none;
}
.video-embed iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
.separator {
text-align: center;
margin: 60px 0 20px 0;
}
/* Remove min-height and top spacing from the first content__entry--full */
.content__entry.content__entry--full:first-child {
min-height: 0 !important;
padding-top: 0 !important;
margin-top: 0 !important;
}
/* Adjust margin-top to close gap on PC view with maximum specificity */
.main.page .main__right:first-child {
margin-top: -3.8rem !important;
margin-top: -3.8rem !important; /* Redundant !important for priority */
}
/* Remove extra padding on right scrolling frame with maximum specificity */
.main.page .main__right {
margin: 0% !important;
margin: 0% !important; /* Redundant !important for priority */
}
/* Target the gap-causing class (.banner--after-content) and remove the line */
.banner--after-content {
margin: 0 !important;
margin: 0 !important; /* Redundant !important for priority */
padding: 0 !important;
padding: 0 !important; /* Redundant !important for priority */
border: none !important;
border: none !important; /* Redundant !important for priority */
outline: none !important;
outline: none !important; /* Redundant !important for priority */
}
/* Reset and adjust spacing for mobile view with maximum specificity */
@media (max-width: 768px) {
.main.page .main__right:first-child {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
/* Target potential parent containers in mobile view */
.main.page .container:first-child,
.main.page .post__entry:first-child {
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
.main.page .main__right .main__right--bottom:first-child {
margin-top: -3.8rem !important;
margin-top: -3.8rem !important; /* Redundant !important for priority */
margin-bottom: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
.main.page .container > .main__right > .main__right--bottom:first-child,
.main.page .post__entry > .main__right > .main__right--bottom:first-child {
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
/* Target the gap-causing class (.banner--after-content) in mobile view */
.banner--after-content {
margin: 0 !important;
margin: 0 !important; /* Redundant !important for priority */
padding: 0 !important;
padding: 0 !important; /* Redundant !important for priority */
border: none !important;
border: none !important; /* Redundant !important for priority */
outline: none !important;
outline: none !important; /* Redundant !important for priority */
}
}
/* Intermediate width range (e.g., 768px to 1024px) to fix centering */
@media (min-width: 769px) and (max-width: 1023px) {
.main.page .main__right {
margin: 0 auto !important;
margin: 0 auto !important; /* Redundant !important for priority */
max-width: 90% !important;
max-width: 90% !important; /* Redundant !important for priority */
width: auto !important;
width: auto !important; /* Redundant !important for priority */
}
.main.page .main__right .content__entry--full {
margin: 0 auto !important;
margin: 0 auto !important; /* Redundant !important for priority */
max-width: 100% !important;
max-width: 100% !important; /* Redundant !important for priority */
}
.main.page .main__right .main__right--bottom {
margin: 0 auto !important;
margin: 0 auto !important; /* Redundant !important for priority */
max-width: 100% !important;
max-width: 100% !important; /* Redundant !important for priority */
}
}
/* Ensure first section-hero--full has no extra top margin */
.main.page .main__right .main__right--bottom .section-hero--full:first-child {
margin-top: 0 !important;
padding-top: 0 !important;
}
/* Remove top margin from the first separator within content__entry--full */
.content__entry.content__entry--full .separator:first-child {
margin-top: 0;
}
.section-hero--full:not([style*="background-image"]) + .separator {
margin-top: 40px;
}
.separator-image {
max-width: 100%;
height: auto;
display: block;
margin: 0 auto;
}
.separator img[src$="down_arrow.png"] {
max-width: 256px;
}
hr {
display: none !important;
visibility: hidden !important;
}
.post__content hr,
.container hr,
.post__content hr[style],
.container hr[style] {
display: none !important;
visibility: hidden !important;
}
.post__content::before,
.post__content::after,
.container::before,
.container::after,
.post__entry::before,
.post__entry::after,
.content__entry::before,
.content__entry::after,
.generic-content::before,
.generic-content::after {
display: none !important;
border: none !important;
content: none !important;
}
.separator::before,
.separator::after {
display: none !important;
border: none !important;
content: none !important;
}
body,
body p,
body h2,
body h3,
body h4,
body h5,
body h6,
.post__content,
.post__content p,
.post__content h2,
.post__content h3,
.post__content h4,
.post__content h5,
.post__content h6,
.container,
.container p,
.container h2,
.container h3,
.container h4,
.container h5,
.container h6 {
color: #333 !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
h1.post__title,
h1.hero__title,
h1.site__title {
color: #fff !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
a.button,
a.btn,
a.post__button,
.post__content a.button,
.post__content a.btn,
.post__content a.post__button,
.container a.button,
.container a.btn,
.container a.post__button {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Custom Modal Styles */
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
background-color: #fff;
margin: 5% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 800px;
min-height: 200px;
position: relative;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
}
.modal-close {
color: #aaa;
position: absolute;
top: 10px;
right: 20px;
font-size: 28px;
font-weight: bold;
cursor: pointer;
transition: color 0.3s ease;
z-index: 1001;
}
.modal-close:hover,
.modal-close:focus {
color: #000;
text-decoration: none;
}
#modal-body {
font-size: 1em;
line-height: 1.6;
color: #333;
max-width: 100%;
box-sizing: border-box;
padding-top: 40px;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
#modal-body h1 {
font-size: 1.5em;
margin-bottom: 0.5em;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
#modal-body p {
margin-bottom: 1em;
}
#modal-body * {
max-width: 100%;
box-sizing: border-box;
}
#modal-body img,
#modal-body div,
#modal-body table {
max-width: 100%;
height: auto;
}
#modal-body .welcome-image {
border-radius: 8px; /* Ensure rounded corners in mobile */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Ensure light shadow in mobile */
}
.modal[aria-hidden="false"] {
display: block;
}
.modal-close:focus {
outline: 2px solid #44c767;
outline-offset: 2px;
}
/* Custom separator for modal sections */
.modal-section-separator {
text-align: center;
margin: 20px 0;
font-size: 24px;
line-height: 1;
color: #666;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.modal-section-separator::before {
content: "···";
}
/* Chaplaincy Admin specific overrides */
.report-container {
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry {
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
box-sizing: border-box !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry table.report-table {
width: 100% !important;
margin: 0 !important;
padding: 0 !important;
border-collapse: collapse !important;
box-sizing: border-box !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
border: none !important and outline: none !important to .banner--after-content with redundant !important to match the circled styles from Image 1.@media (min-width: 769px) and (max-width: 1023px) to target the intermediate range..main.page .main__right { margin: 0 auto !important; max-width: 90% !important; width: auto !important; } to enforce centering..content__entry--full and .main__right--bottom to align their content./* Custom CSS for NLT Chaplaincy CMS - Version 3.5 */.custom.css is in /Web/nlhcm/public/assets/css/custom.css.custom.css loads with a 200 status..banner--after-content shows border: none !important and .main__right shows margin: 0 auto !important in the intermediate range.custom.css and follow troubleshooting steps.https://www.nlt-chaplaincy.org/index.php and https://www.nlt-chaplaincy.org/stories.php at 08:00 PM HKT on Monday, August 11, 2025..banner--after-content showing border: none !important..main__right is centered, with red arrows (if re-added) showing equal lengths..content__entry--full and .main__right--bottom align properly..section-hero--full.index.php and test all views..welcome-image, .myButton, and .myButtonBig styles..main__right in the intermediate range, noting the window width..banner--after-content’s border caused the line, and the intermediate range needs explicit centering rules.The file management plan remains available for your review.
.top__item--right as a potential class to address. Upon reviewing, it seems there was a misunderstanding: the previous fix targeted .banner--after-content for the line removal based on your earlier input, but your latest message indicates .top__item--right might be the correct class causing the line. Since .top__item--right isn’t explicitly mentioned in the page-empty.hbs template you provided, it could be part of the theme’s broader layout (e.g., a header or sidebar element) or dynamically injected. I’ll adjust the custom.css to target .top__item--right for the line removal, while preserving the centering fix, and provide an updated custom.css (Version 3.6) with version numbering.@media (min-width: 769px) and (max-width: 1023px) rules successfully centered .main__right, addressing the uneven red arrows..banner--after-content’s border: none !important and outline: none !important didn’t target the correct element. Your mention of .top__item--right implies this class, possibly in the header or a right-aligned top section, is responsible for the line (e.g., a border or divider)..top__item--right might be part of the navbar partial (included via {{> navbar}} in page-empty.hbs) or a theme-specific style, contributing to the top layout..top__item--right with border: none !important, outline: none !important, and box-shadow: none !important to eliminate the line..main__right, .content__entry--full, and .main__right--bottom..banner--after-content rules and margin-top: -3.8rem adjustments./* Custom CSS for NLT Chaplaincy CMS - Version 3.6 */.Below is the updated custom.css (Version 3.6) targeting .top__item--right for the line.
/* Custom CSS for NLT Chaplaincy CMS - Version 3.6 */
/* Ensure myButton overrides theme styles */
.content__buttons a.myButton {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
a.myButtonBig {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Button Styles */
.myButtonBig {
background: linear-gradient(to bottom, #44c767 5%, #5cbf2a 100%);
background-color: #44c767;
border-radius: 28px;
border: 1px solid #18ab29;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 21px;
font-weight: bold;
padding: 24px 42px;
text-decoration: none;
text-shadow: 0px 1px 0px #2f6627;
transition: all 0.3s ease;
}
.myButtonBig:hover {
background: linear-gradient(to bottom, #5cbf2a 5%, #44c767 100%);
background-color: #5cbf2a;
border-color: #137c21;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.myButtonBig:active {
position: relative;
top: 1px;
background: linear-gradient(to bottom, #3ba052 5%, #4aa62b 100%);
background-color: #3ba052;
border-color: #0f5c18;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
}
.myButton {
background: linear-gradient(to bottom, #44c767 5%, #5cbf2a 100%);
background-color: #44c767;
border-radius: 28px;
border: 1px solid #18ab29;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 17px;
font-weight: bold;
padding: 16px 31px;
text-decoration: none;
text-shadow: 0px 1px 0px #2f6627;
transition: all 0.3s ease;
}
.myButton:hover {
background: linear-gradient(to bottom, #5cbf2a 5%, #44c767 100%);
background-color: #5cbf2a;
border-color: #137c21;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.myButton:active {
position: relative;
top: 1px;
background: linear-gradient(to bottom, #3ba052 5%, #4aa62b 100%);
background-color: #3ba052;
border-color: #0f5c18;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
}
/* Set default font for the entire site */
body {
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Test class to verify font loading */
.font-test {
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 24px;
color: red;
}
/* Dynamic Section Styles */
.content__entry {
position: relative;
padding: 20px;
min-height: 200px;
margin: 0 auto;
max-width: 1200px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #fff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.section-hero--full {
width: auto;
position: relative;
left: 0;
transform: none;
margin: 0 auto;
max-width: 1200px;
min-height: 400px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #fff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
@media (max-width: 768px) {
.section-hero--full {
width: 100vw;
left: 50%;
transform: translateX(-50%);
margin: 0;
padding: 0;
min-height: 300px;
}
.section-hero__content {
padding: 10px;
}
.section-hero__content h1 {
font-size: 1.5em;
margin-bottom: 0.75em;
padding-top: 0.75em;
}
.generic-content {
font-size: 0.9em;
max-width: 100%;
padding: 0 10px;
}
}
.section-hero__content {
position: relative;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
z-index: 1;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.section-hero--full[style*="background-image"] h1,
.section-hero--full[style*="background-image"] .generic-content {
color: #fff;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
.section-hero--full h1,
.section-hero--full .generic-content {
color: #333;
}
/* Override theme's heading font variable */
h1, h2, h3, h4, h5, h6 {
font-family: "LXGW WenKai TC", "Times New Roman", serif !important;
margin-bottom: 1.5em !important; /* Increased margin for taller spacing */
}
/* Ensure specific heading styles inherit the font */
.content__entry h1 {
font-size: 2em;
font-weight: 700;
line-height: 1.2;
color: #333;
margin-bottom: 1.5em !important; /* Taller margin */
padding-top: 1em;
text-align: center;
text-shadow: none;
font-family: "LXGW WenKai TC", "Times New Roman", serif !important;
}
.generic-content {
text-align: center;
margin: 0 auto;
max-width: 800px;
font-size: 1em;
line-height: 1.6;
color: #333;
margin-bottom: 1em;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry[style*="background-image"] h1,
.content__entry[style*="background-image"] .generic-content {
color: #fff;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
.generic-content p {
margin: 0 0 1em 0;
}
.generic-content ul,
.generic-content ol {
margin: 0 0 1em 0;
padding: 0 !important;
list-style: none !important;
}
.generic-content li {
margin-bottom: 0.5em;
text-align: center;
list-style: none !important;
}
.generic-content ul[style*="list-style"],
.generic-content ol[style*="list-style"],
.generic-content li[style*="list-style"] {
list-style: none !important;
}
.content__buttons {
text-align: center !important;
margin: 2em 0 1em 0;
}
.content__buttons a.myButton {
display: inline-block;
margin: 0 auto;
}
.content__entry .content__buttons {
text-align: center !important;
}
.welcome-image {
max-width: 100%;
height: auto;
margin: 1em auto;
display: block;
border-radius: 8px; /* Added for rounded corners */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Added for light shadow */
}
.video-embed {
position: relative;
padding-bottom: 56.25%;
height: 0;
overflow: hidden;
margin: 1em auto;
max-width: 800px;
background: none;
}
.video-embed iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
.separator {
text-align: center;
margin: 60px 0 20px 0;
}
/* Remove min-height and top spacing from the first content__entry--full */
.content__entry.content__entry--full:first-child {
min-height: 0 !important;
padding-top: 0 !important;
margin-top: 0 !important;
}
/* Adjust margin-top to close gap on PC view with maximum specificity */
.main.page .main__right:first-child {
margin-top: -3.8rem !important;
margin-top: -3.8rem !important; /* Redundant !important for priority */
}
/* Remove extra padding on right scrolling frame with maximum specificity */
.main.page .main__right {
margin: 0% !important;
margin: 0% !important; /* Redundant !important for priority */
}
/* Target the gap-causing class (.banner--after-content) */
.banner--after-content {
margin: 0 !important;
margin: 0 !important; /* Redundant !important for priority */
padding: 0 !important;
padding: 0 !important; /* Redundant !important for priority */
border: none !important;
border: none !important; /* Redundant !important for priority */
outline: none !important;
outline: none !important; /* Redundant !important for priority */
}
/* Target .top__item--right to remove the top line */
.top__item--right {
border: none !important;
border: none !important; /* Redundant !important for priority */
outline: none !important;
outline: none !important; /* Redundant !important for priority */
box-shadow: none !important;
box-shadow: none !important; /* Redundant !important for priority */
}
/* Reset and adjust spacing for mobile view with maximum specificity */
@media (max-width: 768px) {
.main.page .main__right:first-child {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
/* Target potential parent containers in mobile view */
.main.page .container:first-child,
.main.page .post__entry:first-child {
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
.main.page .main__right .main__right--bottom:first-child {
margin-top: -3.8rem !important;
margin-top: -3.8rem !important; /* Redundant !important for priority */
margin-bottom: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
.main.page .container > .main__right > .main__right--bottom:first-child,
.main.page .post__entry > .main__right > .main__right--bottom:first-child {
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
/* Target the gap-causing class (.banner--after-content) in mobile view */
.banner--after-content {
margin: 0 !important;
margin: 0 !important; /* Redundant !important for priority */
padding: 0 !important;
padding: 0 !important; /* Redundant !important for priority */
border: none !important;
border: none !important; /* Redundant !important for priority */
outline: none !important;
outline: none !important; /* Redundant !important for priority */
}
/* Target .top__item--right in mobile view */
.top__item--right {
border: none !important;
border: none !important; /* Redundant !important for priority */
outline: none !important;
outline: none !important; /* Redundant !important for priority */
box-shadow: none !important;
box-shadow: none !important; /* Redundant !important for priority */
}
}
/* Intermediate width range (e.g., 768px to 1023px) to fix centering */
@media (min-width: 769px) and (max-width: 1023px) {
.main.page .main__right {
margin: 0 auto !important;
margin: 0 auto !important; /* Redundant !important for priority */
max-width: 90% !important;
max-width: 90% !important; /* Redundant !important for priority */
width: auto !important;
width: auto !important; /* Redundant !important for priority */
}
.main.page .main__right .content__entry--full {
margin: 0 auto !important;
margin: 0 auto !important; /* Redundant !important for priority */
max-width: 100% !important;
max-width: 100% !important; /* Redundant !important for priority */
}
.main.page .main__right .main__right--bottom {
margin: 0 auto !important;
margin: 0 auto !important; /* Redundant !important for priority */
max-width: 100% !important;
max-width: 100% !important; /* Redundant !important for priority */
}
/* Target .top__item--right in intermediate range */
.top__item--right {
border: none !important;
border: none !important; /* Redundant !important for priority */
outline: none !important;
outline: none !important; /* Redundant !important for priority */
box-shadow: none !important;
box-shadow: none !important; /* Redundant !important for priority */
}
}
/* Ensure first section-hero--full has no extra top margin */
.main.page .main__right .main__right--bottom .section-hero--full:first-child {
margin-top: 0 !important;
padding-top: 0 !important;
}
/* Remove top margin from the first separator within content__entry--full */
.content__entry.content__entry--full .separator:first-child {
margin-top: 0;
}
.section-hero--full:not([style*="background-image"]) + .separator {
margin-top: 40px;
}
.separator-image {
max-width: 100%;
height: auto;
display: block;
margin: 0 auto;
}
.separator img[src$="down_arrow.png"] {
max-width: 256px;
}
hr {
display: none !important;
visibility: hidden !important;
}
.post__content hr,
.container hr,
.post__content hr[style],
.container hr[style] {
display: none !important;
visibility: hidden !important;
}
.post__content::before,
.post__content::after,
.container::before,
.container::after,
.post__entry::before,
.post__entry::after,
.content__entry::before,
.content__entry::after,
.generic-content::before,
.generic-content::after {
display: none !important;
border: none !important;
content: none !important;
}
.separator::before,
.separator::after {
display: none !important;
border: none !important;
content: none !important;
}
body,
body p,
body h2,
body h3,
body h4,
body h5,
body h6,
.post__content,
.post__content p,
.post__content h2,
.post__content h3,
.post__content h4,
.post__content h5,
.post__content h6,
.container,
.container p,
.container h2,
.container h3,
.container h4,
.container h5,
.container h6 {
color: #333 !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
h1.post__title,
h1.hero__title,
h1.site__title {
color: #fff !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
a.button,
a.btn,
a.post__button,
.post__content a.button,
.post__content a.btn,
.post__content a.post__button,
.container a.button,
.container a.btn,
.container a.post__button {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Custom Modal Styles */
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
background-color: #fff;
margin: 5% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 800px;
min-height: 200px;
position: relative;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
}
.modal-close {
color: #aaa;
position: absolute;
top: 10px;
right: 20px;
font-size: 28px;
font-weight: bold;
cursor: pointer;
transition: color 0.3s ease;
z-index: 1001;
}
.modal-close:hover,
.modal-close:focus {
color: #000;
text-decoration: none;
}
#modal-body {
font-size: 1em;
line-height: 1.6;
color: #333;
max-width: 100%;
box-sizing: border-box;
padding-top: 40px;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
#modal-body h1 {
font-size: 1.5em;
margin-bottom: 0.5em;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
#modal-body p {
margin-bottom: 1em;
}
#modal-body * {
max-width: 100%;
box-sizing: border-box;
}
#modal-body img,
#modal-body div,
#modal-body table {
max-width: 100%;
height: auto;
}
#modal-body .welcome-image {
border-radius: 8px; /* Ensure rounded corners in mobile */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Ensure light shadow in mobile */
}
.modal[aria-hidden="false"] {
display: block;
}
.modal-close:focus {
outline: 2px solid #44c767;
outline-offset: 2px;
}
/* Custom separator for modal sections */
.modal-section-separator {
text-align: center;
margin: 20px 0;
font-size: 24px;
line-height: 1;
color: #666;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.modal-section-separator::before {
content: "···";
}
/* Chaplaincy Admin specific overrides */
.report-container {
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry {
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
box-sizing: border-box !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry table.report-table {
width: 100% !important;
margin: 0 !important;
padding: 0 !important;
border-collapse: collapse !important;
box-sizing: border-box !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.top__item--right { border: none !important; outline: none !important; box-shadow: none !important; } with redundant !important to target the line, applied globally and in @media (max-width: 768px) and @media (min-width: 769px) and (max-width: 1023px)..main__right, .content__entry--full, and .main__right--bottom..banner--after-content rules and margin-top: -3.8rem adjustments./* Custom CSS for NLT Chaplaincy CMS - Version 3.6 */.custom.css is in /Web/nlhcm/public/assets/css/custom.css.custom.css loads with a 200 status..top__item--right shows border: none !important and check if the line disappears.custom.css and follow troubleshooting steps.https://www.nlt-chaplaincy.org/index.php and https://www.nlt-chaplaincy.org/stories.php at 08:00 PM HKT on Monday, August 11, 2025..top__item--right showing border: none !important..main__right remains centered..section-hero--full.index.php and test all views..welcome-image, .myButton, and .myButtonBig styles..top__item--right or the element with the line, and let me know its exact location (e.g., header, top-right)..top__item--right likely resides in the navbar partial or theme header, contributing the line.The file management plan remains available for your review.
custom.css), the background image is being compressed (outside the red box), and you’d prefer to maintain its original aspect ratio. Additionally, the illustration image (inside the red box) appears too wide, and you’d like more margin on the sides, with conservative adjustments to also affect modal images. Let’s adjust the CSS to address these concerns while keeping changes balanced.background-size: 100% 100% stretches the image to fill both width and height, distorting the aspect ratio and causing compression (as seen outside the red box).background-size: cover (which maintains the aspect ratio while covering the container) or contain (which fits the image within the container without cropping), but cover is better for full-width coverage without white spaces..welcome-image within a .content-image or .section-hero__content div, constrained by max-width: 100% but possibly stretched due to the container’s width.max-width less than 100% and adjusting padding or margins..modal-story-content .content-image), we’ll limit the width reduction and ensure it applies consistently across contexts.We’ll update custom.css to:
background-size: 100% 100% to cover for background images to preserve aspect ratio.max-width to 80% (conservative) and add padding to the container for side margins.custom.css (V4.9)/* Custom CSS for Lifenavi (navi.claudioflute.live) and Chaplaincy Admin (admin.nlt-chaplaincy.org) - Version 4.9 */
/* Shared styles for both systems, with domain-specific overrides as noted */
/* Ensure myButton overrides theme styles */
.content__buttons a.myButton {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
a.myButtonBig {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Button Styles */
.myButtonBig {
background: linear-gradient(to bottom, #44c767 5%, #5cbf2a 100%);
background-color: #44c767;
border-radius: 28px;
border: 1px solid #18ab29;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 21px;
font-weight: bold;
padding: 24px 42px;
text-decoration: none;
text-shadow: 0px 1px 0px #2f6627;
transition: all 0.3s ease;
}
.myButtonBig:hover {
background: linear-gradient(to bottom, #5cbf2a 5%, #44c767 100%);
background-color: #5cbf2a;
border-color: #137c21;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.myButtonBig:active {
position: relative;
top: 1px;
background: linear-gradient(to bottom, #3ba052 5%, #4aa62b 100%);
background-color: #3ba052;
border-color: #0f5c18;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
}
.myButton {
background: linear-gradient(to bottom, #44c767 5%, #5cbf2a 100%);
background-color: #44c767;
border-radius: 28px;
border: 1px solid #18ab29;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 17px;
font-weight: bold;
padding: 16px 31px;
text-decoration: none;
text-shadow: 0px 1px 0px #2f6627;
transition: all 0.3s ease;
}
.myButton:hover {
background: linear-gradient(to bottom, #5cbf2a 5%, #44c767 100%);
background-color: #5cbf2a;
border-color: #137c21;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.myButton:active {
position: relative;
top: 1px;
background: linear-gradient(to bottom, #3ba052 5%, #4aa62b 100%);
background-color: #3ba052;
border-color: #0f5c18;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
}
/* Set default font for the entire site */
body {
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Test class to verify font loading */
.font-test {
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 24px;
color: red;
}
/* Dynamic Section Styles */
.content__entry {
position: relative;
padding: 20px;
min-height: 200px;
margin: 0 auto;
max-width: 1200px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #fff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Hide empty content__entry div from Publii theme */
div.content__entry:empty {
display: none;
}
/* Alternative: Hide content__entry div on dynamic pages (uncomment and add data-page-type="dynamic" to <body> if needed) */
/* body[data-page-type="dynamic"] div.content__entry {
display: none;
} */
/* Enhanced Background Image Styles */
.section-hero--full[style*="background-image"],
.section-group[style*="background-image"] {
width: 100% !important; /* Enforce full width of the container */
max-width: none !important; /* Remove max-width constraint */
margin-left: 0 !important;
margin-right: 0 !important;
background-size: cover !important; /* Preserve aspect ratio, cover the area */
background-position: center !important;
background-repeat: no-repeat !important;
}
.section-hero--full[style*="background-image"] .section-hero__content,
.section-group[style*="background-image"] .section-hero__content {
background: none !important; /* Ensure content area doesn’t obscure background */
}
/* Responsive Adjustments */
@media (max-width: 768px) {
.section-hero--full[style*="background-image"] {
width: 100vw !important; /* Full viewport width on mobile */
left: 50% !important;
transform: translateX(-50%) !important;
margin: 0 !important;
padding: 0 !important;
min-height: 300px;
background-size: cover !important; /* Preserve aspect ratio on mobile */
}
.section-group[style*="background-image"] {
width: 100vw !important; /* Full viewport width on mobile */
margin: 0 !important;
padding: 0 !important;
background-size: cover !important; /* Preserve aspect ratio on mobile */
}
}
/* Illustration Image Adjustments */
.content-image,
.modal-story-content .content-image {
padding: 0 10px; /* Add conservative side margins */
max-width: 80%; /* Reduce width to leave more margin, conservative adjustment */
margin: 1em auto; /* Center with margins */
}
.welcome-image {
max-width: 100%; /* Ensure image respects container width */
height: auto;
margin: 0 auto; /* Center within content-image */
display: block;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
/* Ensure content is visible over background */
.section-hero--full[style*="background-image"] h1,
.section-hero--full[style*="background-image"] .generic-content,
.section-group[style*="background-image"] h1,
.section-group[style*="background-image"] .generic-content {
color: #fff;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
.section-hero--full h1,
.section-hero--column h1,
.section-hero--full .generic-content,
.section-hero--column .generic-content {
color: #333;
}
.section-hero--full {
width: auto;
position: relative;
left: 0;
transform: none;
margin: 0 auto;
max-width: 1200px;
min-height: 400px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #fff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.section-hero--column {
flex: 1;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
padding: 10px;
}
.section-group {
display: flex;
flex-wrap: nowrap; /* Prevent wrapping to new rows */
gap: 20px;
max-width: 1200px;
margin: 0 auto;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.layout-2-column {
display: flex;
justify-content: space-between;
}
.layout-2-column .section-hero--column {
flex: 1 0 49%; /* Slightly less than 50% to account for gap */
max-width: 49%;
}
.layout-3-column {
display: flex;
justify-content: space-between;
}
.layout-3-column .section-hero--column {
flex: 1 0 32%; /* Slightly less than 33.33% to account for gap */
max-width: 32%;
}
@media (max-width: 768px) {
.section-hero--full {
width: 100vw;
left: 50%;
transform: translateX(-50%);
margin: 0;
padding: 0;
min-height: 300px;
}
.section-hero--column {
flex: 1 0 100%;
max-width: 100%;
margin-bottom: 20px;
}
.section-group {
flex-wrap: wrap; /* Allow wrapping on mobile */
}
.section-hero__content {
padding: 10px;
}
.section-hero__content h1 {
font-size: 1.5em;
margin-bottom: 0.75em;
padding-top: 0.75em;
}
.generic-content {
font-size: 0.9em;
max-width: 100%;
padding: 0 10px;
}
}
.section-hero__content {
position: relative;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
z-index: 1;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Alignment Classes */
.align-left {
text-align: left;
}
.content-image.align-left, .video-embed.align-left {
margin: 1em 0;
}
.align-center {
text-align: center;
}
/* Override theme's heading font variable */
h1, h2, h3, h4, h5, h6 {
font-family: "LXGW WenKai TC", "Times New Roman", serif !important;
margin-bottom: 1.5em !important;
}
/* Ensure specific heading styles inherit the font */
.content__entry h1 {
font-size: 2em;
font-weight: 700;
line-height: 1.2;
color: #333;
margin-bottom: 1.5em !important;
padding-top: 1em;
text-align: center;
text-shadow: none;
font-family: "LXGW WenKai TC", "Times New Roman", serif !important;
}
.generic-content {
margin: 0 auto;
max-width: 800px;
font-size: 1em;
line-height: 1.6;
color: #333;
margin-bottom: 1em;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry[style*="background-image"] h1,
.content__entry[style*="background-image"] .generic-content {
color: #fff;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
.generic-content p {
margin: 0 0 1em 0;
}
.generic-content ul,
.generic-content ol {
margin: 0 0 1em 0;
padding: 0 !important;
list-style: none !important;
}
.generic-content li {
margin-bottom: 0.5em;
text-align: inherit;
list-style: none !important;
}
.generic-content ul[style*="list-style"],
.generic-content ol[style*="list-style"],
.generic-content li[style*="list-style"] {
list-style: none !important;
}
.content__buttons {
text-align: center !important;
margin: 2em 0 1em 0;
}
.content__buttons a.myButton {
display: inline-block;
margin: 0 auto;
}
.content__entry .content__buttons {
text-align: center !important;
}
.welcome-image {
max-width: 100%; /* Ensure image respects container width */
height: auto;
margin: 0 auto; /* Center within content-image */
display: block;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.video-embed {
position: relative;
padding-bottom: 56.25%;
height: 0;
overflow: hidden;
margin: 1em auto;
max-width: 800px;
background: none;
}
.video-embed iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
.separator {
text-align: center;
margin: 60px 0 20px 0;
}
.content__entry.content__entry--full:first-child {
min-height: 0 !important;
padding-top: 0 !important;
margin-top: 0 !important;
}
.main.page .main__right:first-child {
margin-top: -3.8rem !important;
}
.main.page .main__right {
margin: 0% !important;
}
.banner--after-content {
margin: 0 !important;
padding: 0 !important;
border: none !important;
outline: none !important;
}
.top__item--right {
border: none !important;
outline: none !important;
box-shadow: none !important;
}
@media (max-width: 768px) {
.main.page .main__right:first-child {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
.main.page .container:first-child,
.main.page .post__entry:first-child {
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
.main.page .main__right .main__right--bottom:first-child {
margin-top: -3.8rem !important;
margin-bottom: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
.main.page .container > .main__right > .main__right--bottom:first-child,
.main.page .post__entry > .main__right > .main__right--bottom:first-child {
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
.banner--after-content {
margin: 0 !important;
padding: 0 !important;
border: none !important;
outline: none !important;
}
.top__item--right {
border: none !important;
outline: none !important;
box-shadow: none !important;
}
}
@media (min-width: 769px) and (max-width: 1023px) {
.main.page .main__right {
margin: 0 auto !important;
max-width: 90% !important;
width: auto !important;
}
.main.page .main__right .content__entry--full {
margin: 0 auto !important;
max-width: 100% !important;
}
.main.page .main__right .main__right--bottom {
margin: 0 auto !important;
max-width: 100% !important;
}
.top__item--right {
border: none !important;
outline: none !important;
box-shadow: none !important;
}
}
.main.page .main__right .main__right--bottom .section-hero--full:first-child {
margin-top: 0 !important;
padding-top: 0 !important;
}
.content__entry.content__entry--full .separator:first-child {
margin-top: 0;
}
.section-hero--full:not([style*="background-image"]) + .separator {
margin-top: 40px;
}
.separator-image {
max-width: 100%;
height: auto;
display: block;
margin: 0 auto;
}
.separator img[src$="down_arrow.png"] {
max-width: 256px;
}
hr {
display: none !important;
visibility: hidden !important;
}
.post__content hr,
.container hr,
.post__content hr[style],
.container hr[style] {
display: none !important;
visibility: hidden !important;
}
.post__content::before,
.post__content::after,
.container::before,
.container::after,
.post__entry::before,
.post__entry::after,
.content__entry::before,
.content__entry::after,
.generic-content::before,
.generic-content::after {
display: none !important;
border: none !important;
content: none !important;
}
.separator::before,
.separator::after {
display: none !important;
border: none !important;
content: none !important;
}
body,
body p,
body h2,
body h3,
body h4,
body h5,
body h6,
.post__content,
.post__content p,
.post__content h2,
.post__content h3,
.post__content h4,
.post__content h5,
.post__content h6,
.container,
.container p,
.container h2,
.container h3,
.container h4,
.container h5,
.container h6 {
color: #333 !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
h1.post__title,
h1.hero__title,
h1.site__title {
color: #fff !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
a.button,
a.btn,
a.post__button,
.post__content a.button,
.post__content a.btn,
.post__content a.post__button,
.container a.button,
.container a.btn,
.container a.post__button {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Custom Modal Styles */
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
background-color: #fff;
margin: 5% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 800px;
min-height: 200px;
position: relative;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
}
.modal-close {
color: #aaa;
position: absolute;
top: 10px;
right: 20px;
font-size: 28px;
font-weight: bold;
cursor: pointer;
transition: color 0.3s ease;
z-index: 1001;
}
.modal-close:hover,
.modal-close:focus {
color: #000;
text-decoration: none;
}
#modal-body {
font-size: 1em;
line-height: 1.6;
color: #333;
max-width: 100%;
box-sizing: border-box;
padding-top: 40px;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
overflow-x: hidden;
}
#modal-body h1 {
font-size: 1.5em;
margin-bottom: 0.5em;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
#modal-body p {
margin-bottom: 1em;
}
#modal-body * {
max-width: 100%;
height: auto;
box-sizing: border-box;
}
#modal-body img,
#modal-body div,
#modal-body table {
max-width: 100%;
height: auto;
}
#modal-body .welcome-image {
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.modal[aria-hidden="false"] {
display: block;
}
.modal-close:focus {
outline: 2px solid #44c767;
outline-offset: 2px;
}
/* Custom separator for modal sections */
.modal-section-separator {
text-align: center;
margin: 20px 0;
font-size: 24px;
line-height: 1;
color: #666;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.modal-section-separator::before {
content: "···";
}
/* Modal-specific content container */
.modal-story-content {
max-width: 100%;
margin: 0 auto;
padding: 20px;
box-sizing: border-box;
overflow-x: hidden;
}
.modal-story-content h1 {
font-size: 2rem;
margin-bottom: 1rem;
text-align: center;
}
.modal-story-content .content-image {
padding: 0 10px; /* Add conservative side margins */
max-width: 80%; /* Reduce width to leave more margin, conservative adjustment */
margin: 1em auto; /* Center with margins */
}
.modal-story-content .generic-content {
font-size: 1rem;
line-height: 1.6;
}
/* Chaplaincy Admin specific overrides */
.report-container {
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry {
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
box-sizing: border-box !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry table.report-table {
width: 100% !important;
margin: 0 !important;
padding: 0 !important;
border-collapse: collapse !important;
box-sizing: border-box !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Ensure background image applies to the section */
.section-hero--full[style*="background-image"] .section-hero__content,
.section-group[style*="background-image"] .section-hero__content {
background: none;
}
custom.css V4.9background-size: 100% 100% to cover in .section-hero--full[style*="background-image"] and .section-group[style*="background-image"] to preserve the original aspect ratio while ensuring the image covers the container, minimizing white spaces.width: 100% !important and max-width: none !important to maintain full width coverage..content-image and .modal-story-content .content-image with:max-width: 80% (down from 100%) to reduce width and leave more side margins.padding: 0 10px to add conservative side spacing.margin: 1em auto to center the image with consistent margins..welcome-image retains max-width: 100% to respect the container’s new width, avoiding further stretching.max-width: 80% and padding: 0 10px to .modal-story-content .content-image for conservative alignment with main content.pull-contents.php: The image application logic remains unaffected; only CSS is modified.custom.css with V4.9.pull-contents.php as V2.39 (no changes required).https://navi.claudioflute.live/public/?page=post-list)..modal-trigger button) with an image.cover may crop the image vertically if the aspect ratio doesn’t match the container. If white spaces reappear, we can try contain with width: 100vw and adjust positioning—let me know if needed.padding: 0 20px)—please specify.Please deploy and test, and let me know the results!

custom.css) didn’t fully resolve the issue. The background image is still being compressed (outside the red box), and the illustration image (inside the red box) remains too wide with insufficient side margins. Let’s refine the solution to ensure the background image preserves its original aspect ratio while filling the width, and adjust the illustration image with more conservative margins that also apply to modals.background-size: cover in V4.9 maintains the aspect ratio but may still cause compression or cropping if the image’s dimensions don’t align with the container’s aspect ratio. This is evident outside the red box.background-size: contain to fit the image within the container while preserving its aspect ratio, though this might reintroduce white spaces. Alternatively, we can combine cover with adjustments to ensure minimal distortion..welcome-image within .content-image, is set to max-width: 80% with padding: 0 10px. This reduction from 100% is still too wide for your preference, suggesting a need for a slightly narrower width (e.g., 70%) and increased padding (e.g., 20px) for more side margins..modal-story-content .content-image to maintain consistency, keeping the adjustment subtle to avoid disrupting modal layouts.We’ll update custom.css to:
background-size: cover to contain for background images to avoid compression while preserving aspect ratio, with width: 100vw to maximize width coverage.max-width to 70% and increase padding to 20px for more side margins.custom.css (V4.10)/* Custom CSS for Lifenavi (navi.claudioflute.live) and Chaplaincy Admin (admin.nlt-chaplaincy.org) - Version 4.10 */
/* Shared styles for both systems, with domain-specific overrides as noted */
/* Ensure myButton overrides theme styles */
.content__buttons a.myButton {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
a.myButtonBig {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Button Styles */
.myButtonBig {
background: linear-gradient(to bottom, #44c767 5%, #5cbf2a 100%);
background-color: #44c767;
border-radius: 28px;
border: 1px solid #18ab29;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 21px;
font-weight: bold;
padding: 24px 42px;
text-decoration: none;
text-shadow: 0px 1px 0px #2f6627;
transition: all 0.3s ease;
}
.myButtonBig:hover {
background: linear-gradient(to bottom, #5cbf2a 5%, #44c767 100%);
background-color: #5cbf2a;
border-color: #137c21;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.myButtonBig:active {
position: relative;
top: 1px;
background: linear-gradient(to bottom, #3ba052 5%, #4aa62b 100%);
background-color: #3ba052;
border-color: #0f5c18;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
}
.myButton {
background: linear-gradient(to bottom, #44c767 5%, #5cbf2a 100%);
background-color: #44c767;
border-radius: 28px;
border: 1px solid #18ab29;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 17px;
font-weight: bold;
padding: 16px 31px;
text-decoration: none;
text-shadow: 0px 1px 0px #2f6627;
transition: all 0.3s ease;
}
.myButton:hover {
background: linear-gradient(to bottom, #5cbf2a 5%, #44c767 100%);
background-color: #5cbf2a;
border-color: #137c21;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.myButton:active {
position: relative;
top: 1px;
background: linear-gradient(to bottom, #3ba052 5%, #4aa62b 100%);
background-color: #3ba052;
border-color: #0f5c18;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
}
/* Set default font for the entire site */
body {
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Test class to verify font loading */
.font-test {
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 24px;
color: red;
}
/* Dynamic Section Styles */
.content__entry {
position: relative;
padding: 20px;
min-height: 200px;
margin: 0 auto;
max-width: 1200px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #fff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Hide empty content__entry div from Publii theme */
div.content__entry:empty {
display: none;
}
/* Alternative: Hide content__entry div on dynamic pages (uncomment and add data-page-type="dynamic" to <body> if needed) */
/* body[data-page-type="dynamic"] div.content__entry {
display: none;
} */
/* Enhanced Background Image Styles */
.section-hero--full[style*="background-image"],
.section-group[style*="background-image"] {
width: 100vw !important; /* Use viewport width to maximize coverage */
max-width: none !important; /* Remove max-width constraint */
margin-left: 50% !important;
margin-right: -50vw !important;
transform: translateX(-50%) !important; /* Center the extended width */
background-size: contain !important; /* Preserve aspect ratio, fit within container */
background-position: center !important;
background-repeat: no-repeat !important;
}
.section-hero--full[style*="background-image"] .section-hero__content,
.section-group[style*="background-image"] .section-hero__content {
background: none !important; /* Ensure content area doesn’t obscure background */
}
/* Responsive Adjustments */
@media (max-width: 768px) {
.section-hero--full[style*="background-image"] {
width: 100vw !important; /* Full viewport width on mobile */
left: 50% !important;
transform: translateX(-50%) !important;
margin: 0 !important;
padding: 0 !important;
min-height: 300px;
background-size: contain !important; /* Preserve aspect ratio on mobile */
}
.section-group[style*="background-image"] {
width: 100vw !important; /* Full viewport width on mobile */
margin: 0 !important;
padding: 0 !important;
background-size: contain !important; /* Preserve aspect ratio on mobile */
}
}
/* Illustration Image Adjustments */
.content-image,
.modal-story-content .content-image {
padding: 0 20px; /* Increase side margins to 20px for more space */
max-width: 70%; /* Reduce width to 70% for more margin, conservative adjustment */
margin: 1em auto; /* Center with margins */
}
.welcome-image {
max-width: 100%; /* Ensure image respects container width */
height: auto;
margin: 0 auto; /* Center within content-image */
display: block;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
/* Ensure content is visible over background */
.section-hero--full[style*="background-image"] h1,
.section-hero--full[style*="background-image"] .generic-content,
.section-group[style*="background-image"] h1,
.section-group[style*="background-image"] .generic-content {
color: #fff;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
.section-hero--full h1,
.section-hero--column h1,
.section-hero--full .generic-content,
.section-hero--column .generic-content {
color: #333;
}
.section-hero--full {
width: auto;
position: relative;
left: 0;
transform: none;
margin: 0 auto;
max-width: 1200px;
min-height: 400px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #fff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.section-hero--column {
flex: 1;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
padding: 10px;
}
.section-group {
display: flex;
flex-wrap: nowrap; /* Prevent wrapping to new rows */
gap: 20px;
max-width: 1200px;
margin: 0 auto;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.layout-2-column {
display: flex;
justify-content: space-between;
}
.layout-2-column .section-hero--column {
flex: 1 0 49%; /* Slightly less than 50% to account for gap */
max-width: 49%;
}
.layout-3-column {
display: flex;
justify-content: space-between;
}
.layout-3-column .section-hero--column {
flex: 1 0 32%; /* Slightly less than 33.33% to account for gap */
max-width: 32%;
}
@media (max-width: 768px) {
.section-hero--full {
width: 100vw;
left: 50%;
transform: translateX(-50%);
margin: 0;
padding: 0;
min-height: 300px;
}
.section-hero--column {
flex: 1 0 100%;
max-width: 100%;
margin-bottom: 20px;
}
.section-group {
flex-wrap: wrap; /* Allow wrapping on mobile */
}
.section-hero__content {
padding: 10px;
}
.section-hero__content h1 {
font-size: 1.5em;
margin-bottom: 0.75em;
padding-top: 0.75em;
}
.generic-content {
font-size: 0.9em;
max-width: 100%;
padding: 0 10px;
}
}
.section-hero__content {
position: relative;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
z-index: 1;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Alignment Classes */
.align-left {
text-align: left;
}
.content-image.align-left, .video-embed.align-left {
margin: 1em 0;
}
.align-center {
text-align: center;
}
/* Override theme's heading font variable */
h1, h2, h3, h4, h5, h6 {
font-family: "LXGW WenKai TC", "Times New Roman", serif !important;
margin-bottom: 1.5em !important;
}
/* Ensure specific heading styles inherit the font */
.content__entry h1 {
font-size: 2em;
font-weight: 700;
line-height: 1.2;
color: #333;
margin-bottom: 1.5em !important;
padding-top: 1em;
text-align: center;
text-shadow: none;
font-family: "LXGW WenKai TC", "Times New Roman", serif !important;
}
.generic-content {
margin: 0 auto;
max-width: 800px;
font-size: 1em;
line-height: 1.6;
color: #333;
margin-bottom: 1em;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry[style*="background-image"] h1,
.content__entry[style*="background-image"] .generic-content {
color: #fff;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
.generic-content p {
margin: 0 0 1em 0;
}
.generic-content ul,
.generic-content ol {
margin: 0 0 1em 0;
padding: 0 !important;
list-style: none !important;
}
.generic-content li {
margin-bottom: 0.5em;
text-align: inherit;
list-style: none !important;
}
.generic-content ul[style*="list-style"],
.generic-content ol[style*="list-style"],
.generic-content li[style*="list-style"] {
list-style: none !important;
}
.content__buttons {
text-align: center !important;
margin: 2em 0 1em 0;
}
.content__buttons a.myButton {
display: inline-block;
margin: 0 auto;
}
.content__entry .content__buttons {
text-align: center !important;
}
.welcome-image {
max-width: 100%; /* Ensure image respects container width */
height: auto;
margin: 0 auto; /* Center within content-image */
display: block;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.video-embed {
position: relative;
padding-bottom: 56.25%;
height: 0;
overflow: hidden;
margin: 1em auto;
max-width: 800px;
background: none;
}
.video-embed iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
.separator {
text-align: center;
margin: 60px 0 20px 0;
}
.content__entry.content__entry--full:first-child {
min-height: 0 !important;
padding-top: 0 !important;
margin-top: 0 !important;
}
.main.page .main__right:first-child {
margin-top: -3.8rem !important;
}
.main.page .main__right {
margin: 0% !important;
}
.banner--after-content {
margin: 0 !important;
padding: 0 !important;
border: none !important;
outline: none !important;
}
.top__item--right {
border: none !important;
outline: none !important;
box-shadow: none !important;
}
@media (max-width: 768px) {
.main.page .main__right:first-child {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
.main.page .container:first-child,
.main.page .post__entry:first-child {
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
.main.page .main__right .main__right--bottom:first-child {
margin-top: -3.8rem !important;
margin-bottom: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
.main.page .container > .main__right > .main__right--bottom:first-child,
.main.page .post__entry > .main__right > .main__right--bottom:first-child {
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
.banner--after-content {
margin: 0 !important;
padding: 0 !important;
border: none !important;
outline: none !important;
}
.top__item--right {
border: none !important;
outline: none !important;
box-shadow: none !important;
}
}
@media (min-width: 769px) and (max-width: 1023px) {
.main.page .main__right {
margin: 0 auto !important;
max-width: 90% !important;
width: auto !important;
}
.main.page .main__right .content__entry--full {
margin: 0 auto !important;
max-width: 100% !important;
}
.main.page .main__right .main__right--bottom {
margin: 0 auto !important;
max-width: 100% !important;
}
.top__item--right {
border: none !important;
outline: none !important;
box-shadow: none !important;
}
}
.main.page .main__right .main__right--bottom .section-hero--full:first-child {
margin-top: 0 !important;
padding-top: 0 !important;
}
.content__entry.content__entry--full .separator:first-child {
margin-top: 0;
}
.section-hero--full:not([style*="background-image"]) + .separator {
margin-top: 40px;
}
.separator-image {
max-width: 100%;
height: auto;
display: block;
margin: 0 auto;
}
.separator img[src$="down_arrow.png"] {
max-width: 256px;
}
hr {
display: none !important;
visibility: hidden !important;
}
.post__content hr,
.container hr,
.post__content hr[style],
.container hr[style] {
display: none !important;
visibility: hidden !important;
}
.post__content::before,
.post__content::after,
.container::before,
.container::after,
.post__entry::before,
.post__entry::after,
.content__entry::before,
.content__entry::after,
.generic-content::before,
.generic-content::after {
display: none !important;
border: none !important;
content: none !important;
}
.separator::before,
.separator::after {
display: none !important;
border: none !important;
content: none !important;
}
body,
body p,
body h2,
body h3,
body h4,
body h5,
body h6,
.post__content,
.post__content p,
.post__content h2,
.post__content h3,
.post__content h4,
.post__content h5,
.post__content h6,
.container,
.container p,
.container h2,
.container h3,
.container h4,
.container h5,
.container h6 {
color: #333 !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
h1.post__title,
h1.hero__title,
h1.site__title {
color: #fff !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
a.button,
a.btn,
a.post__button,
.post__content a.button,
.post__content a.btn,
.post__content a.post__button,
.container a.button,
.container a.btn,
.container a.post__button {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Custom Modal Styles */
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
background-color: #fff;
margin: 5% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 800px;
min-height: 200px;
position: relative;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
}
.modal-close {
color: #aaa;
position: absolute;
top: 10px;
right: 20px;
font-size: 28px;
font-weight: bold;
cursor: pointer;
transition: color 0.3s ease;
z-index: 1001;
}
.modal-close:hover,
.modal-close:focus {
color: #000;
text-decoration: none;
}
#modal-body {
font-size: 1em;
line-height: 1.6;
color: #333;
max-width: 100%;
box-sizing: border-box;
padding-top: 40px;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
overflow-x: hidden;
}
#modal-body h1 {
font-size: 1.5em;
margin-bottom: 0.5em;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
#modal-body p {
margin-bottom: 1em;
}
#modal-body * {
max-width: 100%;
height: auto;
box-sizing: border-box;
}
#modal-body img,
#modal-body div,
#modal-body table {
max-width: 100%;
height: auto;
}
#modal-body .welcome-image {
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.modal[aria-hidden="false"] {
display: block;
}
.modal-close:focus {
outline: 2px solid #44c767;
outline-offset: 2px;
}
/* Custom separator for modal sections */
.modal-section-separator {
text-align: center;
margin: 20px 0;
font-size: 24px;
line-height: 1;
color: #666;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.modal-section-separator::before {
content: "···";
}
/* Modal-specific content container */
.modal-story-content {
max-width: 100%;
margin: 0 auto;
padding: 20px;
box-sizing: border-box;
overflow-x: hidden;
}
.modal-story-content h1 {
font-size: 2rem;
margin-bottom: 1rem;
text-align: center;
}
.modal-story-content .content-image {
padding: 0 20px; /* Increase side margins to 20px for more space */
max-width: 70%; /* Reduce width to 70% for more margin, conservative adjustment */
margin: 1em auto; /* Center with margins */
}
.modal-story-content .generic-content {
font-size: 1rem;
line-height: 1.6;
}
/* Chaplaincy Admin specific overrides */
.report-container {
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry {
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
box-sizing: border-box !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry table.report-table {
width: 100% !important;
margin: 0 !important;
padding: 0 !important;
border-collapse: collapse !important;
box-sizing: border-box !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Ensure background image applies to the section */
.section-hero--full[style*="background-image"] .section-hero__content,
.section-group[style*="background-image"] .section-hero__content {
background: none;
}
custom.css V4.10background-size: cover to contain in .section-hero--full[style*="background-image"] and .section-group[style*="background-image"] to preserve the original aspect ratio and avoid compression.width: 100vw !important with margin-left: 50% !important, margin-right: -50vw !important, and transform: translateX(-50%) !important to extend the container to the viewport width and center it, minimizing white spaces while fitting the image..content-image and .modal-story-content .content-image with:max-width: 70% (down from 80%) to further reduce width for more side margins.padding: 0 20px (up from 10px) to increase side spacing conservatively.margin: 1em auto to center the image with consistent margins..welcome-image retains max-width: 100% to respect the container’s new width.max-width: 70% and padding: 0 20px to .modal-story-content .content-image for a balanced effect.pull-contents.php: The image application logic remains unchanged; only CSS is adjusted.custom.css with V4.10.pull-contents.php as V2.39 (no changes required).https://navi.claudioflute.live/public/?page=post-list).contain may leave small gaps if the aspect ratio differs significantly)..modal-trigger button) with an image.contain preserves the aspect ratio but may leave white spaces if the image is narrower or taller than the container. If this is unacceptable, we can revert to cover with object-fit: cover (via inline styles if needed)—let me know your preference.Please deploy and test, and let me know the results!
custom.css aligns more closely with your intended effect. Since it’s already available in our earlier chat, I won’t regenerate it, and you can revert to that version as needed. I’ll respect your decision to pause further adjustments for now. If you’d like to revisit the background image compression, illustration margins, or the earlier emoji issue later, or if any new urgent tasks arise, feel free to let me know. It’s currently 12:54 PM HKT on Wednesday, August 20, 2025, so you have the afternoon to test or address other priorities. I’m here to assist whenever you’re ready!custom.css (V4.7), does not exhibit this issue. The fact that the scrollbar disappears on an actual phone screen for Chaplaincy Admin adds another layer to investigate. Let’s analyze the potential causes based on the information provided, the attached screenshot, and the shared CSS, and propose a solution.custom.css V4.7, suggesting the issue might stem from differences in HTML structure, base theme CSS, or content rather than the custom CSS alone.min-width, overflow-x) that trigger the scrollbar. The custom CSS overrides might not fully align across both sites.@media (max-width: 768px) rules in V4.7 might not fully account for all elements on Chaplaincy Admin, especially if Lifenavi has fewer or differently structured components.<meta name="viewport"> tag (e.g., missing width=device-width), it might not scale properly in narrow desktop windows, unlike on a phone where the browser handles it natively.pull-contents.php or other scripts (e.g., .section-hero--full, .section-group) might render differently due to varying data or styling overrides in Chaplaincy Admin.Since both sites share custom.css V4.7, the issue likely lies in Chaplaincy Admin’s unique HTML, theme, or content. Let’s address this by:
<head> section includes:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">header.php or equivalent template file. This ensures the page scales correctly in narrow desktop simulations.custom.css V4.7 (or create a Chaplaincy-specific override) to prevent horizontal overflow:
/* Add to custom.css or a Chaplaincy-specific file */
html, body {
overflow-x: hidden;
width: 100%;
margin: 0;
padding: 0;
}
.main.page, .container, .post__entry {
width: 100%;
max-width: 100%;
overflow-x: hidden;
}.welcome-image, .video-embed, or .section-group). .welcome-image {
max-width: 100%;
height: auto;
}
.content-image {
width: 100%;
overflow-x: hidden;
} .section-group {
flex-wrap: wrap;
width: 100%;
}
.section-hero--column {
flex: 1 0 100%;
max-width: 100%;
}@media (max-width: 768px) block in V4.7 to enforce wrapping and width limits:
@media (max-width: 768px) {
.section-hero--full, .section-group {
width: 100vw !important;
left: 50% !important;
transform: translateX(-50%) !important;
margin: 0 !important;
padding: 0 !important;
overflow-x: hidden;
}
.content__entry, .generic-content {
max-width: 100% !important;
padding: 0 10px;
}
}<meta name="viewport"> tag. Add or correct it if needed, then save the theme file.custom.css:
custom-chaplaincy.css file and link it after the shared CSS).web_content library idea or address other tasks.Please implement these changes and let me know the results or any specific elements from the screenshot that need targeting!
However, adding " " to the < head > alone didn't help.
/* Add to custom.css or a Chaplaincy-specific file */
html, body {
overflow-x: hidden;
width: 100%;
margin: 0;
padding: 0;
}
.main.page, .container, .post__entry {
width: 100%;
max-width: 100%;
overflow-x: hidden;
}
Another issue to bring up is we are currently adding PayPal subscription buttons to the website site. However, with the following code provided by PayPal, the button can be viewed from the Publii preview page but not from the dynamic index.php.
<div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div>
<script src="https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription" data-sdk-integration-source="button-factory"></script>
<script>
paypal.Buttons({
style: {
shape: 'pill',
color: 'gold',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
/* Creates the subscription */
plan_id: 'P-3FU48207V4555173AM5STYUA'
});
},
onApprove: function(data, actions) {
alert(data.subscriptionID); // You can add optional success message for the subscriber here
}
}).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA'); // Renders the PayPal button
</script>
I think it's because we've hidden the Publii theme content area when we were working to reduce the white gap on the top of the page in our previous discussions. Please see how we can show static content created in Publii and hide it when there is no static content.
Thank you for your inputs on the updated design. Below are my preferences. Please proceed with coding if you think they're good.I've added positions 100-104 to the "position" field to accommodate the PP sections. I think using three-digit numbers consistently looks better. For the "model" field, I've added "title-text-paypal" which looks clearer than my original proposal as user may confuse "button" with existing CTA buttons. For what you said "Rendering PP buttons on all pages", what I meant was if the PP sections are set to "landing" they should be shown on index.php. If they are set for "finance", then finance.php should display them when both inside a modal or direct-accessed. I was emphasizing that this is the existing logic for any dynamic sections so no change is needed.
Please treat other behaviors of PP sections the same as other sessions, such as CTA button rendering logic (hide in modal), "theme_img" handing, "chk_divider" handling etc. Attached is the source of the current V2.13 of pull-contents.php for your reference.
The code is now 697 lines long and is about right! There is one issue I've missed. Since the "content" field is using a HTML editor it will sanitize the PP button script. Do you think we can put the button code inside the "video_embed" field for it doesn't have a HTML editor? For "model", we can keep "title-text-paypal" unchanged but the rendering logic is basically the same as "title-text-video". We can also add a PayPal button field ("paypal_button") if it's necessary, for you may want to handle the codes differently for YouTube embed code and PP button code. What's your recommendation? Let's review the design first and leave coding for later.
Yup! Let's proceed with coding! Please pay attention to any special character handling in the formerly "video_embed" field (Now renamed to "code") and preserve it. I will do the schema change ("code", "code_type", new "model" option "title-text-code") via AppGini so no DB script is needed.
While the length is still 597 lines long the basic display of the website has been restored. However, all images have been missing in modals and PayPal dynamic sessions are not displayed (I think this is intentional). The page-top debug message is now:Debug: Calling file: 'index.php' Debug: REQUEST_URI: '/' Debug: Current page after str_replace: 'index' Debug: Current page set to 'landing' Debug: Final current_page: 'landing' Debug: Image Base Path: 'https://admin.nlt-chaplaincy.org/images/' Debug: Is modal request: No Debug: Fetched 9 sections for page 'landing'The modal debug message (Missing "image") Debug: Modal opened Debug: Fetch response status: 200 OK Debug: Fetched HTML length: 23478 Debug: Found 3 modal-story-content sections in fetched content Debug: Found 3 modal-story-content sections Debug: Modal openedPlease check if the image is not processed or the image path has been wrongly changed.
This fix has restored image display. However, the PP section is still missing. I've checked the section has chosen "landing" as the page, "PayPal" as code type, "100" as position and is set to "Show". The code put into the "code" field is:
<div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div>
<script src="https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription" data-sdk-integration-source="button-factory"></script>
<script>
paypal.Buttons({
style: {
shape: 'pill',
color: 'gold',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
/* Creates the subscription */
plan_id: 'P-3FU48207V4555173AM5STYUA'
});
},
onApprove: function(data, actions) {
alert(data.subscriptionID); // You can add optional success message for the subscriber here
}
}).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA'); // Renders the PayPal button
</script>
This has been tested in Publii as static content and verified working in the preview.
This fix doesn't solve the PP button display issue. I've tried re-generated the site using Publii. What's working in the preview now fails. PayPal button from the static block is not shown but the title of the static block is shown. I'm not sure if this is just a CSS issue that hide static button.
Thanks for the fix. Please remember to update the version number as we've been staying at 2.14 for very long. Let's also assume the number of lines is correct at 638 lines with the latest V2.14 fix. To help find out the issue, I've set the PP section to "title-text" temporarily. When position is set to "10" the section is displayed but when set to "100" the entire section is missing. While there are 11 "landing" sections in the database the debug message says "Debug: Fetched 10 sections for page 'landing'. Does this give more hints, like we've set the max. number of sections to 10 (Please take a look at our historical chats for reference)? Static PP buttons are still missing. For title, I was referring to the title I added in Publii, not title from the web_content dynamic section. A screenshot has been attached for clarity. The circled title is added in Publii, not from any dynamic section.
Debug: PayPal code for ID 58: <div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div> paypal.Buttons({ style: { shape: 'pill', color: 'gold', layout: 'vertical', label: 'subscribe' }, createSubscription: function(data, actions) { return actions.subscription.create({ /* Creates the subscription */ plan_id: 'P-3FU48207V4555173AM5STYUA' }); }, onApprove: function(data, actions) { alert(data.subscriptionID); // You can add optional success message for the subscriber here } }).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA'); // Renders the PayPal button//
The floating debug message layer says:
Debug: Modal script loaded
Debug: Found 7 modal triggers
Debug: Re-rendered PayPal button for ID 58
Thanks for the update. It was my typo to say "title-text-button". The option chosen was "title-text-code" as our design intended. The script I obtained from PP was:
···
···
As you can see it contain two pairs of < script > tag.With these additional info., does V2.15 (Actually it should be V2.16. According to our past protocol, you'll update the version number every time changes are introduced) still apply?
While you said "Since the SDK is already in the < head >", the PP-provided head code is actually:
<script src="https://www.paypal.com/sdk/js?client-id=BAA3CoIb4JoqOOk3pcQTP3qNktdZtHH6XivPxUlzpsk17UqgPBTbLfowLMyjT6OaRCP39w2Tkv6cEguw3I&components=hosted-buttons&disable-funding=venmo¤cy=HKD">
</script>
This is not the same as this script in the button code:
<script src="https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription" data-sdk-integration-source="button-factory"></script>
Does V2.16 correctly handle this?Please remember to confirm the fix strategy before generating code.
<head> script and the script embedded in the button code is a critical issue that needs to be addressed. Let’s confirm the fix strategy before generating the updated code.Current <head> SDK Script:
<script src="https://www.paypal.com/sdk/js?client-id=BAA3CoIb4JoqOOk3pcQTP3qNktdZtHH6XivPxUlzpsk17UqgPBTbLfowLMyjT6OaRCP39w2Tkv6cEguw3I&components=hosted-buttons&disable-funding=venmo¤cy=HKD">
</script>
client-id=BAA3CoIb4... with components=hosted-buttons, disable-funding=venmo, and currency=HKD.Button Code SDK Script:
<script src="https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription" data-sdk-integration-source="button-factory"></script>
client-id=AUNZIE2pdhV... with vault=true and intent=subscription.Discrepancy:
client-id values indicate these are likely for different PayPal accounts or applications.<head> script is configured for hosted buttons with specific funding and currency options, while the button code requires subscription functionality (vault=true and intent=subscription).To ensure V2.16 correctly handles this, let’s confirm the following strategy:
Unify SDK Loading:
<script> from the button code’s code field since it’s already in the <head>.<head> script to use the client-id=AUNZIE2pdhV... with vault=true and intent=subscription to match the button code’s requirements, as subscriptions are the intended functionality.<head> script with:
<script src="https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription" data-sdk-integration-source="button-factory"></script>Adjust PHP Logic:
paypal.Buttons(...)) from the code field, ignoring the SDK <script>.window.paypalCode for dynamic rendering.JavaScript Re-Rendering:
<head> SDK load.Version Update:
<head> script to match the button code’s SDK parameters (client-id=AUNZIE2pdhV..., vault=true, intent=subscription)? This assumes the button code’s configuration is the intended use case (subscriptions).<script> from the code field in the database, keeping only the <div> and button initialization <script>? This simplifies the dynamic rendering process.Please confirm or provide feedback on these steps. Once confirmed, I’ll generate the updated V2.16 code accordingly.
Do you agree with updating the < head > script...? With further checking, you're right that the two SDK scripts are conflicting with each other. The correct code to put in the < body> of the web page is:
<!-- Load PayPal SDK -->
<script src="https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription"></script>
<!-- PayPal Button Container -->
<div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div>
<!-- Render the Subscription Button -->
<script>
paypal.Buttons({
style: {
shape: 'pill',
color: 'gold',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
plan_id: 'P-3FU48207V4555173AM5STYUA'
});
},
onApprove: function(data, actions) {
alert("Subscription successful! ID: " + data.subscriptionID);
}
}).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA');
</script>
Are you okay with removing the SDK < script > from the code?
Provided Code:
<!-- Load PayPal SDK -->
<script src="https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription"></script>
<!-- PayPal Button Container -->
<div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div>
<!-- Render the Subscription Button -->
<script>
paypal.Buttons({
style: {
shape: 'pill',
color: 'gold',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
plan_id: 'P-3FU48207V4555173AM5STYUA'
});
},
onApprove: function(data, actions) {
alert("Subscription successful! ID: " + data.subscriptionID);
}
}).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA');
</script>
<body>, and no <head> script is needed.Previous Conflict:
<head> script (client-id=BAA3CoIb4...) and the button code’s SDK (client-id=AUNZIE2pdhV...) caused the issue. Removing the <head> script aligns with PayPal’s recommendation to load the SDK where the button is rendered.Current Issue:
<body>, we need to handle the full code field as a single unit, ensuring the SDK loads before the button script executes.Based on your input, let’s adjust the strategy:
Remove <head> Script:
<head> script (client-id=BAA3CoIb4...) from your HTML template, as it’s no longer needed.Handle Full <body> Block:
code field (including the SDK <script>, container, and button <script>) in window.paypalCode.<div> with the inner HTML, ensuring the SDK loads and the button renders in sequence.Dynamic Rendering:
document.body.appendChild to insert a <div> containing the full code content, allowing the browser to execute the scripts naturally.Version Update:
<head> script entirely? This aligns with your updated code, placing all PayPal logic in the <body>.code field? Based on your suggestion, yes, we’ll leave the SDK <script> in the code field to ensure the entire block is loaded dynamically in the <body>.Please confirm these adjustments. Once confirmed, I’ll generate the updated V2.16 code.
Before testing, I just want to check if the current handling of code block compatible with YouTube embed code?
Yes, please extend dynamic insertion. For YT embeds, we usually use sth. like this:
<iframe width="560" height="315" src="https://www.youtube.com/embed/1_7xSwEC71A?si=pUd70OsjPWunYFXe" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
This version is still not showing the button but a block of debug message:
`});
Debug: Embed code for ID 58: <div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div> <script src="https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription" data-sdk-integration-source="button-factory"></script> <script> paypal.Buttons({ style: { shape: 'pill', color: 'gold', layout: 'vertical', label: 'subscribe' }, createSubscription: function(data, actions) { return actions.subscription.create({ /* Creates the subscription */ plan_id: 'P-3FU48207V4555173AM5STYUA' }); }, onApprove: function(data, actions) { alert(data.subscriptionID); // You can add optional success message for the subscriber here } }).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA'); // Renders the PayPal button </script>
The floating layer shows: Debug: contentCode unavailable
And, I find the button code, which is like:
<div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div>
<script src="https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription" data-sdk-integration-source="button-factory"></script>
<script>
paypal.Buttons({
style: {
shape: 'pill',
color: 'gold',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
/* Creates the subscription */
plan_id: 'P-3FU48207V4555173AM5STYUA'
});
},
onApprove: function(data, actions) {
alert(data.subscriptionID); // You can add optional success message for the subscriber here
}
}).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA'); // Renders the PayPal button
</script>
Has been changed to:
<div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div>
[removed][removed]
[removed]
paypal.Buttons({
style: {
shape: 'pill',
color: 'gold',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
/* Creates the subscription */
plan_id: 'P-3FU48207V4555173AM5STYUA'
});
},
onApprove: function(data, actions) {
alert(data.subscriptionID); // You can add optional success message for the subscriber here
}
}).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA'); // Renders the PayPal button
[removed]
The code field is being modified by AppGini generated app upon saving, not by AppGini itself as it's a desktop app which won't deal with my data. I'm okay with reinserting the PP block directly in the database.
I've manually updated the database and confirm the "content" is not changed. However, this version still render the following in orange:
Debug: Embed code for ID 58 (PayPal): <div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div> <script src="https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription" data-sdk-integration-source="button-factory"></script> <script> paypal.Buttons({ style: { shape: 'pill', color: 'gold', layout: 'vertical', label: 'subscribe' }, createSubscription: function(data, actions) { return actions.subscription.create({ plan_id: 'P-3FU48207V4555173AM5STYUA' }); }, onApprove: function(data, actions) { alert(data.subscriptionID); } }).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA'); </script>
This version still fails. The floating debug message says: "Debug: Unsupported embed type or invalid code for ID 58" and the content is still:
Debug: Embed code for ID 58 (PayPal): <div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div> <script src="https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription" data-sdk-integration-source="button-factory"></script> <script> paypal.Buttons({ style: { shape: 'pill', color: 'gold', layout: 'vertical', label: 'subscribe' }, createSubscription: function(data, actions) { return actions.subscription.create({ plan_id: 'P-3FU48207V4555173AM5STYUA' }); }, onApprove: function(data, actions) { alert(data.subscriptionID); } }).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA'); </script>
The on-page content remains unchanged with direct-rendered text only. The floating debug messages have changed to:Debug: Inserted div for PayPal ID 58 Debug: Inserted PayPal SDK script for ID 58 Debug: PayPal SDK failed to load for ID 58 after 5s
Before confirmation, I want to know if the PP code is intended to be inserted into CMS, why it seems that it's difficult to get the button displayed? I think most CMS will be similar to ours to use database and save content in database fields.
code block (containing a <div>, an SDK <script>, and a button <script>) is intended to be dynamically inserted into the webpage to render an interactive "Subscribe" button. This block is typically provided by PayPal for integration and relies on:
<script> loading the PayPal JavaScript library.<script> initializing and rendering the button within the specified <div> once the SDK is available.code in a database field (e.g., web_content.code) and have the PHP/JavaScript logic render it on the frontend. This is a common approach for embedding third-party scripts (e.g., PayPal, YouTube) in CMS platforms like WordPress, Joomla, or custom AppGini-based systems.Several factors are contributing to the difficulty, which are not uncommon in CMS/database-driven setups:
Database Storage and Sanitization:
<script> tags when saving to the database, as you’ve observed with the [removed] placeholders. Even though you’ve manually restored the content, the initial save process highlights a limitation.code field might need to be configured as a "raw HTML" or "unsafe" field in the CMS to preserve scripts, which isn’t always the default.Dynamic Script Execution:
<script> tags via innerHTML or insertAdjacentHTML doesn’t automatically execute the scripts. This is a browser security feature. Our previous attempts used insertAdjacentHTML, which worked for the <div> but not the scripts, requiring separate <script> element creation.<iframe>).SDK Loading Dependency:
https://www.paypal.com/sdk/js?...) that must load before the button script can run. Network delays, CSP restrictions, or an invalid client-id can cause failures. The 5-second timeout in V2.19 might be too short, and the debug message confirms the SDK didn’t load.CMS Rendering Limitations:
pull-contents.php is a custom solution, but it must handle this dynamic nature explicitly.<head>.Debug and Testing Challenges:
<head> (e.g., via a theme or plugin), avoiding the timing issue. Your setup avoids this by keeping the code in the database, which is flexible but requires robust dynamic rendering.<iframe>) don’t require this level of coordination. The difficulty stems from:
code.client-id is valid and the domain allows the script.Please confirm, and I’ll generate the V2.20 code.
Note: It’s 01:50 PM HKT on Friday, August 29, 2025—plenty of time to test today.
The debug message says:Debug: Inserted div for PayPal ID 58 Debug: Inserted PayPal SDK script for ID 58 Debug: PayPal SDK load error for ID 58: undefined Debug: PayPal SDK failed to load for ID 58 after 10sNo change in the content display!
Opening your PP link in the browser returns (too long to include all):
(function({__FIRST_RENDER_EXPERIMENTS__,__FUNDING_ELIGIBILITY__,__MESSAGING_GLOBALS__}){
/*! For license information please see output.js.LICENSE.txt */
!function(n,e){for(var t in e)n[t]=e[t]}(window,function(n){var e={};function t(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return n[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}return t.m=n,t.c=e,t.d=function(n,e,r){t.o(n,e)||Object.defineProperty(n,e,{enumerable:!0,get:r})},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},t.t=function(n,e){if(1&e&&(n=t(n)),8&e)return n;if(4&e&&"object"==typeof n&&n&&n.__esModule)return n;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:n}),2&e&&"string"!=typeof n)for(var o in n)t.d(r,o,function(e){return n[e]}.bind(null,o));return r},t.n=function(n){var e=n&&n.__esModule?.....
I just tried to upload the static HTML file, which is showing the button in the preview, to the server and the buttons become missing when accessed from the public URL https://www.nlt-chaplaincy.org/index.html.I also wonder if separate the SDK script and the button script into two fields (Say we add a pre-populated "sdk" field and hide it from the users) would help to simplify the issue. is not present on the generated HTML files. I do not own the login of the PP account. However, the code is taken from a former website prototype created in Wix. Let's assume the PP client-id is right unless the browser message above indicates something else.
V2.21 still fails to render the button script. The debug message is:Debug: Inserted div for PayPal ID 58 Debug: PayPal SDK failed to load for ID 58 after 10s
Before testing this new version, I want to clarify that if I'm running the website on my own QNAP NAS server (A Synology NAS is doing the reverse proxy role) would there be still CSP? I confirm that the "content" field is now containing just the button script and the container div as:
<div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div>
<script>
paypal.Buttons({
style: {
shape: 'pill',
color: 'gold',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
plan_id: 'P-3FU48207V4555173AM5STYUA'
});
},
onApprove: function(data, actions) {
alert(data.subscriptionID);
}
}).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA');
</script>
Content Security Policy (CSP) Overview:
Content-Security-Policy in .htaccess or server settings).<meta http-equiv="Content-Security-Policy"> tag can define CSP client-side.QNAP NAS Server:
.htaccess for Apache).Synology NAS as Reverse Proxy:
Content-Security-Policy, in the Reverse Proxy settings:https://www.paypal.com.Likelihood of CSP:
<meta> tag is present in your generated HTML and you haven’t mentioned configuring CSP on the QNAP or Synology, it’s possible there’s no explicit CSP. However, a default or inherited policy (e.g., from Synology’s security defaults or a browser extension) could still block the PayPal SDK.https://www.nlt-chaplaincy.org/index.html) suggests a server-side or proxy-level restriction, such as an implicit CSP or CORS issue.Action Steps:
www.nlt-chaplaincy.org, and check the "Custom Header" section for a Content-Security-Policy header. If present, note its value or temporarily remove it for testing.content field now contains only the button script and container <div>:
<div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div>
<script>
paypal.Buttons({
style: {
shape: 'pill',
color: 'gold',
layout: 'vertical',
label: 'subscribe'
},
createSubscription: function(data, actions) {
return actions.subscription.create({
plan_id: 'P-3FU48207V4555173AM5STYUA'
});
},
onApprove: function(data, actions) {
alert(data.subscriptionID);
}
}).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA');
</script>code field. The code_type should still be PayPal to trigger the correct rendering logic.Since the SDK load failure persists, and your setup involves a QNAP NAS with a Synology reverse proxy, the issue is likely server- or proxy-related rather than the code itself. Before testing V2.22, let’s ensure the environment is configured correctly:
Verify Environment:
https://www.paypal.com to the script-src directive (e.g., script-src 'self' https://www.paypal.com;).Proceed with V2.22:
renderEmbed function should now parse the new code correctly, focusing on the <div> and button script.code_type in the database for ID 58 is still PayPal?Please confirm, and I’ll proceed with any adjustments based on your findings. If CSP or a domain mismatch is confirmed, we can refine the approach (e.g., splitting fields or contacting the Wix owner for the client-id).
Note: It’s 07:40 PM HKT on Friday, August 29, 2025—still time to test today, but we can continue tomorrow if needed.
Debug: Inserted div for PayPal ID 58
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: Checking SDK for ID 58, status: undefined
Debug: PayPal SDK failed to load for ID 58 after 10s, Error: No specific error
I found the "Enable CSP HTTP header" option was checked on my QNAP server. I have disabled it and tested again. The debug message changed to:
Debug: Div match for ID 58: Success
Debug: Button match for ID 58: Success
Debug: Inserted div for PayPal ID 58
Debug: Rendered PayPal button for ID 58
The content area is still showing:
Debug: Embed code for ID 58 (PayPal): <div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div> <script> paypal.Buttons({ style: { shape: 'pill', color: 'gold', layout: 'vertical', label: 'subscribe' }, createSubscription: function(data, actions) { return actions.subscription.create({ plan_id: 'P-3FU48207V4555173AM5STYUA' }); }, onApprove: function(data, actions) { alert(data.subscriptionID); } }).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA'); </script>
I have checked my Synology NAS and there is no custom header set.
Debug: Checking SDK for ID 58, status: undefined followed by Debug: PayPal SDK failed to load for ID 58 after 10s, Error: No specific error confirms the PayPal SDK wasn’t loading, likely due to the QNAP server’s CSP setting blocking https://www.paypal.com.Debug: Div match for ID 58: Success and Debug: Button match for ID 58: Success indicate the parsing of the updated content field (containing the <div> and button script) is working correctly.Debug: Inserted div for PayPal ID 58 confirms the <div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"> is inserted into the DOM.Debug: Rendered PayPal button for ID 58 suggests the button script was executed, which is a significant improvement since the SDK load succeeded after disabling CSP.Debug: Embed code for ID 58 (PayPal): ... text, including the <div> and <script> block. This indicates the fallback or original content isn’t being replaced or hidden properly after the button is rendered.renderEmbed function inserts the <div> and executes the button script, but the original code text (logged as debug output) remains visible. This happens because:<div style='color: orange;'>Debug: Embed code for ID 58...) is being rendered as part of the page content and not removed after the button is inserted.container.style.display = 'none' only hides the initial <div class="content-embed">, not the debug output or the original text if it’s part of the content flow.<div> and rendering the button, explicitly clear or replace the original content-embed div to avoid displaying the raw code.<?php
// pull-contents.php (Version 2.23)
// Debug toggle: Set to true to enable debug messages, false to disable
define('DEBUG', true);
// Define base path for images
define('IMAGE_BASE_PATH', 'https://admin.nlt-chaplaincy.org/images/');
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$config_path = '../config.php';
if (!file_exists($config_path)) {
die("Error: config.php not found at $config_path");
}
require_once $config_path;
if (!isset($dbServer) || !isset($dbUsername) || !isset($dbPassword) || !isset($dbDatabase)) {
die("Error: AppGini database variables not defined in config.php");
}
$conn = new mysqli($dbServer, $dbUsername, $dbPassword, $dbDatabase, $dbPort ?: 3306);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Auto-detect page from calling file if $_GET['page'] not set
if (isset($_GET['page'])) {
$current_page = $_GET['page'];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Page set from GET: '$current_page'</div>";
}
} else {
$calling_file = basename($_SERVER['SCRIPT_FILENAME']);
$request_uri = $_SERVER['REQUEST_URI'];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Calling file: '$calling_file'</div>";
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: REQUEST_URI: '$request_uri'</div>";
}
$current_page = str_replace('.php', '', $calling_file);
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page after str_replace: '$current_page'</div>";
}
if ($current_page === 'index') {
$current_page = 'landing';
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page set to 'landing'</div>";
}
if (preg_match('/\/(task-map)\.php/', $request_uri, $matches)) {
$current_page = $matches[1];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page updated from REQUEST_URI: '$current_page'</div>";
}
}
}
}
$status = 'Show';
// Preload PayPal SDK with synchronous load
$paypalSdkUrl = 'https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription';
echo "<script src=\"$paypalSdkUrl\" id=\"paypal-sdk\" async=\"false\" onload=\"console.log('PayPal SDK loaded')\" onerror=\"console.error('PayPal SDK load error:', event)\"></script>";
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Final current_page: '$current_page'</div>";
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Image Base Path: '" . IMAGE_BASE_PATH . "'</div>";
}
// Determine if we're on the stories page
$is_stories_page = ($current_page === 'stories');
// Check if the request is for modal content
$is_modal_request = (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') || isset($_GET['modal']);
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Is modal request: " . ($is_modal_request ? 'Yes' : 'No') . "</div>";
}
$sql = "SELECT id, title, content, code, code_type, image, button_link, button_text, position, model, date_edited, theme_img, img_role, chk_divider
FROM web_content
WHERE page = ? AND status = ?
ORDER BY position ASC, date_edited DESC";
$stmt = $conn->prepare($sql);
if (!$stmt) {
die("Prepare failed: " . $conn->connect_error);
}
$stmt->bind_param("ss", $current_page, $status);
$stmt->execute();
$result = $stmt->get_result();
$sections = [];
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$sections[] = $row;
}
}
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Fetched " . count($sections) . " sections for page '$current_page'</div>";
}
// Group sections by position
$sections_by_position = [];
foreach ($sections as $row) {
$position = $row['position'] ?? 1;
$sections_by_position[$position][] = $row;
}
if (!empty($sections_by_position)) {
ksort($sections_by_position);
$current_index = 0;
foreach ($sections_by_position as $position => $group) {
$current_index++;
$use_default_divider = true;
$has_background_image = false;
foreach ($group as $row) {
if (!empty($row['theme_img']) && $row['img_role'] === 'Background') {
$has_background_image = true;
$use_default_divider = false;
break;
}
}
if (isset($group[0]['chk_divider'])) {
$use_default_divider = $group[0]['chk_divider'] == 1;
}
if ($is_modal_request) {
foreach ($group as $index => $row) {
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Rendering modal section ID: {$row['id']} at position: $position</div>";
}
echo "<div class=\"modal-story-content\">";
if (!empty($row['title'])) {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image modal-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
} elseif ($row['model'] === 'title-text-code' && !empty($row['code']) && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
if (!empty($row['content'])) {
echo "<div class=\"generic-content align-center\">" . $row['content'] . "</div>";
}
if (DEBUG) {
echo "<div style='color: purple; font-weight: bold; text-align: center;'>Debug: Modal content length: " . strlen($row['content']) . " characters</div>";
}
echo "</div>";
if ($index < count($group) - 1 || $current_index < count($sections_by_position)) {
echo "<div class=\"modal-section-separator\"></div>";
}
}
} else {
if (count($group) > 1) {
$column_count = min(count($group), 3);
$extra_class = ($current_page === 'task-map') ? ' task-map-section' : '';
echo "<section class=\"section-hero section-hero--full layout-$column_count-column$extra_class\">";
echo "<div class=\"section-hero__content\">";
foreach ($group as $index => $row) {
echo "<div class=\"column column-$index\">";
if (!empty($row['theme_img']) && $row['img_role'] === 'Background') {
$background_image = IMAGE_BASE_PATH . htmlspecialchars($row['theme_img']);
echo "<div class=\"background-image-wrapper\" style=\"background-image: url('$background_image');\"></div>";
}
if ($current_page === 'faq') {
echo "<h1 class=\"align-center faq-question\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center faq-answer\">" . $row['content'] . "</div>";
} else {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center\">";
if ($is_stories_page) {
$content = strip_tags($row['content']);
$preview = mb_substr($content, 0, 60, 'UTF-8');
if (mb_strlen($content, 'UTF-8') > 60) {
$preview .= '...';
}
echo htmlspecialchars($preview);
} else {
echo $row['content'];
}
echo "</div>";
}
if ($row['model'] === 'title-text-code' && !empty($row['code']) && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
$encodedCode = json_encode($row['code'], JSON_HEX_TAG);
echo "<script>window.contentCode = window.contentCode || []; window.contentCode.push({id: '{$row['id']}', code: " . $encodedCode . ", type: '{$row['code_type']}'});</script>";
if (DEBUG) {
console.log(`Debug: Embed code for ID ${row['id']} (${row['code_type']}): ${row['code']}`);
}
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
}
if (!empty($row['button_text'])) {
$button_text = htmlspecialchars($row['button_text']);
echo "<div class=\"content__buttons\">";
if ($is_stories_page) {
$modal_id = 'modal-content-' . $row['id'];
echo "<div id=\"$modal_id\" style=\"display:none;\">";
echo '<div class="modal-story-content">';
if (!empty($row['title'])) {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image modal-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
} elseif ($row['model'] === 'title-text-code' && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
if (!empty($row['content'])) {
echo "<div class=\"generic-content align-center\">" . $row['content'] . "</div>";
}
if (DEBUG) {
echo "<div style='color: purple; font-weight: bold; text-align: center;'>Debug: Modal content length: " . strlen($row['content']) . " characters</div>";
}
echo '</div>';
echo "</div>";
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-id=\"$modal_id\">$button_text</a>";
if (DEBUG) {
echo "<div style='color: orange; font-weight: bold; text-align: center;'>Debug: Modal trigger rendered for ID: $modal_id with button text: $button_text</div>";
}
} else {
$button_link = htmlspecialchars($row['button_link'] ?: '');
if (!empty($button_link) && $row['button_link'] !== '#') {
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-link=\"$button_link\">$button_text</a>";
} else {
echo "<a class=\"myButton\" href=\"#\">$button_text</a>";
}
}
echo "</div>";
}
echo "</div>";
}
echo "</div>";
echo "</section>";
} else {
$row = $group[0];
$extra_class = ($current_page === 'task-map') ? ' task-map-section' : '';
$background_style = $has_background_image ? " style=\"background-image: url('" . IMAGE_BASE_PATH . htmlspecialchars($row['theme_img']) . "');\"" : '';
echo "<div class=\"section-hero section-hero--full$extra_class\"$background_style>";
echo "<div class=\"section-hero__content\">";
if ($current_page === 'faq') {
echo "<h1 class=\"align-center faq-question\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center faq-answer\">" . $row['content'] . "</div>";
} else {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center\">";
if ($is_stories_page) {
$content = strip_tags($row['content']);
$preview = mb_substr($content, 0, 60, 'UTF-8');
if (mb_strlen($content, 'UTF-8') > 60) {
$preview .= '...';
}
echo htmlspecialchars($preview);
} else {
echo $row['content'];
}
echo "</div>";
}
if ($row['model'] === 'title-text-code' && !empty($row['code']) && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
$encodedCode = json_encode($row['code'], JSON_HEX_TAG);
echo "<script>window.contentCode = window.contentCode || []; window.contentCode.push({id: '{$row['id']}', code: " . $encodedCode . ", type: '{$row['code_type']}'});</script>";
if (DEBUG) {
console.log(`Debug: Embed code for ID ${row['id']} (${row['code_type']}): ${row['code']}`);
}
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
}
if (!empty($row['button_text'])) {
$button_text = htmlspecialchars($row['button_text']);
echo "<div class=\"content__buttons\">";
if ($is_stories_page) {
$modal_id = 'modal-content-' . $row['id'];
echo "<div id=\"$modal_id\" style=\"display:none;\">";
echo '<div class="modal-story-content">';
if (!empty($row['title'])) {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image modal-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
} elseif ($row['model'] === 'title-text-code' && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
if (!empty($row['content'])) {
echo "<div class=\"generic-content align-center\">" . $row['content'] . "</div>";
}
if (DEBUG) {
echo "<div style='color: purple; font-weight: bold; text-align: center;'>Debug: Modal content length: " . strlen($row['content']) . " characters</div>";
}
echo '</div>';
echo "</div>";
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-id=\"$modal_id\">$button_text</a>";
if (DEBUG) {
echo "<div style='color: orange; font-weight: bold; text-align: center;'>Debug: Modal trigger rendered for ID: $modal_id with button text: $button_text</div>";
}
} else {
$button_link = htmlspecialchars($row['button_link'] ?: '');
if (!empty($button_link) && $row['button_link'] !== '#') {
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-link=\"$button_link\">$button_text</a>";
} else {
echo "<a class=\"myButton\" href=\"#\">$button_text</a>";
}
}
echo "</div>";
}
echo "</div>";
echo "</div>";
}
}
if ($current_index < count($sections_by_position) && !$is_modal_request) {
if ($use_default_divider) {
echo "<div class=\"separator\"><img src=\"https://admin.nlt-chaplaincy.org/public/down_arrow.png\" alt=\"Default Separator\" class=\"separator-image\"></div>";
} elseif (!empty($row['theme_img']) && $row['img_role'] === 'Separator') {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['theme_img']);
echo "<div class=\"separator\"><img src=\"$image_url\" alt=\"Custom Separator\" class=\"separator-image\"></div>";
}
}
if (DEBUG) {
echo "<div style=\"color: green; font-weight: bold; text-align: center;\">Debug: Section with position $position rendered successfully with " . count($group) . " items.</div>";
}
}
} else {
echo "No sections found.";
}
// Modal container (only for non-AJAX requests)
if (!$is_modal_request) {
echo '<div id="story-modal" class="modal">';
echo '<div class="modal-content">';
echo '<span class="modal-close">×</span>';
echo '<div id="modal-body"></div>';
echo '</div>';
echo '</div>';
}
$stmt->close();
$conn->close();
?>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Synchronize with PHP DEBUG setting
const DEBUG = <?php echo DEBUG ? 'true' : 'false'; ?>;
// Debug log setup
let debugLog = null;
if (DEBUG) {
debugLog = document.createElement('div');
debugLog.id = 'debug-log';
debugLog.style.position = 'fixed';
debugLog.style.bottom = '10px';
debugLog.style.left = '10px';
debugLog.style.background = 'rgba(0, 0, 0, 0.8)';
debugLog.style.color = 'white';
debugLog.style.padding = '10px';
debugLog.style.zIndex = '1000';
debugLog.style.maxHeight = '200px';
debugLog.style.overflowY = 'auto';
document.body.appendChild(debugLog);
}
function logDebug(message, color = 'green') {
if (DEBUG && debugLog) {
debugLog.insertAdjacentHTML('beforeend', `<div style="color: ${color}; font-weight: bold;">Debug: ${message}</div>`);
debugLog.scrollTop = debugLog.scrollHeight;
}
if (DEBUG && console) console.log(`Debug: ${message}`, { color });
}
if (DEBUG) logDebug('Modal script loaded');
const modal = document.getElementById('story-modal');
const modalBody = document.getElementById('modal-body');
const closeBtn = document.querySelector('.modal-close');
const triggers = document.querySelectorAll('.modal-trigger');
if (DEBUG) logDebug('Found ' + triggers.length + ' modal triggers');
// Function to render embed blocks with script separation
function renderEmbed(item) {
const container = document.getElementById(`embed-${item.id}`);
if (!container) {
if (DEBUG) logDebug(`Container not found for embed ID ${item.id}`, 'red');
return;
}
// Extract components with flexible matching
const divMatch = item.code.match(/<div\s+[^>]*id="[^"]+"[^>]*>/i);
const buttonMatch = item.code.match(/<script>\s*paypal\.Buttons\([\s\S]*?\)\.render\(['"][^'"]+['"]\);\s*<\/script>/i);
if (DEBUG) {
logDebug(`Div match for ID ${item.id}: ${divMatch ? 'Success' : 'Failed'}`, divMatch ? 'green' : 'red');
logDebug(`Button match for ID ${item.id}: ${buttonMatch ? 'Success' : 'Failed'}`, buttonMatch ? 'green' : 'red');
}
if (item.type === 'PayPal' && divMatch && buttonMatch) {
// Insert div and clear container
container.innerHTML = divMatch[0];
if (DEBUG) logDebug(`Inserted div for PayPal ID ${item.id}`, 'orange');
// Check SDK availability with retry
const checkSDK = setInterval(() => {
if (typeof paypal !== 'undefined') {
clearInterval(checkSDK);
const buttonScript = document.createElement('script');
buttonScript.textContent = buttonMatch[0].replace(/^<script>|<\/script>$/g, '').trim();
document.body.appendChild(buttonScript);
if (DEBUG) logDebug(`Rendered PayPal button for ID ${item.id}`, 'orange');
container.style.display = 'block'; // Ensure visibility
} else if (DEBUG) {
logDebug(`Checking SDK for ID ${item.id}, status: ${typeof paypal}`, 'yellow');
}
}, 100);
// Extended timeout with detailed log
setTimeout(() => {
if (typeof paypal === 'undefined') {
clearInterval(checkSDK);
const sdkScript = document.getElementById('paypal-sdk');
const errorMsg = sdkScript ? (sdkScript.error || 'No specific error') : 'Script element not found';
if (DEBUG) logDebug(`PayPal SDK failed to load for ID ${item.id} after 10s, Error: ${errorMsg}`, 'red');
}
}, 10000);
} else if (item.type === 'YouTube') {
// Insert YouTube iframe directly
container.innerHTML = item.code;
container.style.display = 'block';
if (DEBUG) logDebug(`Rendered YouTube embed for ID ${item.id}`, 'orange');
} else {
// Fallback only on parsing failure
container.innerHTML = `<div class="embed-fallback" id="fallback-${item.id}">${item.code}</div>`;
container.style.display = 'block';
if (DEBUG) logDebug(`Fallback rendered for ID ${item.id} (parsing failed, scripts not executed)`, 'red');
}
}
// Process embed blocks
if (window.contentCode && Array.isArray(window.contentCode)) {
window.contentCode.forEach(item => {
renderEmbed(item);
});
} else if (DEBUG) {
logDebug('contentCode is not an array or unavailable', 'red');
}
function openModal(content) {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = content;
const buttons = tempDiv.querySelectorAll('.content__buttons');
buttons.forEach(button => button.remove());
const debugMessages = tempDiv.querySelectorAll('div[style*="color: purple"], div[style*="color: blue"], div[style*="color: red"], div[style*="color: green"]');
debugMessages.forEach(msg => msg.remove());
let combinedContent = '';
const sections = tempDiv.querySelectorAll('.modal-story-content');
if (DEBUG) logDebug('Found ' + sections.length + ' modal-story-content sections');
if (sections.length > 0) {
sections.forEach((section, index) => {
combinedContent += section.outerHTML.trim();
if (index < sections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const fallbackSections = tempDiv.querySelectorAll('.section-hero__content');
if (DEBUG) logDebug('Found ' + fallbackSections.length + ' section-hero__content sections');
if (fallbackSections.length > 0) {
fallbackSections.forEach((section, index) => {
const title = section.querySelector('h1');
const image = section.querySelector('.content-image');
const content = section.querySelector('.generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
if (title) newContent.appendChild(title.cloneNode(true));
if (image) newContent.appendChild(image.cloneNode(true));
if (content) newContent.appendChild(content.cloneNode(true));
combinedContent += newContent.outerHTML.trim();
if (index < fallbackSections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const genericContent = tempDiv.querySelector('.generic-content');
if (genericContent) {
if (DEBUG) logDebug('Falling back to .generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
newContent.appendChild(genericContent.cloneNode(true));
combinedContent = newContent.outerHTML.trim();
} else {
if (DEBUG) logDebug('No content found in .modal-story-content, .section-hero__content, or .generic-content', 'red');
combinedContent = '<p>Content could not be parsed from the page.</p>';
}
}
}
modalBody.innerHTML = combinedContent;
modal.style.display = 'block';
modal.setAttribute('aria-hidden', 'false');
if (modalBody.children.length > 0 && closeBtn) {
closeBtn.focus();
}
if (DEBUG) logDebug('Modal opened');
}
function closeModal() {
modal.style.display = 'none';
modal.setAttribute('aria-hidden', 'true');
modalBody.innerHTML = '';
if (DEBUG && debugLog) {
debugLog.innerHTML = '';
}
if (DEBUG) logDebug('Modal closed');
}
if (modal && modalBody && closeBtn && triggers) {
triggers.forEach(trigger => {
trigger.addEventListener('click', function(e) {
e.preventDefault();
const modalId = this.getAttribute('data-modal-id');
if (modalId) {
const contentDiv = document.getElementById(modalId);
if (contentDiv) {
const content = contentDiv.innerHTML;
if (DEBUG) logDebug('Stories modal triggered, content from ID: ' + modalId);
if (DEBUG) logDebug('Modal content length: ' + content.length + ' characters', 'purple');
openModal(content);
} else {
openModal('<p>Content not found.</p>');
if (DEBUG) logDebug('Modal content not found for ID: ' + modalId, 'red');
}
return;
}
const link = this.getAttribute('data-modal-link');
if (DEBUG) logDebug('Trigger clicked, link: ' + link);
if (!link || link === '#' || link.includes('index.php')) {
openModal('<p>This link cannot be loaded in a modal to prevent recursive loading.</p>');
return;
}
let basePath = window.location.origin;
let absoluteLink;
try {
if (link.startsWith('http://') || link.startsWith('https://')) {
absoluteLink = link;
} else if (link.startsWith('/')) {
absoluteLink = new URL(link, window.location.origin).href;
} else {
absoluteLink = new URL(link, window.location.origin + '/').href;
}
absoluteLink += (absoluteLink.includes('?') ? '&' : '?') + 'modal=1';
if (DEBUG) logDebug('Fetching absolute link: ' + absoluteLink);
} catch (error) {
if (DEBUG) logDebug('URL construction error: ' + error.message, 'red');
openModal('<p>Invalid URL format.</p>');
return;
}
openModal('<p>Loading...</p>');
fetch(absoluteLink, {
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => {
if (DEBUG) logDebug('Fetch response status: ' + response.status + ' ' + response.statusText);
if (!response.ok) {
throw new Error('Network response was not ok: ' + response.statusText);
}
return response.text();
})
.then(data => {
if (DEBUG) logDebug('Fetched HTML length: ' + data.length);
const parser = new DOMParser();
const doc = parser.parseFromString(data, 'text/html');
let combinedContent = '';
const sections = doc.querySelectorAll('.modal-story-content');
if (DEBUG) logDebug('Found ' + sections.length + ' modal-story-content sections in fetched content');
if (sections.length > 0) {
sections.forEach((content, index) => {
combinedContent += content.outerHTML.trim();
if (index < sections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const fallbackSections = doc.querySelectorAll('.section-hero__content');
if (DEBUG) logDebug('Found ' + fallbackSections.length + ' section-hero__content sections');
if (fallbackSections.length > 0) {
fallbackSections.forEach((section, index) => {
const title = section.querySelector('h1');
const image = section.querySelector('.content-image');
const content = section.querySelector('.generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
if (title) newContent.appendChild(title.cloneNode(true));
if (image) newContent.appendChild(image.cloneNode(true));
if (content) newContent.appendChild(content.cloneNode(true));
combinedContent += newContent.outerHTML.trim();
if (index < fallbackSections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const genericContent = doc.querySelector('.generic-content');
if (genericContent) {
if (DEBUG) logDebug('Falling back to .generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
newContent.appendChild(genericContent.cloneNode(true));
combinedContent = newContent.outerHTML.trim();
} else {
if (DEBUG) logDebug('No content found in .modal-story-content, .section-hero__content, or .generic-content', 'red');
combinedContent = '<p>Content could not be parsed from the page.</p>';
}
}
}
if (combinedContent) {
openModal(combinedContent);
} else {
openModal('<p>No content found.</p>');
}
})
.catch(error => {
if (DEBUG) logDebug('Fetch error: ' + error.message, 'red');
openModal('<p>Sorry, the content could not be loaded: ' + error.message + '</p>');
});
});
});
closeBtn.addEventListener('click', closeModal);
window.addEventListener('click', function(event) {
if (event.target === modal) {
closeModal();
}
});
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && modal.style.display === 'block') {
closeModal();
}
});
} else {
if (DEBUG) logDebug('Modal elements missing (modal, modalBody, closeBtn, or triggers)', 'red');
}
});
</script>
Remove Debug Output from Content:
echo "<div style='color: orange;'>..." to console.log in both PHP sections, ensuring it appears in the browser console (F12) rather than the page content.Ensure Content Replacement:
container.insertAdjacentHTML('afterend', divMatch[0]) to container.innerHTML = divMatch[0] to replace the entire content-embed div’s content with the PayPal <div>, avoiding residual text.container.style.display = 'block' after rendering to ensure visibility, though this should be automatic with innerHTML.Version Update:
Verify Database:
content column for ID 58 contains the updated button script and <div> as shown.code_type is PayPal.Deploy Updated File:
pull-contents.php with the 638-line V2.23 code.Regenerate and Test:
https://www.nlt-chaplaincy.org/index.html and check the PP section at position 100.Test PayPal Button:
subscriptionID).Test YouTube Embed:
<iframe> embeds display and play correctly.Debug Output:
DEBUG true and review messages in the floating log (e.g., match success, insertion, rendering).PayPal SDK load error:).<div> and button are present but hidden, or check for JavaScript errors.Please deploy, test, and share the debug log and console output! We’re close to resolving this.
Debug: Embed code for ID 58 (PayPal): <div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"></div> <script> paypal.Buttons({ style: { shape: 'pill', color: 'gold', layout: 'vertical', label: 'subscribe' }, createSubscription: function(data, actions) { return actions.subscription.create({ plan_id: 'P-3FU48207V4555173AM5STYUA' }); }, onApprove: function(data, actions) { alert(data.subscriptionID); } }).render('#paypal-button-container-P-3FU48207V4555173AM5STYUA'); </script>
The floating debug msg says:
Debug: Inserted div for PayPal ID 58
Debug: Rendered PayPal button for ID 58
V2.24 has unfortunately made things more worse. Firstly the PP buttons are missing with debug msg://Fatal error: Uncaught Error: Undefined constant "console" in /share/CACHEDEV1_DATA/Web/nlhcm/public/pull-contents.php:269 Stack trace: #0 /share/CACHEDEV1_DATA/Web/nlhcm/public/index.php(3): include() #1 {main} thrown in /share/CACHEDEV1_DATA/Web/nlhcm/public/pull-contents.php on line 269//The background image of the left frame (Top frame in mobile view) fails to load and has become dark.Interestingly, re-testing V2.23 has the same effect. What worked was V2.22 actually. I guess there might be a cache issue. What confirmed working is V2.22, both V2.23 and 2.24 are not working.
Undefined constant "console" in /share/CACHEDEV1_DATA/Web/nlhcm/public/pull-contents.php:269 indicates that PHP is interpreting console as a constant rather than the JavaScript console object. This happened because the console.log calls in the PHP section (e.g., if (DEBUG) { console.log(...); }) were incorrectly placed in PHP code instead of a <script> block. PHP doesn’t recognize console as a valid object unless it’s within a JavaScript context, causing the fatal error on line 269 (likely where the first console.log appears).theme_img or background-image-wrapper is being processed. This could be due to the PHP error halting script execution, preventing proper image rendering, or a side effect of the code changes affecting the CSS/JS interaction.console.log change wasn’t introduced until V2.23, so V2.22 avoided the PHP syntax error.console.log calls back to a proper JavaScript context (e.g., within a <script> block) or remove them from PHP entirely, relying on the existing JavaScript logDebug function.theme_img and img_role handling.<?php
// pull-contents.php (Version 2.25)
// Debug toggle: Set to true to enable debug messages, false to disable
define('DEBUG', true);
// Define base path for images
define('IMAGE_BASE_PATH', 'https://admin.nlt-chaplaincy.org/images/');
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$config_path = '../config.php';
if (!file_exists($config_path)) {
die("Error: config.php not found at $config_path");
}
require_once $config_path;
if (!isset($dbServer) || !isset($dbUsername) || !isset($dbPassword) || !isset($dbDatabase)) {
die("Error: AppGini database variables not defined in config.php");
}
$conn = new mysqli($dbServer, $dbUsername, $dbPassword, $dbDatabase, $dbPort ?: 3306);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Auto-detect page from calling file if $_GET['page'] not set
if (isset($_GET['page'])) {
$current_page = $_GET['page'];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Page set from GET: '$current_page'</div>";
}
} else {
$calling_file = basename($_SERVER['SCRIPT_FILENAME']);
$request_uri = $_SERVER['REQUEST_URI'];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Calling file: '$calling_file'</div>";
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: REQUEST_URI: '$request_uri'</div>";
}
$current_page = str_replace('.php', '', $calling_file);
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page after str_replace: '$current_page'</div>";
}
if ($current_page === 'index') {
$current_page = 'landing';
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page set to 'landing'</div>";
}
if (preg_match('/\/(task-map)\.php/', $request_uri, $matches)) {
$current_page = $matches[1];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page updated from REQUEST_URI: '$current_page'</div>";
}
}
}
}
$status = 'Show';
// Preload PayPal SDK with synchronous load
$paypalSdkUrl = 'https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription';
echo "<script src=\"$paypalSdkUrl\" id=\"paypal-sdk\" async=\"false\" onload=\"console.log('PayPal SDK loaded')\" onerror=\"console.error('PayPal SDK load error:', event)\"></script>";
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Final current_page: '$current_page'</div>";
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Image Base Path: '" . IMAGE_BASE_PATH . "'</div>";
}
// Determine if we're on the stories page
$is_stories_page = ($current_page === 'stories');
// Check if the request is for modal content
$is_modal_request = (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') || isset($_GET['modal']);
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Is modal request: " . ($is_modal_request ? 'Yes' : 'No') . "</div>";
}
$sql = "SELECT id, title, content, code, code_type, image, button_link, button_text, position, model, date_edited, theme_img, img_role, chk_divider
FROM web_content
WHERE page = ? AND status = ?
ORDER BY position ASC, date_edited DESC";
$stmt = $conn->prepare($sql);
if (!$stmt) {
die("Prepare failed: " . $conn->connect_error);
}
$stmt->bind_param("ss", $current_page, $status);
$stmt->execute();
$result = $stmt->get_result();
$sections = [];
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$sections[] = $row;
}
}
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Fetched " . count($sections) . " sections for page '$current_page'</div>";
}
// Group sections by position
$sections_by_position = [];
foreach ($sections as $row) {
$position = $row['position'] ?? 1;
$sections_by_position[$position][] = $row;
}
if (!empty($sections_by_position)) {
ksort($sections_by_position);
$current_index = 0;
foreach ($sections_by_position as $position => $group) {
$current_index++;
$use_default_divider = true;
$has_background_image = false;
foreach ($group as $row) {
if (!empty($row['theme_img']) && $row['img_role'] === 'Background') {
$has_background_image = true;
$use_default_divider = false;
break;
}
}
if (isset($group[0]['chk_divider'])) {
$use_default_divider = $group[0]['chk_divider'] == 1;
}
if ($is_modal_request) {
foreach ($group as $index => $row) {
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Rendering modal section ID: {$row['id']} at position: $position</div>";
}
echo "<div class=\"modal-story-content\">";
if (!empty($row['title'])) {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image modal-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
} elseif ($row['model'] === 'title-text-code' && !empty($row['code']) && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
if (!empty($row['content'])) {
echo "<div class=\"generic-content align-center\">" . $row['content'] . "</div>";
}
if (DEBUG) {
echo "<div style='color: purple; font-weight: bold; text-align: center;'>Debug: Modal content length: " . strlen($row['content']) . " characters</div>";
}
echo "</div>";
if ($index < count($group) - 1 || $current_index < count($sections_by_position)) {
echo "<div class=\"modal-section-separator\"></div>";
}
}
} else {
if (count($group) > 1) {
$column_count = min(count($group), 3);
$extra_class = ($current_page === 'task-map') ? ' task-map-section' : '';
echo "<section class=\"section-hero section-hero--full layout-$column_count-column$extra_class\">";
echo "<div class=\"section-hero__content\">";
foreach ($group as $index => $row) {
echo "<div class=\"column column-$index\">";
if (!empty($row['theme_img']) && $row['img_role'] === 'Background') {
$background_image = IMAGE_BASE_PATH . htmlspecialchars($row['theme_img']);
echo "<div class=\"background-image-wrapper\" style=\"background-image: url('$background_image');\"></div>";
}
if ($current_page === 'faq') {
echo "<h1 class=\"align-center faq-question\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center faq-answer\">" . $row['content'] . "</div>";
} else {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center\">";
if ($is_stories_page) {
$content = strip_tags($row['content']);
$preview = mb_substr($content, 0, 60, 'UTF-8');
if (mb_strlen($content, 'UTF-8') > 60) {
$preview .= '...';
}
echo htmlspecialchars($preview);
} else {
echo $row['content'];
}
echo "</div>";
}
if ($row['model'] === 'title-text-code' && !empty($row['code']) && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
$encodedCode = json_encode($row['code'], JSON_HEX_TAG);
echo "<script>window.contentCode = window.contentCode || []; window.contentCode.push({id: '{$row['id']}', code: " . $encodedCode . ", type: '{$row['code_type']}'});</script>";
if (DEBUG) {
echo "<div style='color: orange; display: none;'>Debug: Embed code for ID ${row['id']} (${row['code_type']}): ${row['code']}</div>"; // Temporarily hidden
}
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
}
if (!empty($row['button_text'])) {
$button_text = htmlspecialchars($row['button_text']);
echo "<div class=\"content__buttons\">";
if ($is_stories_page) {
$modal_id = 'modal-content-' . $row['id'];
echo "<div id=\"$modal_id\" style=\"display:none;\">";
echo '<div class="modal-story-content">';
if (!empty($row['title'])) {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image modal-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
} elseif ($row['model'] === 'title-text-code' && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
if (!empty($row['content'])) {
echo "<div class=\"generic-content align-center\">" . $row['content'] . "</div>";
}
if (DEBUG) {
echo "<div style='color: purple; font-weight: bold; text-align: center;'>Debug: Modal content length: " . strlen($row['content']) . " characters</div>";
}
echo '</div>';
echo "</div>";
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-id=\"$modal_id\">$button_text</a>";
if (DEBUG) {
echo "<div style='color: orange; font-weight: bold; text-align: center;'>Debug: Modal trigger rendered for ID: $modal_id with button text: $button_text</div>";
}
} else {
$button_link = htmlspecialchars($row['button_link'] ?: '');
if (!empty($button_link) && $row['button_link'] !== '#') {
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-link=\"$button_link\">$button_text</a>";
} else {
echo "<a class=\"myButton\" href=\"#\">$button_text</a>";
}
}
echo "</div>";
}
echo "</div>";
}
echo "</div>";
echo "</section>";
} else {
$row = $group[0];
$extra_class = ($current_page === 'task-map') ? ' task-map-section' : '';
$background_style = $has_background_image ? " style=\"background-image: url('" . IMAGE_BASE_PATH . htmlspecialchars($row['theme_img']) . "');\"" : '';
echo "<div class=\"section-hero section-hero--full$extra_class\"$background_style>";
echo "<div class=\"section-hero__content\">";
if ($current_page === 'faq') {
echo "<h1 class=\"align-center faq-question\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center faq-answer\">" . $row['content'] . "</div>";
} else {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center\">";
if ($is_stories_page) {
$content = strip_tags($row['content']);
$preview = mb_substr($content, 0, 60, 'UTF-8');
if (mb_strlen($content, 'UTF-8') > 60) {
$preview .= '...';
}
echo htmlspecialchars($preview);
} else {
echo $row['content'];
}
echo "</div>";
}
if ($row['model'] === 'title-text-code' && !empty($row['code']) && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
$encodedCode = json_encode($row['code'], JSON_HEX_TAG);
echo "<script>window.contentCode = window.contentCode || []; window.contentCode.push({id: '{$row['id']}', code: " . $encodedCode . ", type: '{$row['code_type']}'});</script>";
if (DEBUG) {
echo "<div style='color: orange; display: none;'>Debug: Embed code for ID ${row['id']} (${row['code_type']}): ${row['code']}</div>"; // Temporarily hidden
}
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
}
if (!empty($row['button_text'])) {
$button_text = htmlspecialchars($row['button_text']);
echo "<div class=\"content__buttons\">";
if ($is_stories_page) {
$modal_id = 'modal-content-' . $row['id'];
echo "<div id=\"$modal_id\" style=\"display:none;\">";
echo '<div class="modal-story-content">';
if (!empty($row['title'])) {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image modal-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
} elseif ($row['model'] === 'title-text-code' && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
if (!empty($row['content'])) {
echo "<div class=\"generic-content align-center\">" . $row['content'] . "</div>";
}
if (DEBUG) {
echo "<div style='color: purple; font-weight: bold; text-align: center;'>Debug: Modal content length: " . strlen($row['content']) . " characters</div>";
}
echo '</div>';
echo "</div>";
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-id=\"$modal_id\">$button_text</a>";
if (DEBUG) {
echo "<div style='color: orange; font-weight: bold; text-align: center;'>Debug: Modal trigger rendered for ID: $modal_id with button text: $button_text</div>";
}
} else {
$button_link = htmlspecialchars($row['button_link'] ?: '');
if (!empty($button_link) && $row['button_link'] !== '#') {
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-link=\"$button_link\">$button_text</a>";
} else {
echo "<a class=\"myButton\" href=\"#\">$button_text</a>";
}
}
echo "</div>";
}
echo "</div>";
echo "</div>";
}
}
if ($current_index < count($sections_by_position) && !$is_modal_request) {
if ($use_default_divider) {
echo "<div class=\"separator\"><img src=\"https://admin.nlt-chaplaincy.org/public/down_arrow.png\" alt=\"Default Separator\" class=\"separator-image\"></div>";
} elseif (!empty($row['theme_img']) && $row['img_role'] === 'Separator') {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['theme_img']);
echo "<div class=\"separator\"><img src=\"$image_url\" alt=\"Custom Separator\" class=\"separator-image\"></div>";
}
}
if (DEBUG) {
echo "<div style=\"color: green; font-weight: bold; text-align: center;\">Debug: Section with position $position rendered successfully with " . count($group) . " items.</div>";
}
}
} else {
echo "No sections found.";
}
// Modal container (only for non-AJAX requests)
if (!$is_modal_request) {
echo '<div id="story-modal" class="modal">';
echo '<div class="modal-content">';
echo '<span class="modal-close">×</span>';
echo '<div id="modal-body"></div>';
echo '</div>';
echo '</div>';
}
$stmt->close();
$conn->close();
?>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Synchronize with PHP DEBUG setting
const DEBUG = <?php echo DEBUG ? 'true' : 'false'; ?>;
// Debug log setup
let debugLog = null;
if (DEBUG) {
debugLog = document.createElement('div');
debugLog.id = 'debug-log';
debugLog.style.position = 'fixed';
debugLog.style.bottom = '10px';
debugLog.style.left = '10px';
debugLog.style.background = 'rgba(0, 0, 0, 0.8)';
debugLog.style.color = 'white';
debugLog.style.padding = '10px';
debugLog.style.zIndex = '1000';
debugLog.style.maxHeight = '200px';
debugLog.style.overflowY = 'auto';
document.body.appendChild(debugLog);
}
function logDebug(message, color = 'green') {
if (DEBUG && debugLog) {
debugLog.insertAdjacentHTML('beforeend', `<div style="color: ${color}; font-weight: bold;">Debug: ${message}</div>`);
debugLog.scrollTop = debugLog.scrollHeight;
}
if (DEBUG && console) console.log(`Debug: ${message}`, { color });
}
if (DEBUG) logDebug('Modal script loaded');
const modal = document.getElementById('story-modal');
const modalBody = document.getElementById('modal-body');
const closeBtn = document.querySelector('.modal-close');
const triggers = document.querySelectorAll('.modal-trigger');
if (DEBUG) logDebug('Found ' + triggers.length + ' modal triggers');
// Function to render embed blocks with script separation
function renderEmbed(item) {
const container = document.getElementById(`embed-${item.id}`);
if (!container) {
if (DEBUG) logDebug(`Container not found for embed ID ${item.id}`, 'red');
return;
}
// Extract components with flexible matching
const divMatch = item.code.match(/<div\s+[^>]*id="[^"]+"[^>]*>/i);
const buttonMatch = item.code.match(/<script>\s*paypal\.Buttons\([\s\S]*?\)\.render\(['"][^'"]+['"]\);\s*<\/script>/i);
if (DEBUG) {
logDebug(`Div match for ID ${item.id}: ${divMatch ? 'Success' : 'Failed'}`, divMatch ? 'green' : 'red');
logDebug(`Button match for ID ${item.id}: ${buttonMatch ? 'Success' : 'Failed'}`, buttonMatch ? 'green' : 'red');
}
if (item.type === 'PayPal' && divMatch && buttonMatch) {
// Insert div and clear container
container.innerHTML = divMatch[0];
if (DEBUG) logDebug(`Inserted div for PayPal ID ${item.id}`, 'orange');
// Check SDK availability with retry
const checkSDK = setInterval(() => {
if (typeof paypal !== 'undefined') {
clearInterval(checkSDK);
const buttonScript = document.createElement('script');
buttonScript.textContent = buttonMatch[0].replace(/^<script>|<\/script>$/g, '').trim();
document.body.appendChild(buttonScript);
if (DEBUG) logDebug(`Rendered PayPal button for ID ${item.id}`, 'orange');
container.style.display = 'block'; // Ensure visibility
} else if (DEBUG) {
logDebug(`Checking SDK for ID ${item.id}, status: ${typeof paypal}`, 'yellow');
}
}, 100);
// Extended timeout with detailed log
setTimeout(() => {
if (typeof paypal === 'undefined') {
clearInterval(checkSDK);
const sdkScript = document.getElementById('paypal-sdk');
const errorMsg = sdkScript ? (sdkScript.error || 'No specific error') : 'Script element not found';
if (DEBUG) logDebug(`PayPal SDK failed to load for ID ${item.id} after 10s, Error: ${errorMsg}`, 'red');
}
}, 10000);
} else if (item.type === 'YouTube') {
// Insert YouTube iframe directly
container.innerHTML = item.code;
container.style.display = 'block';
if (DEBUG) logDebug(`Rendered YouTube embed for ID ${item.id}`, 'orange');
} else {
// Fallback only on parsing failure
container.innerHTML = `<div class="embed-fallback" id="fallback-${item.id}">${item.code}</div>`;
container.style.display = 'block';
if (DEBUG) logDebug(`Fallback rendered for ID ${item.id} (parsing failed, scripts not executed)`, 'red');
}
}
// Process embed blocks
if (window.contentCode && Array.isArray(window.contentCode)) {
window.contentCode.forEach(item => {
renderEmbed(item);
});
} else if (DEBUG) {
logDebug('contentCode is not an array or unavailable', 'red');
}
function openModal(content) {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = content;
const buttons = tempDiv.querySelectorAll('.content__buttons');
buttons.forEach(button => button.remove());
const debugMessages = tempDiv.querySelectorAll('div[style*="color: purple"], div[style*="color: blue"], div[style*="color: red"], div[style*="color: green"]');
debugMessages.forEach(msg => msg.remove());
let combinedContent = '';
const sections = tempDiv.querySelectorAll('.modal-story-content');
if (DEBUG) logDebug('Found ' + sections.length + ' modal-story-content sections');
if (sections.length > 0) {
sections.forEach((section, index) => {
combinedContent += section.outerHTML.trim();
if (index < sections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const fallbackSections = tempDiv.querySelectorAll('.section-hero__content');
if (DEBUG) logDebug('Found ' + fallbackSections.length + ' section-hero__content sections');
if (fallbackSections.length > 0) {
fallbackSections.forEach((section, index) => {
const title = section.querySelector('h1');
const image = section.querySelector('.content-image');
const content = section.querySelector('.generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
if (title) newContent.appendChild(title.cloneNode(true));
if (image) newContent.appendChild(image.cloneNode(true));
if (content) newContent.appendChild(content.cloneNode(true));
combinedContent += newContent.outerHTML.trim();
if (index < fallbackSections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const genericContent = tempDiv.querySelector('.generic-content');
if (genericContent) {
if (DEBUG) logDebug('Falling back to .generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
newContent.appendChild(genericContent.cloneNode(true));
combinedContent = newContent.outerHTML.trim();
} else {
if (DEBUG) logDebug('No content found in .modal-story-content, .section-hero__content, or .generic-content', 'red');
combinedContent = '<p>Content could not be parsed from the page.</p>';
}
}
}
modalBody.innerHTML = combinedContent;
modal.style.display = 'block';
modal.setAttribute('aria-hidden', 'false');
if (modalBody.children.length > 0 && closeBtn) {
closeBtn.focus();
}
if (DEBUG) logDebug('Modal opened');
}
function closeModal() {
modal.style.display = 'none';
modal.setAttribute('aria-hidden', 'true');
modalBody.innerHTML = '';
if (DEBUG && debugLog) {
debugLog.innerHTML = '';
}
if (DEBUG) logDebug('Modal closed');
}
if (modal && modalBody && closeBtn && triggers) {
triggers.forEach(trigger => {
trigger.addEventListener('click', function(e) {
e.preventDefault();
const modalId = this.getAttribute('data-modal-id');
if (modalId) {
const contentDiv = document.getElementById(modalId);
if (contentDiv) {
const content = contentDiv.innerHTML;
if (DEBUG) logDebug('Stories modal triggered, content from ID: ' + modalId);
if (DEBUG) logDebug('Modal content length: ' + content.length + ' characters', 'purple');
openModal(content);
} else {
openModal('<p>Content not found.</p>');
if (DEBUG) logDebug('Modal content not found for ID: ' + modalId, 'red');
}
return;
}
const link = this.getAttribute('data-modal-link');
if (DEBUG) logDebug('Trigger clicked, link: ' + link);
if (!link || link === '#' || link.includes('index.php')) {
openModal('<p>This link cannot be loaded in a modal to prevent recursive loading.</p>');
return;
}
let basePath = window.location.origin;
let absoluteLink;
try {
if (link.startsWith('http://') || link.startsWith('https://')) {
absoluteLink = link;
} else if (link.startsWith('/')) {
absoluteLink = new URL(link, window.location.origin).href;
} else {
absoluteLink = new URL(link, window.location.origin + '/').href;
}
absoluteLink += (absoluteLink.includes('?') ? '&' : '?') + 'modal=1';
if (DEBUG) logDebug('Fetching absolute link: ' + absoluteLink);
} catch (error) {
if (DEBUG) logDebug('URL construction error: ' + error.message, 'red');
openModal('<p>Invalid URL format.</p>');
return;
}
openModal('<p>Loading...</p>');
fetch(absoluteLink, {
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => {
if (DEBUG) logDebug('Fetch response status: ' + response.status + ' ' + response.statusText);
if (!response.ok) {
throw new Error('Network response was not ok: ' + response.statusText);
}
return response.text();
})
.then(data => {
if (DEBUG) logDebug('Fetched HTML length: ' + data.length);
const parser = new DOMParser();
const doc = parser.parseFromString(data, 'text/html');
let combinedContent = '';
const sections = doc.querySelectorAll('.modal-story-content');
if (DEBUG) logDebug('Found ' + sections.length + ' modal-story-content sections in fetched content');
if (sections.length > 0) {
sections.forEach((content, index) => {
combinedContent += content.outerHTML.trim();
if (index < sections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const fallbackSections = doc.querySelectorAll('.section-hero__content');
if (DEBUG) logDebug('Found ' + fallbackSections.length + ' section-hero__content sections');
if (fallbackSections.length > 0) {
fallbackSections.forEach((section, index) => {
const title = section.querySelector('h1');
const image = section.querySelector('.content-image');
const content = section.querySelector('.generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
if (title) newContent.appendChild(title.cloneNode(true));
if (image) newContent.appendChild(image.cloneNode(true));
if (content) newContent.appendChild(content.cloneNode(true));
combinedContent += newContent.outerHTML.trim();
if (index < fallbackSections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const genericContent = doc.querySelector('.generic-content');
if (genericContent) {
if (DEBUG) logDebug('Falling back to .generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
newContent.appendChild(genericContent.cloneNode(true));
combinedContent = newContent.outerHTML.trim();
} else {
if (DEBUG) logDebug('No content found in .modal-story-content, .section-hero__content, or .generic-content', 'red');
combinedContent = '<p>Content could not be parsed from the page.</p>';
}
}
}
if (combinedContent) {
openModal(combinedContent);
} else {
openModal('<p>No content found.</p>');
}
})
.catch(error => {
if (DEBUG) logDebug('Fetch error: ' + error.message, 'red');
openModal('<p>Sorry, the content could not be loaded: ' + error.message + '</p>');
});
});
});
closeBtn.addEventListener('click', closeModal);
window.addEventListener('click', function(event) {
if (event.target === modal) {
closeModal();
}
});
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && modal.style.display === 'block') {
closeModal();
}
});
} else {
if (DEBUG) logDebug('Modal elements missing (modal, modalBody, closeBtn, or triggers)', 'red');
}
});
</script>
console.log calls from the PHP section and reverted to using echo with display: none for the embed code debug (as a temporary measure). The JavaScript logDebug function will handle logging correctly.background-image-wrapper logic remains unchanged, which should restore the background image rendering.Verify Database:
content column for ID 58 contains the button script and <div> as shown in your update.code_type is PayPal.Clear Cache:
Deploy Updated File:
pull-contents.php with the 638-line V2.25 code.Regenerate and Test:
https://www.nlt-chaplaincy.org/index.html and check the PP section at position 100.Test PayPal Button:
subscriptionID).Test Background Image:
Test YouTube Embed:
<iframe> embeds display and play correctly.Debug Output:
DEBUG true and review messages in the floating log (e.g., match success, insertion, rendering).PayPal SDK load error:).display: none approach is a quick fix. Once confirmed working, we can move the debug to the console properly in a future version.Please deploy, clear caches, test, and share the debug log and console output! We’ll get this back on track.
Debug: Inserted div for PayPal ID 58
Debug: Checking SDK for ID 58, status: undefined
Debug: Rendered PayPal button for ID 58Is the "status: undefined" problematic?
Debug: Inserted div for PayPal ID 58: Confirms the <div id="paypal-button-container-P-3FU48207V4555173AM5STYUA"> was successfully inserted into the DOM.Debug: Checking SDK for ID 58, status: undefined: Indicates the initial check for the paypal object returned undefined, meaning the PayPal SDK hadn’t loaded yet at that point.Debug: Rendered PayPal button for ID 58: Confirms the button script executed successfully, implying the SDK loaded eventually and the buttons (Subscribe via PayPal or Credit Card) were rendered.checkSDK interval in the renderEmbed function periodically checks typeof paypal to determine if the SDK is available. The status: undefined message appears because the first few checks occur before the SDK finishes loading, which is expected behavior given the asynchronous nature of script loading (even with async="false").Debug: Rendered PayPal button for ID 58 indicates the SDK did load, and the button was rendered, so the undefined status didn’t prevent functionality.setInterval ensures the script waits until paypal is defined before proceeding, and the 10-second timeout would catch any persistent failure (though no timeout error was logged).undefined checks persist for a long time (e.g., beyond a few iterations) or the timeout triggers (PayPal SDK failed to load after 10s), it could indicate a loading delay. However, since the buttons rendered, the delay was resolved within the script’s logic.The "status: undefined" message is not problematic in this case. It’s a normal part of the SDK loading process, and the successful rendering of the PayPal buttons confirms the system worked as intended. The debug output simply reflects the intermediate state before the SDK was available.
subscriptionID).PayPal SDK load error: messages.setInterval delay (e.g., from 100ms to 50ms) or add a loading indicator. However, this isn’t necessary unless it impacts user experience.display: none in V2.25. If you’d prefer it removed entirely, we can adjust the code in the next version to rely solely on the JavaScript logDebug function.onApprove alert.Please test the buttons and share the results or any console output! If everything works, we can consider this resolved or plan minor enhancements.
Debug: Div match for ID 58: Success
Debug: Button match for ID 58: Success
Debug: Inserted div for PayPal ID 58
Debug: Div match for ID 59: Success
Debug: Button match for ID 59: Failed
Debug: Fallback rendered for ID 59 (parsing failed, scripts not executed)
Debug: Div match for ID 60: Success
Debug: Button match for ID 60: Failed
Debug: Fallback rendered for ID 60 (parsing failed, scripts not executed)
Debug: Div match for ID 61: Success
Debug: Button match for ID 61: Failed
Debug: Fallback rendered for ID 61 (parsing failed, scripts not executed)
Debug: Rendered PayPal button for ID 58
I tried assigning the same position for two sections but they do not appear in columns. But we can handle this later when the button display is fixed.
Since you said "If the SDK isn’t available or reinitialized for IDs 59-61, the button script won’t execute, even if the < div > is inserted", I did check the codes for the buttons. I find each button seems to have its own SDK. Since we're only initializing SDK for ID58, that could be what cause other buttons to fail to display.Below are the codes from PP for our four subscription amount:
V2.27 fails to show buttons for all four sections, including the originally working ones.
Thanks for the PP code. V2.28 still fails to show PP buttons for all four sections. The debug code is:
I've updated sections 59-61 with the new button codes. V2.29 still fails to show any buttons. The debug code is:
Div match: Success and Button match: Success for all IDs (58-61) indicate the regex is now correctly identifying the <div> and paypal.Buttons script in the updated code fields.Inserted div and Rendered PayPal button script for all IDs show the function is processing the scripts as intended.Checking SDK for ID X, status: undefined messages suggest the checkSDK interval is running before the preloaded SDK is fully loaded or available in the global scope.PayPal SDK available message appears later for all IDs, but it seems the button rendering isn’t triggered after the SDK becomes available, likely due to the timing of the script execution and the interval check.PayPal SDK available), the buttons aren’t visible. This could be because the paypal.Buttons initialization isn’t properly tied to the SDK’s availability, or the script execution is happening too early.checkSDK interval checks typeof paypal after the script is appended, but it doesn’t actively wait for the SDK to load before executing the render call. The preloaded SDK (async="false") should load synchronously, but there might be a delay or browser-specific behavior preventing immediate availability.<script> element with textContent and relying on an interval to check the SDK might not guarantee the paypal.Buttons function is called at the right time, especially if the SDK initialization is asynchronous despite async="false".renderEmbed:
paypal.Buttons rendering until the SDK is confirmed loaded.pull-contents.php (V2.30, 638 Lines)<?php
// pull-contents.php (Version 2.30)
// Debug toggle: Set to true to enable debug messages, false to disable
define('DEBUG', true);
// Define base path for images
define('IMAGE_BASE_PATH', 'https://admin.nlt-chaplaincy.org/images/');
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$config_path = '../config.php';
if (!file_exists($config_path)) {
die("Error: config.php not found at $config_path");
}
require_once $config_path;
if (!isset($dbServer) || !isset($dbUsername) || !isset($dbPassword) || !isset($dbDatabase)) {
die("Error: AppGini database variables not defined in config.php");
}
$conn = new mysqli($dbServer, $dbUsername, $dbPassword, $dbDatabase, $dbPort ?: 3306);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Auto-detect page from calling file if $_GET['page'] not set
if (isset($_GET['page'])) {
$current_page = $_GET['page'];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Page set from GET: '$current_page'</div>";
}
} else {
$calling_file = basename($_SERVER['SCRIPT_FILENAME']);
$request_uri = $_SERVER['REQUEST_URI'];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Calling file: '$calling_file'</div>";
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: REQUEST_URI: '$request_uri'</div>";
}
$current_page = str_replace('.php', '', $calling_file);
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page after str_replace: '$current_page'</div>";
}
if ($current_page === 'index') {
$current_page = 'landing';
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page set to 'landing'</div>";
}
if (preg_match('/\/(task-map)\.php/', $request_uri, $matches)) {
$current_page = $matches[1];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page updated from REQUEST_URI: '$current_page'</div>";
}
}
}
}
$status = 'Show';
// Preload PayPal SDK to support all buttons
$paypalSdkUrl = 'https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription';
echo "<script src=\"$paypalSdkUrl\" id=\"paypal-sdk\" async=\"false\" onload=\"console.log('PayPal SDK preloaded')\" onerror=\"console.error('PayPal SDK preload error:', event)\"></script>";
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Final current_page: '$current_page'</div>";
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Image Base Path: '" . IMAGE_BASE_PATH . "'</div>";
}
// Determine if we're on the stories page
$is_stories_page = ($current_page === 'stories');
// Check if the request is for modal content
$is_modal_request = (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') || isset($_GET['modal']);
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Is modal request: " . ($is_modal_request ? 'Yes' : 'No') . "</div>";
}
$sql = "SELECT id, title, content, code, code_type, image, button_link, button_text, position, model, date_edited, theme_img, img_role, chk_divider
FROM web_content
WHERE page = ? AND status = ?
ORDER BY position ASC, date_edited DESC";
$stmt = $conn->prepare($sql);
if (!$stmt) {
die("Prepare failed: " . $conn->connect_error);
}
$stmt->bind_param("ss", $current_page, $status);
$stmt->execute();
$result = $stmt->get_result();
$sections = [];
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$sections[] = $row;
}
}
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Fetched " . count($sections) . " sections for page '$current_page'</div>";
}
// Group sections by position
$sections_by_position = [];
foreach ($sections as $row) {
$position = $row['position'] ?? 1;
$sections_by_position[$position][] = $row;
}
if (!empty($sections_by_position)) {
ksort($sections_by_position);
$current_index = 0;
foreach ($sections_by_position as $position => $group) {
$current_index++;
$use_default_divider = true;
$has_background_image = false;
foreach ($group as $row) {
if (!empty($row['theme_img']) && $row['img_role'] === 'Background') {
$has_background_image = true;
$use_default_divider = false;
break;
}
}
if (isset($group[0]['chk_divider'])) {
$use_default_divider = $group[0]['chk_divider'] == 1;
}
if ($is_modal_request) {
foreach ($group as $index => $row) {
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Rendering modal section ID: {$row['id']} at position: $position</div>";
}
echo "<div class=\"modal-story-content\">";
if (!empty($row['title'])) {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image modal-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
} elseif ($row['model'] === 'title-text-code' && !empty($row['code']) && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
if (!empty($row['content'])) {
echo "<div class=\"generic-content align-center\">" . $row['content'] . "</div>";
}
if (DEBUG) {
echo "<div style='color: purple; font-weight: bold; text-align: center;'>Debug: Modal content length: " . strlen($row['content']) . " characters</div>";
}
echo "</div>";
if ($index < count($group) - 1 || $current_index < count($sections_by_position)) {
echo "<div class=\"modal-section-separator\"></div>";
}
}
} else {
if (count($group) > 1) {
$column_count = min(count($group), 3);
$extra_class = ($current_page === 'task-map') ? ' task-map-section' : '';
echo "<section class=\"section-hero section-hero--full layout-$column_count-column$extra_class\">";
echo "<div class=\"section-hero__content\">";
foreach ($group as $index => $row) {
echo "<div class=\"column column-$index\">";
if (!empty($row['theme_img']) && $row['img_role'] === 'Background') {
$background_image = IMAGE_BASE_PATH . htmlspecialchars($row['theme_img']);
echo "<div class=\"background-image-wrapper\" style=\"background-image: url('$background_image');\"></div>";
}
if ($current_page === 'faq') {
echo "<h1 class=\"align-center faq-question\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center faq-answer\">" . $row['content'] . "</div>";
} else {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center\">";
if ($is_stories_page) {
$content = strip_tags($row['content']);
$preview = mb_substr($content, 0, 60, 'UTF-8');
if (mb_strlen($content, 'UTF-8') > 60) {
$preview .= '...';
}
echo htmlspecialchars($preview);
} else {
echo $row['content'];
}
echo "</div>";
}
if ($row['model'] === 'title-text-code' && !empty($row['code']) && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
$encodedCode = json_encode($row['code'], JSON_HEX_TAG);
echo "<script>window.contentCode = window.contentCode || []; window.contentCode.push({id: '{$row['id']}', code: " . $encodedCode . ", type: '{$row['code_type']}'});</script>";
if (DEBUG) {
echo "<div style='color: orange; display: none;'>Debug: Embed code for ID ${row['id']} (${row['code_type']}): ${row['code']}</div>";
}
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
}
if (!empty($row['button_text'])) {
$button_text = htmlspecialchars($row['button_text']);
echo "<div class=\"content__buttons\">";
if ($is_stories_page) {
$modal_id = 'modal-content-' . $row['id'];
echo "<div id=\"$modal_id\" style=\"display:none;\">";
echo '<div class="modal-story-content">';
if (!empty($row['title'])) {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image modal-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
} elseif ($row['model'] === 'title-text-code' && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
if (!empty($row['content'])) {
echo "<div class=\"generic-content align-center\">" . $row['content'] . "</div>";
}
if (DEBUG) {
echo "<div style='color: purple; font-weight: bold; text-align: center;'>Debug: Modal content length: " . strlen($row['content']) . " characters</div>";
}
echo '</div>';
echo "</div>";
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-id=\"$modal_id\">$button_text</a>";
if (DEBUG) {
echo "<div style='color: orange; font-weight: bold; text-align: center;'>Debug: Modal trigger rendered for ID: $modal_id with button text: $button_text</div>";
}
} else {
$button_link = htmlspecialchars($row['button_link'] ?: '');
if (!empty($button_link) && $row['button_link'] !== '#') {
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-link=\"$button_link\">$button_text</a>";
} else {
echo "<a class=\"myButton\" href=\"#\">$button_text</a>";
}
}
echo "</div>";
}
echo "</div>";
}
echo "</div>";
echo "</section>";
} else {
$row = $group[0];
$extra_class = ($current_page === 'task-map') ? ' task-map-section' : '';
$background_style = $has_background_image ? " style=\"background-image: url('" . IMAGE_BASE_PATH . htmlspecialchars($row['theme_img']) . "');\"" : '';
echo "<div class=\"section-hero section-hero--full$extra_class\"$background_style>";
echo "<div class=\"section-hero__content\">";
if ($current_page === 'faq') {
echo "<h1 class=\"align-center faq-question\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center faq-answer\">" . $row['content'] . "</div>";
} else {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center\">";
if ($is_stories_page) {
$content = strip_tags($row['content']);
$preview = mb_substr($content, 0, 60, 'UTF-8');
if (mb_strlen($content, 'UTF-8') > 60) {
$preview .= '...';
}
echo htmlspecialchars($preview);
} else {
echo $row['content'];
}
echo "</div>";
}
if ($row['model'] === 'title-text-code' && !empty($row['code']) && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
$encodedCode = json_encode($row['code'], JSON_HEX_TAG);
echo "<script>window.contentCode = window.contentCode || []; window.contentCode.push({id: '{$row['id']}', code: " . $encodedCode . ", type: '{$row['code_type']}'});</script>";
if (DEBUG) {
echo "<div style='color: orange; display: none;'>Debug: Embed code for ID ${row['id']} (${row['code_type']}): ${row['code']}</div>";
}
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
}
if (!empty($row['button_text'])) {
$button_text = htmlspecialchars($row['button_text']);
echo "<div class=\"content__buttons\">";
if ($is_stories_page) {
$modal_id = 'modal-content-' . $row['id'];
echo "<div id=\"$modal_id\" style=\"display:none;\">";
echo '<div class="modal-story-content">';
if (!empty($row['title'])) {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image modal-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
} elseif ($row['model'] === 'title-text-code' && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
if (!empty($row['content'])) {
echo "<div class=\"generic-content align-center\">" . $row['content'] . "</div>";
}
if (DEBUG) {
echo "<div style='color: purple; font-weight: bold; text-align: center;'>Debug: Modal content length: " . strlen($row['content']) . " characters</div>";
}
echo '</div>';
echo "</div>";
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-id=\"$modal_id\">$button_text</a>";
if (DEBUG) {
echo "<div style='color: orange; font-weight: bold; text-align: center;'>Debug: Modal trigger rendered for ID: $modal_id with button text: $button_text</div>";
}
} else {
$button_link = htmlspecialchars($row['button_link'] ?: '');
if (!empty($button_link) && $row['button_link'] !== '#') {
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-link=\"$button_link\">$button_text</a>";
} else {
echo "<a class=\"myButton\" href=\"#\">$button_text</a>";
}
}
echo "</div>";
}
echo "</div>";
echo "</div>";
}
}
if ($current_index < count($sections_by_position) && !$is_modal_request) {
if ($use_default_divider) {
echo "<div class=\"separator\"><img src=\"https://admin.nlt-chaplaincy.org/public/down_arrow.png\" alt=\"Default Separator\" class=\"separator-image\"></div>";
} elseif (!empty($row['theme_img']) && $row['img_role'] === 'Separator') {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['theme_img']);
echo "<div class=\"separator\"><img src=\"$image_url\" alt=\"Custom Separator\" class=\"separator-image\"></div>";
}
}
if (DEBUG) {
echo "<div style=\"color: green; font-weight: bold; text-align: center;\">Debug: Section with position $position rendered successfully with " . count($group) . " items.</div>";
}
}
} else {
echo "No sections found.";
}
// Modal container (only for non-AJAX requests)
if (!$is_modal_request) {
echo '<div id="story-modal" class="modal">';
echo '<div class="modal-content">';
echo '<span class="modal-close">×</span>';
echo '<div id="modal-body"></div>';
echo '</div>';
echo '</div>';
}
$stmt->close();
$conn->close();
?>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Synchronize with PHP DEBUG setting
const DEBUG = <?php echo DEBUG ? 'true' : 'false'; ?>;
// Debug log setup
let debugLog = null;
if (DEBUG) {
debugLog = document.createElement('div');
debugLog.id = 'debug-log';
debugLog.style.position = 'fixed';
debugLog.style.bottom = '10px';
debugLog.style.left = '10px';
debugLog.style.background = 'rgba(0, 0, 0, 0.8)';
debugLog.style.color = 'white';
debugLog.style.padding = '10px';
debugLog.style.zIndex = '1000';
debugLog.style.maxHeight = '200px';
debugLog.style.overflowY = 'auto';
document.body.appendChild(debugLog);
}
function logDebug(message, color = 'green') {
if (DEBUG && debugLog) {
debugLog.insertAdjacentHTML('beforeend', `<div style="color: ${color}; font-weight: bold;">Debug: ${message}</div>`);
debugLog.scrollTop = debugLog.scrollHeight;
}
if (DEBUG && console) console.log(`Debug: ${message}`, { color });
}
if (DEBUG) logDebug('Modal script loaded');
const modal = document.getElementById('story-modal');
const modalBody = document.getElementById('modal-body');
const closeBtn = document.querySelector('.modal-close');
const triggers = document.querySelectorAll('.modal-trigger');
if (DEBUG) logDebug('Found ' + triggers.length + ' modal triggers');
// Function to render embed blocks with synchronized SDK
function renderEmbed(item) {
const container = document.getElementById(`embed-${item.id}`);
if (!container) {
if (DEBUG) logDebug(`Container not found for embed ID ${item.id}`, 'red');
return;
}
// Extract components with flexible matching
const divMatch = item.code.match(/<div\s+[^>]*id="[^"]+"[^>]*>/i);
const buttonMatch = item.code.match(/<script>\s*paypal\.Buttons\([\s\S]*?\)\.render\(['"][^'"]+['"]\);\s*<\/script>/i);
if (DEBUG) {
logDebug(`Div match for ID ${item.id}: ${divMatch ? 'Success' : 'Failed'}`, divMatch ? 'green' : 'red');
logDebug(`Button match for ID ${item.id}: ${buttonMatch ? 'Success' : 'Failed'}`, buttonMatch ? 'green' : 'red');
}
if (item.type === 'PayPal' && divMatch && buttonMatch) {
// Insert div with unique ID
const uniqueId = `paypal-button-container-${item.id}`;
let divContent = divMatch[0].replace(/id="[^"]+"/, `id="${uniqueId}"`);
container.innerHTML = divContent;
if (DEBUG) logDebug(`Inserted div for PayPal ID ${item.id}`, 'orange');
// Wait for SDK to be available
function waitForSDK(callback) {
if (typeof paypal !== 'undefined') {
if (DEBUG) logDebug(`PayPal SDK available for ID ${item.id}`, 'green');
callback();
} else {
if (DEBUG) logDebug(`Checking SDK for ID ${item.id}, status: ${typeof paypal}`, 'yellow');
setTimeout(() => waitForSDK(callback), 100);
}
}
// Extract and adjust button script
let scriptContent = buttonMatch[0].replace(/^<script>|<\/script>$/g, '').trim();
scriptContent = scriptContent.replace(/\.render\(['"][^'"]+['"]\)/, `.render('#${uniqueId}')`);
waitForSDK(() => {
const buttonScript = document.createElement('script');
buttonScript.textContent = scriptContent;
document.body.appendChild(buttonScript);
if (DEBUG) logDebug(`Rendered PayPal button script for ID ${item.id}`, 'orange');
});
} else if (item.type === 'YouTube') {
container.innerHTML = item.code;
container.style.display = 'block';
if (DEBUG) logDebug(`Rendered YouTube embed for ID ${item.id}`, 'orange');
} else {
container.innerHTML = `<div class="embed-fallback" id="fallback-${item.id}">${item.code}</div>`;
container.style.display = 'block';
if (DEBUG) logDebug(`Fallback rendered for ID ${item.id} (parsing failed, scripts not executed)`, 'red');
}
}
// Process embed blocks
if (window.contentCode && Array.isArray(window.contentCode)) {
window.contentCode.forEach(item => {
renderEmbed(item);
});
} else if (DEBUG) {
logDebug('contentCode is not an array or unavailable', 'red');
}
function openModal(content) {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = content;
const buttons = tempDiv.querySelectorAll('.content__buttons');
buttons.forEach(button => button.remove());
const debugMessages = tempDiv.querySelectorAll('div[style*="color: purple"], div[style*="color: blue"], div[style*="color: red"], div[style*="color: green"]');
debugMessages.forEach(msg => msg.remove());
let combinedContent = '';
const sections = tempDiv.querySelectorAll('.modal-story-content');
if (DEBUG) logDebug('Found ' + sections.length + ' modal-story-content sections');
if (sections.length > 0) {
sections.forEach((section, index) => {
combinedContent += section.outerHTML.trim();
if (index < sections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const fallbackSections = tempDiv.querySelectorAll('.section-hero__content');
if (DEBUG) logDebug('Found ' + fallbackSections.length + ' section-hero__content sections');
if (fallbackSections.length > 0) {
fallbackSections.forEach((section, index) => {
const title = section.querySelector('h1');
const image = section.querySelector('.content-image');
const content = section.querySelector('.generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
if (title) newContent.appendChild(title.cloneNode(true));
if (image) newContent.appendChild(image.cloneNode(true));
if (content) newContent.appendChild(content.cloneNode(true));
combinedContent += newContent.outerHTML.trim();
if (index < fallbackSections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const genericContent = tempDiv.querySelector('.generic-content');
if (genericContent) {
if (DEBUG) logDebug('Falling back to .generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
newContent.appendChild(genericContent.cloneNode(true));
combinedContent = newContent.outerHTML.trim();
} else {
if (DEBUG) logDebug('No content found in .modal-story-content, .section-hero__content, or .generic-content', 'red');
combinedContent = '<p>Content could not be parsed from the page.</p>';
}
}
}
modalBody.innerHTML = combinedContent;
modal.style.display = 'block';
modal.setAttribute('aria-hidden', 'false');
if (modalBody.children.length > 0 && closeBtn) {
closeBtn.focus();
}
if (DEBUG) logDebug('Modal opened');
}
function closeModal() {
modal.style.display = 'none';
modal.setAttribute('aria-hidden', 'true');
modalBody.innerHTML = '';
if (DEBUG && debugLog) {
debugLog.innerHTML = '';
}
if (DEBUG) logDebug('Modal closed');
}
if (modal && modalBody && closeBtn && triggers) {
triggers.forEach(trigger => {
trigger.addEventListener('click', function(e) {
e.preventDefault();
const modalId = this.getAttribute('data-modal-id');
if (modalId) {
const contentDiv = document.getElementById(modalId);
if (contentDiv) {
const content = contentDiv.innerHTML;
if (DEBUG) logDebug('Stories modal triggered, content from ID: ' + modalId);
if (DEBUG) logDebug('Modal content length: ' + content.length + ' characters', 'purple');
openModal(content);
} else {
openModal('<p>Content not found.</p>');
if (DEBUG) logDebug('Modal content not found for ID: ' + modalId, 'red');
}
return;
}
const link = this.getAttribute('data-modal-link');
if (DEBUG) logDebug('Trigger clicked, link: ' + link);
if (!link || link === '#' || link.includes('index.php')) {
openModal('<p>This link cannot be loaded in a modal to prevent recursive loading.</p>');
return;
}
let basePath = window.location.origin;
let absoluteLink;
try {
if (link.startsWith('http://') || link.startsWith('https://')) {
absoluteLink = link;
} else if (link.startsWith('/')) {
absoluteLink = new URL(link, window.location.origin).href;
} else {
absoluteLink = new URL(link, window.location.origin + '/').href;
}
absoluteLink += (absoluteLink.includes('?') ? '&' : '?') + 'modal=1';
if (DEBUG) logDebug('Fetching absolute link: ' + absoluteLink);
} catch (error) {
if (DEBUG) logDebug('URL construction error: ' + error.message, 'red');
openModal('<p>Invalid URL format.</p>');
return;
}
openModal('<p>Loading...</p>');
fetch(absoluteLink, {
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => {
if (DEBUG) logDebug('Fetch response status: ' + response.status + ' ' + response.statusText);
if (!response.ok) {
throw new Error('Network response was not ok: ' + response.statusText);
}
return response.text();
})
.then(data => {
if (DEBUG) logDebug('Fetched HTML length: ' + data.length);
const parser = new DOMParser();
const doc = parser.parseFromString(data, 'text/html');
let combinedContent = '';
const sections = doc.querySelectorAll('.modal-story-content');
if (DEBUG) logDebug('Found ' + sections.length + ' modal-story-content sections in fetched content');
if (sections.length > 0) {
sections.forEach((content, index) => {
combinedContent += content.outerHTML.trim();
if (index < sections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const fallbackSections = doc.querySelectorAll('.section-hero__content');
if (DEBUG) logDebug('Found ' + fallbackSections.length + ' section-hero__content sections');
if (fallbackSections.length > 0) {
fallbackSections.forEach((section, index) => {
const title = section.querySelector('h1');
const image = section.querySelector('.content-image');
const content = section.querySelector('.generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
if (title) newContent.appendChild(title.cloneNode(true));
if (image) newContent.appendChild(image.cloneNode(true));
if (content) newContent.appendChild(content.cloneNode(true));
combinedContent += newContent.outerHTML.trim();
if (index < fallbackSections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const genericContent = doc.querySelector('.generic-content');
if (genericContent) {
if (DEBUG) logDebug('Falling back to .generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
newContent.appendChild(genericContent.cloneNode(true));
combinedContent = newContent.outerHTML.trim();
} else {
if (DEBUG) logDebug('No content found in .modal-story-content, .section-hero__content, or .generic-content', 'red');
combinedContent = '<p>Content could not be parsed from the page.</p>';
}
}
}
if (combinedContent) {
openModal(combinedContent);
} else {
openModal('<p>No content found.</p>');
}
})
.catch(error => {
if (DEBUG) logDebug('Fetch error: ' + error.message, 'red');
openModal('<p>Sorry, the content could not be loaded: ' + error.message + '</p>');
});
});
});
closeBtn.addEventListener('click', closeModal);
window.addEventListener('click', function(event) {
if (event.target === modal) {
closeModal();
}
});
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && modal.style.display === 'block') {
closeModal();
}
});
} else {
if (DEBUG) logDebug('Modal elements missing (modal, modalBody, closeBtn, or triggers)', 'red');
}
});
</script>
checkSDK interval with a waitForSDK recursive function that delays the script execution until typeof paypal is defined, ensuring the button script runs only after the SDK is available.code column for IDs 58-61 contains the standardized button codes without the SDK load (as updated previously):
$200 with plan_id: 'P-3FU48207V4555173AM5STYUA'$500 with plan_id: 'P-7G7358239N945925DM5ST2XY'$2000 with plan_id: 'P-1N7946829C436443CM5ST37I'$10000 with plan_id: 'P-06X02949MG546820SM5ST5QA'code_type is PayPal for all.pull-contents.php with the 638-line V2.30 code.https://www.nlt-chaplaincy.org/index.html and check sections at positions 100-103.subscriptionID).Button match: Success, Inserted div, Rendered PayPal button script, and PayPal SDK available for all IDs (58-61).PayPal SDK preload error:).renderEmbed or check for CSP or network issues in the browser console.Please deploy, test, and let me know the results! This adjustment should align the SDK availability with the button rendering.
Now, let's check if PP sections are having the same multi-column behaviour as other sections? The core logic is:
It's almost there! The PP columns are now displayed with the intended multi-column, show/hide and ordering logic. However, in the mobile view, the PP buttons should resize automatically to the single-column full width instead of displaying in multi-column-adapting smaller size like the desktop view.
Since I'm away from my computer, before testing this new version, can you check if the PHP/CSS is handling column width properly? Now, I see when PP sections are displayed in two columns (Two sections sharing the same position) the two sessions are not taking the full width of the content frame. What's expected is when two columns are shown, they should automatically adjust to take 50% of the width, and when three columns are shown, each should take 33% of the width in a dynamic manner. The pastor has also requested to show the image for a PP section so that the team can try uploading graphics that highlight the different amounts. If so, I think we will have to expand the "model" field to include both "title-text-code" and "title-text-image-code" options, and adjust the rendering logic accordingly.
Okay, let's keep the CSS in the PHP for now. V2.33 has perfect display for desktop view but the buttons are overflowing the display area when viewed on mobile. I think we should adjust the width of the buttons for just the mobile view.
V2.34 didn't solve the problem. The PP buttons are still overflowing the display area.
This fix still fails. Why PP buttons were showing correctly before we adjusted the desktop multi-column display? Would the problem be in our earlier fix instead?
Um..this version still fails. If my understanding is right, desktop and mobile views can use a completely different display methods so our fix for desktop should not have any effect on the mobile view. If this is true, can we just reuse the pre-V2.32 display method? Or, is the desktop view fix will somewhat affect the mobile view that we need to change both desktop/mobile views' display methods altogether?
Thank your for this significant fix! I think things are much better in general. Attached are two screenshots that show the remaining issue. The first one is showing the desktop view where the PP buttons are left-aligned and in different sizes (Seems to be affected by the length of the title) , as indicated by the red lines. The expected display should be for ALL buttons to be of the same width and center-aligned. The 2nd one is the mobile view. Similarly, buttons are left-aligned instead of centered. What's good is buttons are of the same widths.


·---
custom.css (V4.9) uses display: grid for desktop layouts, which respects the natural width of .content-embed and .paypal-button. The varying widths likely stem from the PayPal SDK applying inline styles based on the container or title context. The lack of a fixed width or explicit centering in the Grid setup is causing the left alignment.display: block layout on mobile stacks the .column elements vertically, and the .content-embed and .paypal-button are set to width: 100% !important with max-width: none !important. The left alignment suggests the .content__buttons or .content-embed container isn’t being centered properly..paypal-button (e.g., 300px, a common PayPal default) and use margin: 0 auto to center it within .content-embed..content-embed respects this width and centers its content.text-align: center to .content__buttons to center the .paypal-button within its container.width: 100% !important to maintain consistent widths.custom.css:
pull-contents.php:
custom.css (V4.10)/* Custom CSS for Lifenavi (navi.claudioflute.live) and Chaplaincy Admin (admin.nlt-chaplaincy.org) - Version 4.10 */
/* Shared styles for both systems, with domain-specific overrides as noted */
/* Ensure myButton overrides theme styles */
.content__buttons a.myButton {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
a.myButtonBig {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Button Styles */
.myButtonBig {
background: linear-gradient(to bottom, #44c767 5%, #5cbf2a 100%);
background-color: #44c767;
border-radius: 28px;
border: 1px solid #18ab29;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 21px;
font-weight: bold;
padding: 24px 42px;
text-decoration: none;
text-shadow: 0px 1px 0px #2f6627;
transition: all 0.3s ease;
}
.myButtonBig:hover {
background: linear-gradient(to bottom, #5cbf2a 5%, #44c767 100%);
background-color: #5cbf2a;
border-color: #137c21;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.myButtonBig:active {
position: relative;
top: 1px;
background: linear-gradient(to bottom, #3ba052 5%, #4aa62b 100%);
background-color: #3ba052;
border-color: #0f5c18;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
}
.myButton {
background: linear-gradient(to bottom, #44c767 5%, #5cbf2a 100%);
background-color: #44c767;
border-radius: 28px;
border: 1px solid #18ab29;
display: inline-block;
cursor: pointer;
color: #ffffff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 17px;
font-weight: bold;
padding: 16px 31px;
text-decoration: none;
text-shadow: 0px 1px 0px #2f6627;
transition: all 0.3s ease;
}
.myButton:hover {
background: linear-gradient(to bottom, #5cbf2a 5%, #44c767 100%);
background-color: #5cbf2a;
border-color: #137c21;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.myButton:active {
position: relative;
top: 1px;
background: linear-gradient(to bottom, #3ba052 5%, #4aa62b 100%);
background-color: #3ba052;
border-color: #0f5c18;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
}
/* Set default font for the entire site */
body {
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Test class to verify font loading */
.font-test {
font-family: "LXGW WenKai TC", "Times New Roman", serif;
font-size: 24px;
color: red;
}
/* Dynamic Section Styles */
.content__entry {
position: relative;
padding: 20px;
min-height: 200px;
margin: 0 auto;
max-width: 1200px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #fff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Hide empty content__entry div from Publii theme */
div.content__entry:empty {
display: none;
}
/* Alternative: Hide content__entry div on dynamic pages (uncomment and add data-page-type="dynamic" to <body> if needed) */
/* body[data-page-type="dynamic"] div.content__entry {
display: none;
} */
.section-hero--full {
width: auto;
position: relative;
left: 0;
transform: none;
margin: 0 auto;
max-width: 1200px;
min-height: 400px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: #fff;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.section-hero--column {
flex: 1;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
padding: 10px;
}
.section-group {
display: flex;
flex-wrap: nowrap; /* Prevent wrapping to new rows */
gap: 20px;
max-width: 1200px;
margin: 0 auto;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.layout-2-column {
display: flex;
justify-content: space-between;
}
.layout-2-column .section-hero--column {
flex: 1 0 49%; /* Slightly less than 50% to account for gap */
max-width: 49%;
}
.layout-3-column {
display: flex;
justify-content: space-between;
}
.layout-3-column .section-hero--column {
flex: 1 0 32%; /* Slightly less than 33.33% to account for gap */
max-width: 32%;
}
/* Layout and Button Styling (Moved from pull-contents.php) */
@media (min-width: 768px) {
.section-hero--full.layout-2-column .section-hero__content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.section-hero--full.layout-3-column .section-hero__content {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 20px;
}
.column {
width: 100%; /* Ensure columns take full width in grid */
}
.content-embed {
width: 300px; /* Fixed width for uniformity */
margin: 0 auto; /* Center the embed container */
text-align: center; /* Center the button within */
}
.paypal-button {
width: 300px !important; /* Fixed width for all buttons */
max-width: 300px !important; /* Prevent overflow or shrinkage */
box-sizing: border-box; /* Include padding in width */
margin: 0 auto; /* Center the button */
}
}
@media (max-width: 767px) {
.section-hero--full .section-hero__content {
display: block; /* Stack vertically on mobile */
}
.column {
margin-bottom: 20px; /* Add spacing between stacked sections */
width: 100%; /* Ensure full width on mobile */
}
.content-embed {
width: 100% !important; /* Force full width on mobile, overriding SDK styles */
}
.paypal-button {
width: 100% !important; /* Force PayPal button to full width on mobile */
max-width: none !important; /* Remove any max-width constraints */
}
.content__buttons {
text-align: center !important; /* Center align buttons on mobile */
}
}
/* Alignment Classes */
.align-left {
text-align: left;
}
.content-image.align-left, .video-embed.align-left {
margin: 1em 0;
}
.align-center {
text-align: center;
}
/* Override theme's heading font variable */
h1, h2, h3, h4, h5, h6 {
font-family: "LXGW WenKai TC", "Times New Roman", serif !important;
margin-bottom: 1.5em !important;
}
/* Ensure specific heading styles inherit the font */
.content__entry h1 {
font-size: 2em;
font-weight: 700;
line-height: 1.2;
color: #333;
margin-bottom: 1.5em !important;
padding-top: 1em;
text-align: center;
text-shadow: none;
font-family: "LXGW WenKai TC", "Times New Roman", serif !important;
}
.generic-content {
margin: 0 auto;
max-width: 800px;
font-size: 1em;
line-height: 1.6;
color: #333;
margin-bottom: 1em;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry[style*="background-image"] h1,
.content__entry[style*="background-image"] .generic-content {
color: #fff;
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
}
.generic-content p {
margin: 0 0 1em 0;
}
.generic-content ul,
.generic-content ol {
margin: 0 0 1em 0;
padding: 0 !important;
list-style: none !important;
}
.generic-content li {
margin-bottom: 0.5em;
text-align: inherit;
list-style: none !important;
}
.generic-content ul[style*="list-style"],
.generic-content ol[style*="list-style"],
.generic-content li[style*="list-style"] {
list-style: none !important;
}
.content__buttons {
text-align: center !important; /* Default center alignment */
margin: 2em 0 1em 0;
}
.content__buttons a.myButton {
display: inline-block;
margin: 0 auto;
}
.content__entry .content__buttons {
text-align: center !important;
}
.welcome-image {
max-width: 100%;
height: auto;
margin: 1em auto;
display: block;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.video-embed {
position: relative;
padding-bottom: 56.25%;
height: 0;
overflow: hidden;
margin: 1em auto;
max-width: 800px;
background: none;
}
.video-embed iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
.separator {
text-align: center;
margin: 60px 0 20px 0;
}
.content__entry.content__entry--full:first-child {
min-height: 0 !important;
padding-top: 0 !important;
margin-top: 0 !important;
}
.main.page .main__right:first-child {
margin-top: -3.8rem !important;
}
.main.page .main__right {
margin: 0% !important;
}
.banner--after-content {
margin: 0 !important;
padding: 0 !important;
border: none !important;
outline: none !important;
}
.top__item--right {
border: none !important;
outline: none !important;
box-shadow: none !important;
}
@media (max-width: 768px) {
.main.page .main__right:first-child {
margin-top: 0 !important;
margin-bottom: 0 !important;
}
.main.page .container:first-child,
.main.page .post__entry:first-child {
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
.main.page .main__right .main__right--bottom:first-child {
margin-top: -3.8rem !important;
margin-bottom: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
.main.page .container > .main__right > .main__right--bottom:first-child,
.main.page .post__entry > .main__right > .main__right--bottom:first-child {
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
min-height: 0 !important;
}
.banner--after-content {
margin: 0 !important;
padding: 0 !important;
border: none !important;
outline: none !important;
}
.top__item--right {
border: none !important;
outline: none !important;
box-shadow: none !important;
}
}
@media (min-width: 769px) and (max-width: 1023px) {
.main.page .main__right {
margin: 0 auto !important;
max-width: 90% !important;
width: auto !important;
}
.main.page .main__right .content__entry--full {
margin: 0 auto !important;
max-width: 100% !important;
}
.main.page .main__right .main__right--bottom {
margin: 0 auto !important;
max-width: 100% !important;
}
.top__item--right {
border: none !important;
outline: none !important;
box-shadow: none !important;
}
}
.main.page .main__right .main__right--bottom .section-hero--full:first-child {
margin-top: 0 !important;
padding-top: 0 !important;
}
.content__entry.content__entry--full .separator:first-child {
margin-top: 0;
}
.section-hero--full:not([style*="background-image"]) + .separator {
margin-top: 40px;
}
.separator-image {
max-width: 100%;
height: auto;
display: block;
margin: 0 auto;
}
.separator img[src$="down_arrow.png"] {
max-width: 256px;
}
hr {
display: none !important;
visibility: hidden !important;
}
.post__content hr,
.container hr,
.post__content hr[style],
.container hr[style] {
display: none !important;
visibility: hidden !important;
}
.post__content::before,
.post__content::after,
.container::before,
.container::after,
.post__entry::before,
.post__entry::after,
.content__entry::before,
.content__entry::after,
.generic-content::before,
.generic-content::after {
display: none !important;
border: none !important;
content: none !important;
}
.separator::before,
.separator::after {
display: none !important;
border: none !important;
content: none !important;
}
body,
body p,
body h2,
body h3,
body h4,
body h5,
body h6,
.post__content,
.post__content p,
.post__content h2,
.post__content h3,
.post__content h4,
.post__content h5,
.post__content h6,
.container,
.container p,
.container h2,
.container h3,
.container h4,
.container h5,
.container h6 {
color: #333 !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
h1.post__title,
h1.hero__title,
h1.site__title {
color: #fff !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
a.button,
a.btn,
a.post__button,
.post__content a.button,
.post__content a.btn,
.post__content a.post__button,
.container a.button,
.container a.btn,
.container a.post__button {
text-decoration: none !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Custom Modal Styles */
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
background-color: #fff;
margin: 5% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 800px;
min-height: 200px;
position: relative;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
}
.modal-close {
color: #aaa;
position: absolute;
top: 10px;
right: 20px;
font-size: 28px;
font-weight: bold;
cursor: pointer;
transition: color 0.3s ease;
z-index: 1001;
}
.modal-close:hover,
.modal-close:focus {
color: #000;
text-decoration: none;
}
#modal-body {
font-size: 1em;
line-height: 1.6;
color: #333;
max-width: 100%;
box-sizing: border-box;
padding-top: 40px;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
overflow-x: hidden;
}
#modal-body h1 {
font-size: 1.5em;
margin-bottom: 0.5em;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
#modal-body p {
margin-bottom: 1em;
}
#modal-body * {
max-width: 100%;
height: auto;
box-sizing: border-box;
}
#modal-body img,
#modal-body div,
#modal-body table {
max-width: 100%;
height: auto;
}
#modal-body .welcome-image {
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.modal[aria-hidden="false"] {
display: block;
}
.modal-close:focus {
outline: 2px solid #44c767;
outline-offset: 2px;
}
/* Custom separator for modal sections */
.modal-section-separator {
text-align: center;
margin: 20px 0;
font-size: 24px;
line-height: 1;
color: #666;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.modal-section-separator::before {
content: "···";
}
/* Modal-specific content container */
.modal-story-content {
max-width: 100%;
margin: 0 auto;
padding: 20px;
box-sizing: border-box;
overflow-x: hidden;
}
.modal-story-content h1 {
font-size: 2rem;
margin-bottom: 1rem;
text-align: center;
}
.modal-story-content .content-image {
max-width: 100%;
margin: 1rem 0;
}
.modal-story-content .generic-content {
font-size: 1rem;
line-height: 1.6;
}
/* Chaplaincy Admin specific overrides */
.report-container {
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry {
max-width: 100% !important;
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
box-sizing: border-box !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
.content__entry table.report-table {
width: 100% !important;
margin: 0 !important;
padding: 0 !important;
border-collapse: collapse !important;
box-sizing: border-box !important;
font-family: "LXGW WenKai TC", "Times New Roman", serif;
}
/* Ensure background image applies to the section */
.section-hero--full[style*="background-image"] .section-hero__content,
.section-group[style*="background-image"] .section-hero__content {
background: none;
}
/* Add to custom.css or a Chaplaincy-specific file */
html, body {
overflow-x: hidden;
width: 100%;
margin: 0;
padding: 0;
}
.main.page, .container, .post__entry {
width: 100%;
max-width: 100%;
overflow-x: hidden;
}
/* PP Button Layout Adjustments */
@media (min-width: 769px) {
.layout-3-column.position-100 .section-hero--column {
flex: 1 0 32%;
max-width: 32%;
}
}
@media (max-width: 768px) {
.layout-3-column.position-100 .section-hero--column {
flex: 1 0 100%;
max-width: 100%;
}
}
.section-group.position-100,
.section-hero--full {
margin-top: 2em;
}
.content-embed to width: 300px and margin: 0 auto to center it within the Grid column..paypal-button to width: 300px !important and max-width: 300px !important to enforce uniform width, with margin: 0 auto for centering.text-align: center !important to .content__buttons to center the .paypal-button within its container.width: 100% !important and max-width: none !important for consistent full-width behavior.custom.css to V4.10.custom.css with the V4.10 content.https://www.nlt-chaplaincy.org/index.html and navigate to position 100..paypal-button computed styles (width and alignment) on both desktop and mobile.margin: 0 auto and text-align: center should resolve the alignment issues. If centering still fails, it might be due to the PayPal SDK’s inline styles overriding ours—share the computed styles, and we can add more specific selectors or !important flags..paypal-button and its parents. Share the output, and we can refine the CSS further.Please deploy, test, and let me know the results! This should align the buttons correctly and standardize their widths.
With this fix, the PP buttons and the ENTIRE content area are moved outside of the right frame (I remember it's called something like main_right in the CSS) and bleeding onto the left frame on desktop view. For mobile view, the buttons are overflowing outside of the display area again as before.
It's still not restored. Since the layout is important, let's revert to the original layout (Button left-aligned but other things were fine) first and you may then review our previous display method where everything were fine except that the buttons are shrunken to see if there are any insights. Or, you may use CSS in PHP temporarily to help figure out the cause of this layout disruption.
There is no change with this version on the layout (Buttons left aligned on both views, shrunken buttons on mobile view) though I see new floating debug message:
Debug: Adjusted PayPal button paypal-button-container-58 width and margin Debug: Adjusted PayPal button paypal-button-container-59 width and margin Debug: Adjusted PayPal button paypal-button-container-60 width and margin Debug: Adjusted PayPal button paypal-button-container-61 width and margin
I wonder would disabling multi-column display once and for all for mobile view can solve this tricky problem?
V2.47 restores all PP buttons to the original size on both views and the buttons are not overflowing in the mobile view. However, multi-column layout is missing on desktop view.
This update has caused complications. The left alignment is not solved for both view. Furthermore, the yellow button's bottom has been cut away, with the button surrounded by a border. The lower black button for credit card is entirely missing. This happens in both desktop and mobile views.
Desktop Rendering:
Mobile View:
Desktop Rendering Issue:
renderEmbed function processes each contentCode item sequentially, but the SDK might not handle multiple paypal.Buttons() instances correctly if their containers overlap or if the setTimeout adjustment isn’t applying to all instances. The first black button rendering fully indicates the initial render works, but subsequent embeds fail, possibly due to timing or ID conflicts.uniqueId (paypal-button-container-${item.id}) should prevent ID clashes, but the PayPal iframe styling (e.g., .paypal-buttons, iframe) might be overriding our width constraints, causing the cut-away effect.Mobile Left Alignment:
justify-content: center, margin: 0 auto, and transform: translateX(-50%) suggests a theme or parent container (e.g., .main__right, .section-hero__content) is enforcing a left-aligned layout with higher specificity. The debug log’s computed style output should reveal the overriding rule.Desktop Rendering:
renderEmbed function to handle multiple instances more robustly, adding a delay between renders if needed.Mobile Centering:
.main__right .section-hero--full .column .content-embed-container) and add a wrapper div with explicit centering.pull-contents.php (V2.56)<?php
// pull-contents.php (Version 2.56)
// Debug toggle: Set to true to enable debug messages, false to disable
define('DEBUG', true);
// Define base path for images
define('IMAGE_BASE_PATH', 'https://admin.nlt-chaplaincy.org/images/');
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$config_path = '../config.php';
if (!file_exists($config_path)) {
die("Error: config.php not found at $config_path");
}
require_once $config_path;
if (!isset($dbServer) || !isset($dbUsername) || !isset($dbPassword) || !isset($dbDatabase)) {
die("Error: AppGini database variables not defined in config.php");
}
$conn = new mysqli($dbServer, $dbUsername, $dbPassword, $dbDatabase, $dbPort ?: 3306);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Auto-detect page from calling file if $_GET['page'] not set
if (isset($_GET['page'])) {
$current_page = $_GET['page'];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Page set from GET: '$current_page'</div>";
}
} else {
$calling_file = basename($_SERVER['SCRIPT_FILENAME']);
$request_uri = $_SERVER['REQUEST_URI'];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Calling file: '$calling_file'</div>";
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: REQUEST_URI: '$request_uri'</div>";
}
$current_page = str_replace('.php', '', $calling_file);
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page after str_replace: '$current_page'</div>";
}
if ($current_page === 'index') {
$current_page = 'landing';
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page set to 'landing'</div>";
}
if (preg_match('/\/(task-map)\.php/', $request_uri, $matches)) {
$current_page = $matches[1];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page updated from REQUEST_URI: '$current_page'</div>";
}
}
}
}
$status = 'Show';
// Preload PayPal SDK to support all buttons
$paypalSdkUrl = 'https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription';
echo "<script src=\"$paypalSdkUrl\" id=\"paypal-sdk\" async=\"false\" onload=\"console.log('PayPal SDK preloaded')\" onerror=\"console.error('PayPal SDK preload error:', event)\"></script>";
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Final current_page: '$current_page'</div>";
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Image Base Path: '" . IMAGE_BASE_PATH . "'</div>";
}
// Determine if we're on the stories page
$is_stories_page = ($current_page === 'stories');
// Check if the request is for modal content
$is_modal_request = (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') || isset($_GET['modal']);
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Is modal request: " . ($is_modal_request ? 'Yes' : 'No') . "</div>";
}
$sql = "SELECT id, title, content, code, code_type, image, button_link, button_text, position, model, date_edited, theme_img, img_role, chk_divider
FROM web_content
WHERE page = ? AND status = ?
ORDER BY position ASC, date_edited DESC";
$stmt = $conn->prepare($sql);
if (!$stmt) {
die("Prepare failed: " . $conn->connect_error);
}
$stmt->bind_param("ss", $current_page, $status);
$stmt->execute();
$result = $stmt->get_result();
$sections = [];
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$sections[] = $row;
}
}
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Fetched " . count($sections) . " sections for page '$current_page'</div>";
}
// Group sections by position
$sections_by_position = [];
foreach ($sections as $row) {
$position = $row['position'] ?? 1;
$sections_by_position[$position][] = $row;
}
if (!empty($sections_by_position)) {
ksort($sections_by_position);
$current_index = 0;
foreach ($sections_by_position as $position => $group) {
$current_index++;
$use_default_divider = true;
$has_background_image = false;
$has_paypal = false;
foreach ($group as $row) {
if (!empty($row['theme_img']) && $row['img_role'] === 'Background') {
$has_background_image = true;
$use_default_divider = false;
}
if ($row['code_type'] === 'PayPal') {
$has_paypal = true;
}
}
if (isset($group[0]['chk_divider'])) {
$use_default_divider = $group[0]['chk_divider'] == 1;
}
if ($is_modal_request) {
foreach ($group as $index => $row) {
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Rendering modal section ID: {$row['id']} at position: $position</div>";
}
echo "<div class=\"modal-story-content\">";
if (!empty($row['title'])) {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image modal-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
} elseif ($row['model'] === 'title-text-code' || $row['model'] === 'title-text-image-code' && !empty($row['code']) && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
if (!empty($row['content'])) {
echo "<div class=\"generic-content align-center\">" . $row['content'] . "</div>";
}
if (DEBUG) {
echo "<div style='color: purple; font-weight: bold; text-align: center;'>Debug: Modal content length: " . strlen($row['content']) . " characters</div>";
}
echo "</div>";
if ($index < count($group) - 1 || $current_index < count($sections_by_position)) {
echo "<div class=\"modal-section-separator\"></div>";
}
}
} else {
$column_count = min(count($group), 3);
if ($has_paypal) {
$column_count = 1; // Force single-column for sections with PayPal
}
$extra_class = ($current_page === 'task-map') ? ' task-map-section' : '';
echo "<section class=\"section-hero section-hero--full layout-$column_count-column $extra_class\">";
echo "<div class=\"section-hero__content\">";
// Sort by title for mobile view
usort($group, function($a, $b) {
return strcmp($a['title'], $b['title']);
});
foreach ($group as $index => $row) {
if ($index >= 3 && !$has_paypal) {
continue; // Hide sections beyond the third column on desktop for non-PP
}
echo "<div class=\"column column-$index\">";
if (!empty($row['theme_img']) && $row['img_role'] === 'Background') {
$background_image = IMAGE_BASE_PATH . htmlspecialchars($row['theme_img']);
echo "<div class=\"background-image-wrapper\" style=\"background-image: url('$background_image');\"></div>";
}
if ($current_page === 'faq') {
echo "<h1 class=\"align-center faq-question\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center faq-answer\">" . $row['content'] . "</div>";
} else {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center\">";
if ($is_stories_page) {
$content = strip_tags($row['content']);
$preview = mb_substr($content, 0, 60, 'UTF-8');
if (mb_strlen($content, 'UTF-8') > 60) {
$preview .= '...';
}
echo htmlspecialchars($preview);
} else {
echo $row['content'];
}
echo "</div>";
}
if ($row['model'] === 'title-text-image-code' || $row['model'] === 'title-text-code') {
if (!empty($row['image']) && $row['model'] === 'title-text-image-code') {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
}
if (!empty($row['code']) && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed-container\">";
if ($row['code_type'] === 'PayPal') {
echo "<div class=\"content-embed paypal-embed\" id=\"embed-{$row['id']}\"></div>";
} else {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
$encodedCode = json_encode($row['code'], JSON_HEX_TAG);
echo "<script>window.contentCode = window.contentCode || []; window.contentCode.push({id: '{$row['id']}', code: " . $encodedCode . ", type: '{$row['code_type']}'});</script>";
if (DEBUG) {
echo "<div style='color: orange; display: none;'>Debug: Embed code for ID ${row['id']} (${row['code_type']}): ${row['code']}</div>";
}
echo "</div>";
}
} elseif (!empty($row['image']) && $row['model'] !== 'title-text-image-code') {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
}
if (!empty($row['button_text'])) {
$button_text = htmlspecialchars($row['button_text']);
echo "<div class=\"content__buttons\">";
if ($is_stories_page) {
$modal_id = 'modal-content-' . $row['id'];
echo "<div id=\"$modal_id\" style=\"display:none;\">";
echo '<div class="modal-story-content">';
if (!empty($row['title'])) {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image modal-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
} elseif ($row['model'] === 'title-text-code' || $row['model'] === 'title-text-image-code' && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
if (!empty($row['content'])) {
echo "<div class=\"generic-content align-center\">" . $row['content'] . "</div>";
}
if (DEBUG) {
echo "<div style='color: purple; font-weight: bold; text-align: center;'>Debug: Modal content length: " . strlen($row['content']) . " characters</div>";
}
echo '</div>';
echo "</div>";
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-id=\"$modal_id\">$button_text</a>";
if (DEBUG) {
echo "<div style='color: orange; font-weight: bold; text-align: center;'>Debug: Modal trigger rendered for ID: $modal_id with button text: $button_text</div>";
}
} else {
$button_link = htmlspecialchars($row['button_link'] ?: '');
if (!empty($button_link) && $row['button_link'] !== '#') {
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-link=\"$button_link\">$button_text</a>";
} else {
echo "<a class=\"myButton\" href=\"#\">$button_text</a>";
}
}
echo "</div>";
}
echo "</div>";
}
echo "</div>";
echo "</section>";
}
if ($current_index < count($sections_by_position) && !$is_modal_request) {
if ($use_default_divider) {
echo "<div class=\"separator\"><img src=\"https://admin.nlt-chaplaincy.org/public/down_arrow.png\" alt=\"Default Separator\" class=\"separator-image\"></div>";
} elseif (!empty($row['theme_img']) && $row['img_role'] === 'Separator') {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['theme_img']);
echo "<div class=\"separator\"><img src=\"$image_url\" alt=\"Custom Separator\" class=\"separator-image\"></div>";
}
}
if (DEBUG) {
echo "<div style=\"color: green; font-weight: bold; text-align: center;\">Debug: Section with position $position rendered successfully with " . count($group) . " items.</div>";
}
}
} else {
echo "No sections found.";
}
// Add custom CSS for layout fixes
if ($current_page === 'landing' && strpos($_SERVER['REQUEST_URI'], 'position-100') !== false) {
echo '<style>';
echo '.main__right .section-hero--full {
width: 100% !important;
max-width: 1200px !important;
margin: 0 auto !important;
display: flex !important;
justify-content: center !important;
box-sizing: border-box !important;
overflow: hidden !important;
}';
echo '.main__right .section-hero--full .section-hero__content {
width: 100% !important;
max-width: 100% !important;
margin: 0 auto !important;
padding: 0 !important;
}';
echo '.main__right .section-hero--full .column {
width: 100% !important;
max-width: 100% !important;
padding: 0 !important;
margin: 0 0 20px 0 !important;
box-sizing: border-box !important;
text-align: center !important;
display: flex !important;
justify-content: center !important;
}';
echo '.main__right .section-hero--full .content-embed-container {
display: block !important;
width: 100% !important;
min-width: 300px !important;
max-width: 300px !important;
margin: 0 auto !important;
text-align: center !important;
position: relative !important;
left: 50% !important;
transform: translateX(-50%) !important;
}';
echo '.main__right .section-hero--full .paypal-embed {
width: 100% !important;
min-width: 300px !important;
max-width: 300px !important;
margin: 0 auto !important;
text-align: center !important;
overflow: visible !important;
}';
echo '.main__right .section-hero--full .paypal-embed .paypal-buttons,
.main__right .section-hero--full .paypal-embed iframe {
width: 100% !important;
min-width: 300px !important;
max-width: 300px !important;
margin: 0 auto !important;
box-sizing: border-box !important;
border: none !important;
outline: none !important;
}';
echo '.main__right .section-hero--full .content__buttons {
text-align: center !important;
width: 100% !important;
margin: 0 auto !important;
padding: 0 !important;
}';
// Mobile-specific single-column with forced centering
echo '@media (max-width: 767px) {
.main__right .section-hero--full .section-hero__content {
display: block !important;
width: 100% !important;
margin: 0 !important;
padding: 0 !important;
flex-direction: column !important;
}
.main__right .section-hero--full .column {
width: 100% !important;
max-width: 100% !important;
margin-bottom: 20px !important;
text-align: center !important;
display: flex !important;
justify-content: center !important;
align-items: center !important;
}
.main__right .section-hero--full .content-embed-container {
display: block !important;
width: 100% !important;
min-width: 300px !important;
max-width: 300px !important;
margin: 0 auto !important;
text-align: center !important;
position: relative !important;
left: 50% !important;
transform: translateX(-50%) !important;
/* Added wrapper for higher specificity */
box-sizing: border-box !important;
}
.main__right .section-hero--full .paypal-embed,
.main__right .section-hero--full .paypal-embed .paypal-buttons,
.main__right .section-hero--full .paypal-embed iframe {
width: 100% !important;
min-width: 300px !important;
max-width: 300px !important;
margin: 0 auto !important;
overflow: visible !important;
box-sizing: border-box !important;
}
.main__right .section-hero--full.layout-2-column .section-hero__content,
.main__right .section-hero--full.layout-3-column .section-hero__content {
flex-direction: column !important;
}
}';
// Desktop single-column for PayPal, multi-column for others
echo '@media (min-width: 1024px) {
.main__right .section-hero--full.layout-1-column .section-hero__content {
display: block !important;
}
.main__right .section-hero--full.layout-2-column .section-hero__content,
.main__right .section-hero--full.layout-3-column .section-hero__content {
display: grid !important;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) !important;
gap: 20px !important;
justify-content: center !important;
align-items: center !important;
}
.main__right .section-hero--full .column {
width: auto !important;
max-width: 100% !important;
text-align: center !important;
}
.main__right .section-hero--full .content-embed-container,
.main__right .section-hero--full .paypal-embed,
.main__right .section-hero--full .paypal-embed .paypal-buttons,
.main__right .section-hero--full .paypal-embed iframe {
width: 100% !important;
min-width: 300px !important;
max-width: 300px !important;
margin: 0 auto !important;
overflow: visible !important;
}
}';
echo '</style>';
}
// Modal container (only for non-AJAX requests)
if (!$is_modal_request) {
echo '<div id="story-modal" class="modal">';
echo '<div class="modal-content">';
echo '<span class="modal-close">×</span>';
echo '<div id="modal-body"></div>';
echo '</div>';
echo '</div>';
}
$stmt->close();
$conn->close();
?>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Synchronize with PHP DEBUG setting
const DEBUG = <?php echo DEBUG ? 'true' : 'false'; ?>;
// Debug log setup
let debugLog = null;
if (DEBUG) {
debugLog = document.createElement('div');
debugLog.id = 'debug-log';
debugLog.style.position = 'fixed';
debugLog.style.bottom = '10px';
debugLog.style.left = '10px';
debugLog.style.background = 'rgba(0, 0, 0, 0.8)';
debugLog.style.color = 'white';
debugLog.style.padding = '10px';
debugLog.style.zIndex = '1000';
debugLog.style.maxHeight = '200px';
debugLog.style.overflowY = 'auto';
document.body.appendChild(debugLog);
}
function logDebug(message, color = 'green') {
if (DEBUG && debugLog) {
debugLog.insertAdjacentHTML('beforeend', `<div style="color: ${color}; font-weight: bold;">Debug: ${message}</div>`);
debugLog.scrollTop = debugLog.scrollHeight;
}
if (DEBUG && console) console.log(`Debug: ${message}`, { color });
}
if (DEBUG) logDebug('Modal script loaded');
const modal = document.getElementById('story-modal');
const modalBody = document.getElementById('modal-body');
const closeBtn = document.querySelector('.modal-close');
const triggers = document.querySelectorAll('.modal-trigger');
if (DEBUG) logDebug('Found ' + triggers.length + ' modal triggers');
// Function to render embed blocks with synchronized SDK and sequential rendering
function renderEmbed(item, index, total) {
const container = document.getElementById(`embed-${item.id}`);
if (!container) {
if (DEBUG) logDebug(`Container not found for embed ID ${item.id}`, 'red');
return;
}
// Extract components with flexible matching
const divMatch = item.code.match(/<div\s+[^>]*id="[^"]+"[^>]*>/i);
const buttonMatch = item.code.match(/<script>\s*paypal\.Buttons\([\s\S]*?\)\.render\(['"][^'"]+['"]\);\s*<\/script>/i);
if (DEBUG) {
logDebug(`Div match for ID ${item.id}: ${divMatch ? 'Success' : 'Failed'}`, divMatch ? 'green' : 'red');
logDebug(`Button match for ID ${item.id}: ${buttonMatch ? 'Success' : 'Failed'}`, buttonMatch ? 'green' : 'red');
}
if (item.type === 'PayPal' && divMatch && buttonMatch) {
// Insert div with unique ID
const uniqueId = `paypal-button-container-${item.id}`;
let divContent = divMatch[0].replace(/id="[^"]+"/, `id="${uniqueId}"`);
container.innerHTML = divContent;
if (DEBUG) logDebug(`Inserted div for PayPal ID ${item.id}`, 'orange');
// Wait for SDK to be available
function waitForSDK(callback) {
if (typeof paypal !== 'undefined') {
if (DEBUG) logDebug(`PayPal SDK available for ID ${item.id}`, 'green');
callback();
} else {
if (DEBUG) logDebug(`Checking SDK for ID ${item.id}, status: ${typeof paypal}`, 'yellow');
setTimeout(() => waitForSDK(callback), 100);
}
}
// Extract and adjust button script
let scriptContent = buttonMatch[0].replace(/^<script>|<\/script>$/g, '').trim();
scriptContent = scriptContent.replace(/\.render\(['"][^'"]+['"]\)/, `.render('#${uniqueId}')`);
waitForSDK(() => {
const buttonScript = document.createElement('script');
buttonScript.textContent = scriptContent;
document.body.appendChild(buttonScript);
if (DEBUG) logDebug(`Rendered PayPal button script for ID ${item.id}`, 'orange');
// Sequential adjustment with delay based on index
setTimeout(() => {
const paypalButtons = document.querySelectorAll(`#${uniqueId} .paypal-buttons`);
const paypalIframes = document.querySelectorAll(`#${uniqueId} iframe`);
paypalButtons.forEach((button, btnIndex) => {
const iframe = paypalIframes[btnIndex];
if (button && iframe) {
// Apply inline styles to override PayPal defaults
button.style.cssText = 'width: 100% !important; min-width: 300px !important; max-width: 300px !important; margin: 0 auto !important; border: none !important; outline: none !important; display: block !important;';
iframe.style.cssText = 'width: 100% !important; min-width: 300px !important; max-width: 300px !important; margin: 0 auto !important; border: none !important; outline: none !important; display: block !important;';
if (DEBUG) {
const style = window.getComputedStyle(button);
logDebug(`Computed style for button ${uniqueId} (index ${btnIndex}): width=${style.width}, margin=${style.margin}, justify-content=${style.justifyContent}`, 'purple');
}
}
});
}, index * 500); // Staggered delay (500ms per instance)
});
} else if (item.type === 'YouTube') {
container.innerHTML = item.code;
container.style.display = 'block';
if (DEBUG) logDebug(`Rendered YouTube embed for ID ${item.id}`, 'orange');
} else {
container.innerHTML = `<div class="embed-fallback" id="fallback-${item.id}">${item.code}</div>`;
container.style.display = 'block';
if (DEBUG) logDebug(`Fallback rendered for ID ${item.id} (parsing failed, scripts not executed)`, 'red');
}
}
// Process embed blocks with sequential rendering
if (window.contentCode && Array.isArray(window.contentCode)) {
window.contentCode.forEach((item, index) => {
renderEmbed(item, index, window.contentCode.length);
});
} else if (DEBUG) {
logDebug('contentCode is not an array or unavailable', 'red');
}
// Desktop centering fallback
function adjustDesktopLayout() {
if (window.innerWidth >= 1024) {
const embedContainers = document.querySelectorAll('.main__right .section-hero--full .content-embed-container');
embedContainers.forEach(container => {
container.style.margin = '0 auto !important';
if (DEBUG) logDebug(`Adjusted desktop container centering for ${container.querySelector('.paypal-embed')?.id}`, 'blue');
});
}
}
window.addEventListener('load', adjustDesktopLayout);
window.addEventListener('resize', adjustDesktopLayout);
function openModal(content) {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = content;
const buttons = tempDiv.querySelectorAll('.content__buttons');
buttons.forEach(button => button.remove());
const debugMessages = tempDiv.querySelectorAll('div[style*="color: purple"], div[style*="color: blue"], div[style*="color: red"], div[style*="color: green"]');
debugMessages.forEach(msg => msg.remove());
let combinedContent = '';
const sections = tempDiv.querySelectorAll('.modal-story-content');
if (DEBUG) logDebug('Found ' + sections.length + ' modal-story-content sections');
if (sections.length > 0) {
sections.forEach((section, index) => {
combinedContent += section.outerHTML.trim();
if (index < sections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const fallbackSections = tempDiv.querySelectorAll('.section-hero__content');
if (DEBUG) logDebug('Found ' + fallbackSections.length + ' section-hero__content sections');
if (fallbackSections.length > 0) {
fallbackSections.forEach((section, index) => {
const title = section.querySelector('h1');
const image = section.querySelector('.content-image');
const content = section.querySelector('.generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
if (title) newContent.appendChild(title.cloneNode(true));
if (image) newContent.appendChild(image.cloneNode(true));
if (content) newContent.appendChild(content.cloneNode(true));
combinedContent += newContent.outerHTML.trim();
if (index < fallbackSections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const genericContent = tempDiv.querySelector('.generic-content');
if (genericContent) {
if (DEBUG) logDebug('Falling back to .generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
newContent.appendChild(genericContent.cloneNode(true));
combinedContent = newContent.outerHTML.trim();
} else {
if (DEBUG) logDebug('No content found in .modal-story-content, .section-hero__content, or .generic-content', 'red');
combinedContent = '<p>Content could not be parsed from the page.</p>';
}
}
}
modalBody.innerHTML = combinedContent;
modal.style.display = 'block';
modal.setAttribute('aria-hidden', 'false');
if (modalBody.children.length > 0 && closeBtn) {
closeBtn.focus();
}
if (DEBUG) logDebug('Modal opened');
}
function closeModal() {
modal.style.display = 'none';
modal.setAttribute('aria-hidden', 'true');
modalBody.innerHTML = '';
if (DEBUG && debugLog) {
debugLog.innerHTML = '';
}
if (DEBUG) logDebug('Modal closed');
}
if (modal && modalBody && closeBtn && triggers) {
triggers.forEach(trigger => {
trigger.addEventListener('click', function(e) {
e.preventDefault();
const modalId = this.getAttribute('data-modal-id');
if (modalId) {
const contentDiv = document.getElementById(modalId);
if (contentDiv) {
const content = contentDiv.innerHTML;
if (DEBUG) logDebug('Stories modal triggered, content from ID: ' + modalId);
if (DEBUG) logDebug('Modal content length: ' + content.length + ' characters', 'purple');
openModal(content);
} else {
openModal('<p>Content not found.</p>');
if (DEBUG) logDebug('Modal content not found for ID: ' + modalId, 'red');
}
return;
}
const link = this.getAttribute('data-modal-link');
if (DEBUG) logDebug('Trigger clicked, link: ' + link);
if (!link || link === '#' || link.includes('index.php')) {
openModal('<p>This link cannot be loaded in a modal to prevent recursive loading.</p>');
return;
}
let basePath = window.location.origin;
let absoluteLink;
try {
if (link.startsWith('http://') || link.startsWith('https://')) {
absoluteLink = link;
} else if (link.startsWith('/')) {
absoluteLink = new URL(link, window.location.origin).href;
} else {
absoluteLink = new URL(link, window.location.origin + '/').href;
}
absoluteLink += (absoluteLink.includes('?') ? '&' : '?') + 'modal=1';
if (DEBUG) logDebug('Fetching absolute link: ' + absoluteLink);
} catch (error) {
if (DEBUG) logDebug('URL construction error: ' + error.message, 'red');
openModal('<p>Invalid URL format.</p>');
return;
}
openModal('<p>Loading...</p>');
fetch(absoluteLink, {
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => {
if (DEBUG) logDebug('Fetch response status: ' + response.status + ' ' + response.statusText);
if (!response.ok) {
throw new Error('Network response was not ok: ' + response.statusText);
}
return response.text();
})
.then(data => {
if (DEBUG) logDebug('Fetched HTML length: ' + data.length);
const parser = new DOMParser();
const doc = parser.parseFromString(data, 'text/html');
let combinedContent = '';
const sections = doc.querySelectorAll('.modal-story-content');
if (DEBUG) logDebug('Found ' + sections.length + ' modal-story-content sections in fetched content');
if (sections.length > 0) {
sections.forEach((content, index) => {
combinedContent += content.outerHTML.trim();
if (index < sections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const fallbackSections = doc.querySelectorAll('.section-hero__content');
if (DEBUG) logDebug('Found ' + fallbackSections.length + ' section-hero__content sections');
if (fallbackSections.length > 0) {
fallbackSections.forEach((section, index) => {
const title = section.querySelector('h1');
const image = section.querySelector('.content-image');
const content = section.querySelector('.generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
if (title) newContent.appendChild(title.cloneNode(true));
if (image) newContent.appendChild(image.cloneNode(true));
if (content) newContent.appendChild(content.cloneNode(true));
combinedContent += newContent.outerHTML.trim();
if (index < fallbackSections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const genericContent = doc.querySelector('.generic-content');
if (genericContent) {
if (DEBUG) logDebug('Falling back to .generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
newContent.appendChild(genericContent.cloneNode(true));
combinedContent = newContent.outerHTML.trim();
} else {
if (DEBUG) logDebug('No content found in .modal-story-content, .section-hero__content, or .generic-content', 'red');
combinedContent = '<p>Content could not be parsed from the page.</p>';
}
}
}
if (combinedContent) {
openModal(combinedContent);
} else {
openModal('<p>No content found.</p>');
}
})
.catch(error => {
if (DEBUG) logDebug('Fetch error: ' + error.message, 'red');
openModal('<p>Sorry, the content could not be loaded: ' + error.message + '</p>');
});
});
});
closeBtn.addEventListener('click', closeModal);
window.addEventListener('click', function(event) {
if (event.target === modal) {
closeModal();
}
});
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && modal.style.display === 'block') {
closeModal();
}
});
} else {
if (DEBUG) logDebug('Modal elements missing (modal, modalBody, closeBtn, or triggers)', 'red');
}
});
</script>
JavaScript (renderEmbed):
index and total parameters to renderEmbed to enable sequential rendering.setTimeout delay (index * 500ms) to allow each PP embed to render independently, preventing conflicts between multiple paypal.Buttons() instances.display: block !important to ensure proper layout of buttons and iframes, addressing the cut-away issue.CSS:
box-sizing: border-box !important to .content-embed-container on mobile to prevent width miscalculations.Version Update: Incremented to V2.56 in the file header comment.
Update pull-contents.php:
pull-contents.php with the V2.56 content above.Test Desktop View:
https://www.nlt-chaplaincy.org/index.html with position-100.Test Mobile View:
position-100) to ensure they stack vertically and are centered.Inspect Elements:
#zoid-paypal-buttons-...) and its iframe have a computed width of 300px, no borders, and no cut-off..column, .content-embed-container, and .paypal-embed for justify-content, margin, and transform properties.Debug Output:
Please update pull-contents.php to V2.56, test thoroughly, and let me know the results! This should address the rendering and alignment problems.
But why there was no issue when all PP sections are having different positions? The PP SDK shouldn't "know" whether I'm using exclusive or same position as the rendering will still be single column?
Previous Success with Different Positions:
position (e.g., 1, 2, 3, 4), the renders worked because the renderEmbed function processed each instance sequentially with its own container (embed-${item.id}). The SDK likely initialized each paypal.Buttons() instance independently without interference.Current Failure with Same Position:
position (e.g., all at position 100), the PHP logic groups them into the same $group array within sections_by_position. This means renderEmbed is called multiple times in quick succession for the same position, potentially overwhelming the SDK or causing conflicts:setTimeout (1000ms per instance) might not be enough to prevent overlap, especially if the SDK queues renders and skips later ones.embed-${item.id}) are rendered in the same DOM context without proper isolation, the SDK might overwrite or fail to distinguish them.Single-Column Rendering:
layout-1-column) ensures each PP embed has its own 300px-wide container, so the issue isn’t layout-related. The problem lies in the SDK’s handling of multiple paypal.Buttons() calls on the same page.The PayPal SDK is designed to render buttons within a single page but expects unique configurations and containers. When multiple embeds share the same position, the rapid succession of renderEmbed calls might:
code) varies slightly or is incomplete for later sections.setTimeout delay doesn’t allow the SDK to complete one render before starting the next.paypal.Buttons() instance is fully independent by resetting the SDK context or using a unique namespace per render.buttonMatch content includes both yellow and black button configurations for all sections.pull-contents.php (V2.61)<?php
// pull-contents.php (Version 2.61)
// Debug toggle: Set to true to enable debug messages, false to disable
define('DEBUG', true);
// Define base path for images
define('IMAGE_BASE_PATH', 'https://admin.nlt-chaplaincy.org/images/');
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$config_path = '../config.php';
if (!file_exists($config_path)) {
die("Error: config.php not found at $config_path");
}
require_once $config_path;
if (!isset($dbServer) || !isset($dbUsername) || !isset($dbPassword) || !isset($dbDatabase)) {
die("Error: AppGini database variables not defined in config.php");
}
$conn = new mysqli($dbServer, $dbUsername, $dbPassword, $dbDatabase, $dbPort ?: 3306);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// Auto-detect page from calling file if $_GET['page'] not set
if (isset($_GET['page'])) {
$current_page = $_GET['page'];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Page set from GET: '$current_page'</div>";
}
} else {
$calling_file = basename($_SERVER['SCRIPT_FILENAME']);
$request_uri = $_SERVER['REQUEST_URI'];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Calling file: '$calling_file'</div>";
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: REQUEST_URI: '$request_uri'</div>";
}
$current_page = str_replace('.php', '', $calling_file);
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page after str_replace: '$current_page'</div>";
}
if ($current_page === 'index') {
$current_page = 'landing';
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page set to 'landing'</div>";
}
if (preg_match('/\/(task-map)\.php/', $request_uri, $matches)) {
$current_page = $matches[1];
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Current page updated from REQUEST_URI: '$current_page'</div>";
}
}
}
}
$status = 'Show';
// Preload PayPal SDK to support all buttons
$paypalSdkUrl = 'https://www.paypal.com/sdk/js?client-id=AUNZIE2pdhVLgVgUFGEQyyYAJVMuxwkXmCwvslu3c1eR-TMLSvCIBhDZxhhteIoQCTAzJ-50qNcVpuoa&vault=true&intent=subscription';
echo "<script src=\"$paypalSdkUrl\" id=\"paypal-sdk\" async=\"false\" onload=\"console.log('PayPal SDK preloaded')\" onerror=\"console.error('PayPal SDK preload error:', event)\"></script>";
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Final current_page: '$current_page'</div>";
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Image Base Path: '" . IMAGE_BASE_PATH . "'</div>";
}
// Determine if we're on the stories page
$is_stories_page = ($current_page === 'stories');
// Check if the request is for modal content
$is_modal_request = (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') || isset($_GET['modal']);
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Is modal request: " . ($is_modal_request ? 'Yes' : 'No') . "</div>";
}
$sql = "SELECT id, title, content, code, code_type, image, button_link, button_text, position, model, date_edited, theme_img, img_role, chk_divider
FROM web_content
WHERE page = ? AND status = ?
ORDER BY position ASC, date_edited DESC";
$stmt = $conn->prepare($sql);
if (!$stmt) {
die("Prepare failed: " . $conn->connect_error);
}
$stmt->bind_param("ss", $current_page, $status);
$stmt->execute();
$result = $stmt->get_result();
$sections = [];
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$sections[] = $row;
}
}
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Fetched " . count($sections) . " sections for page '$current_page'</div>";
}
// Group sections by position
$sections_by_position = [];
foreach ($sections as $row) {
$position = $row['position'] ?? 1;
$sections_by_position[$position][] = $row;
}
if (!empty($sections_by_position)) {
ksort($sections_by_position);
$current_index = 0;
foreach ($sections_by_position as $position => $group) {
$current_index++;
$use_default_divider = true;
$has_background_image = false;
$has_paypal = false;
foreach ($group as $row) {
if (!empty($row['theme_img']) && $row['img_role'] === 'Background') {
$has_background_image = true;
$use_default_divider = false;
}
if ($row['code_type'] === 'PayPal') {
$has_paypal = true;
}
}
if (isset($group[0]['chk_divider'])) {
$use_default_divider = $group[0]['chk_divider'] == 1;
}
if ($is_modal_request) {
foreach ($group as $index => $row) {
if (DEBUG) {
echo "<div style='color: blue; font-weight: bold; text-align: center;'>Debug: Rendering modal section ID: {$row['id']} at position: $position</div>";
}
echo "<div class=\"modal-story-content\">";
if (!empty($row['title'])) {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image modal-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
} elseif ($row['model'] === 'title-text-code' || $row['model'] === 'title-text-image-code' && !empty($row['code']) && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
if (!empty($row['content'])) {
echo "<div class=\"generic-content align-center\">" . $row['content'] . "</div>";
}
if (DEBUG) {
echo "<div style='color: purple; font-weight: bold; text-align: center;'>Debug: Modal content length: " . strlen($row['content']) . " characters</div>";
}
echo "</div>";
if ($index < count($group) - 1 || $current_index < count($sections_by_position)) {
echo "<div class=\"modal-section-separator\"></div>";
}
}
} else {
$column_count = min(count($group), 3);
if ($has_paypal) {
$column_count = 1; // Force single-column for sections with PayPal
}
$extra_class = ($current_page === 'task-map') ? ' task-map-section' : '';
echo "<section class=\"section-hero section-hero--full layout-$column_count-column $extra_class\">";
echo "<div class=\"section-hero__content\">";
// Sort by title for mobile view
usort($group, function($a, $b) {
return strcmp($a['title'], $b['title']);
});
foreach ($group as $index => $row) {
if ($index >= 3 && !$has_paypal) {
continue; // Hide sections beyond the third column on desktop for non-PP
}
echo "<div class=\"column column-$index\">";
if (!empty($row['theme_img']) && $row['img_role'] === 'Background') {
$background_image = IMAGE_BASE_PATH . htmlspecialchars($row['theme_img']);
echo "<div class=\"background-image-wrapper\" style=\"background-image: url('$background_image');\"></div>";
}
if ($current_page === 'faq') {
echo "<h1 class=\"align-center faq-question\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center faq-answer\">" . $row['content'] . "</div>";
} else {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
echo "<div class=\"generic-content align-center\">";
if ($is_stories_page) {
$content = strip_tags($row['content']);
$preview = mb_substr($content, 0, 60, 'UTF-8');
if (mb_strlen($content, 'UTF-8') > 60) {
$preview .= '...';
}
echo htmlspecialchars($preview);
} else {
echo $row['content'];
}
echo "</div>";
}
if ($row['model'] === 'title-text-image-code' || $row['model'] === 'title-text-code') {
if (!empty($row['image']) && $row['model'] === 'title-text-image-code') {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
}
if (!empty($row['code']) && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed-container\">";
if ($row['code_type'] === 'PayPal') {
echo "<div class=\"content-embed paypal-embed\" id=\"embed-{$row['id']}\"></div>";
} else {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
$encodedCode = json_encode($row['code'], JSON_HEX_TAG);
echo "<script>window.contentCode = window.contentCode || []; window.contentCode.push({id: '{$row['id']}', code: " . $encodedCode . ", type: '{$row['code_type']}'});</script>";
if (DEBUG) {
echo "<div style='color: orange; display: none;'>Debug: Embed code for ID ${row['id']} (${row['code_type']}): ${row['code']}</div>";
}
echo "</div>";
}
} elseif (!empty($row['image']) && $row['model'] !== 'title-text-image-code') {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
}
if (!empty($row['button_text'])) {
$button_text = htmlspecialchars($row['button_text']);
echo "<div class=\"content__buttons\">";
if ($is_stories_page) {
$modal_id = 'modal-content-' . $row['id'];
echo "<div id=\"$modal_id\" style=\"display:none;\">";
echo '<div class="modal-story-content">';
if (!empty($row['title'])) {
echo "<h1 class=\"align-center\">" . $row['title'] . "</h1>";
}
if (!empty($row['image'])) {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['image']);
echo "<div class=\"content-image modal-image\"><img src=\"$image_url\" alt=\"Section Image\" class=\"welcome-image\"></div>";
} elseif ($row['model'] === 'title-text-code' || $row['model'] === 'title-text-image-code' && ($row['code_type'] === 'YouTube' || $row['code_type'] === 'PayPal')) {
echo "<div class=\"content-embed\" id=\"embed-{$row['id']}\"></div>";
}
if (!empty($row['content'])) {
echo "<div class=\"generic-content align-center\">" . $row['content'] . "</div>";
}
if (DEBUG) {
echo "<div style='color: purple; font-weight: bold; text-align: center;'>Debug: Modal content length: " . strlen($row['content']) . " characters</div>";
}
echo '</div>';
echo "</div>";
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-id=\"$modal_id\">$button_text</a>";
if (DEBUG) {
echo "<div style='color: orange; font-weight: bold; text-align: center;'>Debug: Modal trigger rendered for ID: $modal_id with button text: $button_text</div>";
}
} else {
$button_link = htmlspecialchars($row['button_link'] ?: '');
if (!empty($button_link) && $row['button_link'] !== '#') {
echo "<a class=\"myButton modal-trigger\" href=\"#\" data-modal-link=\"$button_link\">$button_text</a>";
} else {
echo "<a class=\"myButton\" href=\"#\">$button_text</a>";
}
}
echo "</div>";
}
echo "</div>";
}
echo "</div>";
echo "</section>";
}
if ($current_index < count($sections_by_position) && !$is_modal_request) {
if ($use_default_divider) {
echo "<div class=\"separator\"><img src=\"https://admin.nlt-chaplaincy.org/public/down_arrow.png\" alt=\"Default Separator\" class=\"separator-image\"></div>";
} elseif (!empty($row['theme_img']) && $row['img_role'] === 'Separator') {
$image_url = IMAGE_BASE_PATH . htmlspecialchars($row['theme_img']);
echo "<div class=\"separator\"><img src=\"$image_url\" alt=\"Custom Separator\" class=\"separator-image\"></div>";
}
}
if (DEBUG) {
echo "<div style=\"color: green; font-weight: bold; text-align: center;\">Debug: Section with position $position rendered successfully with " . count($group) . " items.</div>";
}
}
} else {
echo "No sections found.";
}
// Add custom CSS for layout fixes
if ($current_page === 'landing' && strpos($_SERVER['REQUEST_URI'], 'position-100') !== false) {
echo '<style>';
echo '.main__right .section-hero--full {
width: 100% !important;
max-width: 1200px !important;
margin: 0 auto !important;
display: flex !important;
justify-content: center !important;
box-sizing: border-box !important;
overflow: hidden !important;
}';
echo '.main__right .section-hero--full .section-hero__content {
width: 100% !important;
max-width: 100% !important;
margin: 0 auto !important;
padding: 0 !important;
}';
echo '.main__right .section-hero--full .column {
width: 100% !important;
max-width: 100% !important;
padding: 0 !important;
margin: 0 0 20px 0 !important;
box-sizing: border-box !important;
text-align: center !important;
display: flex !important;
justify-content: center !important;
}';
echo '.main__right .section-hero--full .content-embed-container {
display: block !important;
width: 100% !important;
min-width: 300px !important;
max-width: 300px !important;
margin: 0 auto !important;
text-align: center !important;
position: relative !important;
left: 50% !important;
transform: translateX(-50%) !important;
}';
echo '.main__right .section-hero--full .paypal-embed {
width: 100% !important;
min-width: 300px !important;
max-width: 300px !important;
margin: 0 auto !important;
text-align: center !important;
overflow: visible !important;
}';
echo '.main__right .section-hero--full .paypal-embed .paypal-buttons,
.main__right .section-hero--full .paypal-embed iframe {
width: 100% !important;
min-width: 300px !important;
max-width: 300px !important;
margin: 0 auto !important;
box-sizing: border-box !important;
border: none !important;
outline: none !important;
}';
// Mobile-specific single-column with forced centering
echo '@media (max-width: 767px) {
.main__right .section-hero--full .section-hero__content {
display: block !important;
width: 100% !important;
margin: 0 !important;
padding: 0 !important;
flex-direction: column !important;
}
.main__right .section-hero--full .column {
width: 100% !important;
max-width: 100% !important;
margin-bottom: 20px !important;
text-align: center !important;
display: flex !important;
justify-content: center !important;
align-items: center !important;
}
.main__right .section-hero--full .content-embed-container {
display: block !important;
width: 100% !important;
min-width: 300px !important;
max-width: 300px !important;
margin: 0 auto !important;
text-align: center !important;
position: relative !important;
left: 50% !important;
transform: translateX(-50%) !important;
box-sizing: border-box !important;
}
.main__right .section-hero--full .paypal-embed,
.main__right .section-hero--full .paypal-embed .paypal-buttons,
.main__right .section-hero--full .paypal-embed iframe {
width: 100% !important;
min-width: 300px !important;
max-width: 300px !important;
margin: 0 auto !important;
overflow: visible !important;
box-sizing: border-box !important;
}
.main__right .section-hero--full.layout-2-column .section-hero__content,
.main__right .section-hero--full.layout-3-column .section-hero__content {
flex-direction: column !important;
}
}';
// Desktop single-column for PayPal, multi-column for others
echo '@media (min-width: 1024px) {
.main__right .section-hero--full.layout-1-column .section-hero__content {
display: block !important;
}
.main__right .section-hero--full.layout-2-column .section-hero__content,
.main__right .section-hero--full.layout-3-column .section-hero__content {
display: grid !important;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)) !important;
gap: 20px !important;
justify-content: center !important;
align-items: center !important;
}
.main__right .section-hero--full .column {
width: auto !important;
max-width: 100% !important;
text-align: center !important;
}
.main__right .section-hero--full .content-embed-container,
.main__right .section-hero--full .paypal-embed,
.main__right .section-hero--full .paypal-embed .paypal-buttons,
.main__right .section-hero--full .paypal-embed iframe {
width: 100% !important;
min-width: 300px !important;
max-width: 300px !important;
margin: 0 auto !important;
overflow: visible !important;
}
}';
echo '</style>';
}
// Modal container (only for non-AJAX requests)
if (!$is_modal_request) {
echo '<div id="story-modal" class="modal">';
echo '<div class="modal-content">';
echo '<span class="modal-close">×</span>';
echo '<div id="modal-body"></div>';
echo '</div>';
echo '</div>';
}
$stmt->close();
$conn->close();
?>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Synchronize with PHP DEBUG setting
const DEBUG = <?php echo DEBUG ? 'true' : 'false'; ?>;
// Debug log setup
let debugLog = null;
if (DEBUG) {
debugLog = document.createElement('div');
debugLog.id = 'debug-log';
debugLog.style.position = 'fixed';
debugLog.style.bottom = '10px';
debugLog.style.left = '10px';
debugLog.style.background = 'rgba(0, 0, 0, 0.8)';
debugLog.style.color = 'white';
debugLog.style.padding = '10px';
debugLog.style.zIndex = '1000';
debugLog.style.maxHeight = '200px';
debugLog.style.overflowY = 'auto';
document.body.appendChild(debugLog);
}
function logDebug(message, color = 'green') {
if (DEBUG && debugLog) {
debugLog.insertAdjacentHTML('beforeend', `<div style="color: ${color}; font-weight: bold;">Debug: ${message}</div>`);
debugLog.scrollTop = debugLog.scrollHeight;
}
if (DEBUG && console) console.log(`Debug: ${message}`, { color });
}
if (DEBUG) logDebug('Modal script loaded');
const modal = document.getElementById('story-modal');
const modalBody = document.getElementById('modal-body');
const closeBtn = document.querySelector('.modal-close');
const triggers = document.querySelectorAll('.modal-trigger');
if (DEBUG) logDebug('Found ' + triggers.length + ' modal triggers');
// Function to render embed blocks with dynamic delay
function renderEmbed(item, index, total) {
const container = document.getElementById(`embed-${item.id}`);
if (!container) {
if (DEBUG) logDebug(`Container not found for embed ID ${item.id}`, 'red');
return;
}
// Extract components with flexible matching
const divMatch = item.code.match(/<div\s+[^>]*id="[^"]+"[^>]*>/i);
const buttonMatch = item.code.match(/<script>\s*paypal\.Buttons\([\s\S]*?\)\.render\(['"][^'"]+['"]\);\s*<\/script>/i);
if (DEBUG) {
logDebug(`Div match for ID ${item.id}: ${divMatch ? 'Success' : 'Failed'}`, divMatch ? 'green' : 'red');
logDebug(`Button match for ID ${item.id}: ${buttonMatch ? 'Success' : 'Failed'}`, buttonMatch ? 'green' : 'red');
if (buttonMatch) logDebug(`Button script content for ID ${item.id}: ${buttonMatch[0]}`, 'orange');
}
if (item.type === 'PayPal' && divMatch && buttonMatch) {
// Insert div with unique ID
const uniqueId = `paypal-button-container-${item.id}`;
let divContent = divMatch[0].replace(/id="[^"]+"/, `id="${uniqueId}"`);
container.innerHTML = divContent;
// Apply immediate styles
container.querySelector(`#${uniqueId}`).style.cssText = 'width: 100% !important; min-width: 300px !important; max-width: 300px !important; margin: 0 auto !important;';
if (DEBUG) logDebug(`Inserted div for PayPal ID ${item.id}`, 'orange');
// Wait for SDK to be available
function waitForSDK(callback) {
if (typeof paypal !== 'undefined') {
if (DEBUG) logDebug(`PayPal SDK available for ID ${item.id}`, 'green');
callback();
} else {
if (DEBUG) logDebug(`Checking SDK for ID ${item.id}, status: ${typeof paypal}`, 'yellow');
setTimeout(() => waitForSDK(callback), 100);
}
}
waitForSDK(() => {
let scriptContent = buttonMatch[0].replace(/^<script>|<\/script>$/g, '').trim();
scriptContent = scriptContent.replace(/\.render\(['"][^'"]+['"]\)/, `.render('#${uniqueId}')`);
// Wrap in unique namespace
const uniqueScript = `(function() { var paypalInstance = paypal.Buttons; ${scriptContent} })();`;
const buttonScript = document.createElement('script');
buttonScript.textContent = uniqueScript;
document.body.appendChild(buttonScript);
if (DEBUG) logDebug(`Injected unique button script for ID ${item.id}`, 'orange');
// Adjust styles and check render with dynamic delay
const dynamicDelay = index * 1500 + (total * 500); // Increase delay based on total instances
setTimeout(() => {
const paypalButtons = document.querySelectorAll(`#${uniqueId} .paypal-buttons`);
const paypalIframes = document.querySelectorAll(`#${uniqueId} iframe`);
if (DEBUG) logDebug(`Found ${paypalButtons.length} button(s) and ${paypalIframes.length} iframe(s) for ID ${item.id} after ${dynamicDelay}ms`, paypalButtons.length > 0 ? 'green' : 'red');
paypalButtons.forEach((button, btnIndex) => {
const iframe = paypalIframes[btnIndex];
if (button && iframe) {
button.style.cssText += 'width: 100% !important; min-width: 300px !important; max-width: 300px !important; margin: 0 auto !important; border: none !important; outline: none !important; display: block !important;';
iframe.style.cssText += 'width: 100% !important; min-width: 300px !important; max-width: 300px !important; margin: 0 auto !important; border: none !important; outline: none !important; display: block !important;';
if (DEBUG) {
const style = window.getComputedStyle(button);
logDebug(`Computed style for button ${uniqueId} (index ${btnIndex}): width=${style.width}, margin=${style.margin}, justify-content=${style.justifyContent}`, 'purple');
}
} else if (DEBUG) {
logDebug(`Button or iframe not found for ID ${item.id} at index ${btnIndex}`, 'red');
}
});
}, dynamicDelay);
});
} else if (item.type === 'YouTube') {
container.innerHTML = item.code;
container.style.display = 'block';
if (DEBUG) logDebug(`Rendered YouTube embed for ID ${item.id}`, 'orange');
} else {
container.innerHTML = `<div class="embed-fallback" id="fallback-${item.id}">${item.code}</div>`;
container.style.display = 'block';
if (DEBUG) logDebug(`Fallback rendered for ID ${item.id} (parsing failed, scripts not executed)`, 'red');
}
}
// Process embed blocks with sequential rendering
if (window.contentCode && Array.isArray(window.contentCode)) {
window.contentCode.forEach((item, index) => {
renderEmbed(item, index, window.contentCode.length);
});
} else if (DEBUG) {
logDebug('contentCode is not an array or unavailable', 'red');
}
// Desktop centering fallback
function adjustDesktopLayout() {
if (window.innerWidth >= 1024) {
const embedContainers = document.querySelectorAll('.main__right .section-hero--full .content-embed-container');
embedContainers.forEach(container => {
container.style.margin = '0 auto !important';
if (DEBUG) logDebug(`Adjusted desktop container centering for ${container.querySelector('.paypal-embed')?.id}`, 'blue');
});
}
}
window.addEventListener('load', adjustDesktopLayout);
window.addEventListener('resize', adjustDesktopLayout);
function openModal(content) {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = content;
const buttons = tempDiv.querySelectorAll('.content__buttons');
buttons.forEach(button => button.remove());
const debugMessages = tempDiv.querySelectorAll('div[style*="color: purple"], div[style*="color: blue"], div[style*="color: red"], div[style*="color: green"]');
debugMessages.forEach(msg => msg.remove());
let combinedContent = '';
const sections = tempDiv.querySelectorAll('.modal-story-content');
if (DEBUG) logDebug('Found ' + sections.length + ' modal-story-content sections');
if (sections.length > 0) {
sections.forEach((section, index) => {
combinedContent += section.outerHTML.trim();
if (index < sections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const fallbackSections = tempDiv.querySelectorAll('.section-hero__content');
if (DEBUG) logDebug('Found ' + fallbackSections.length + ' section-hero__content sections');
if (fallbackSections.length > 0) {
fallbackSections.forEach((section, index) => {
const title = section.querySelector('h1');
const image = section.querySelector('.content-image');
const content = section.querySelector('.generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
if (title) newContent.appendChild(title.cloneNode(true));
if (image) newContent.appendChild(image.cloneNode(true));
if (content) newContent.appendChild(content.cloneNode(true));
combinedContent += newContent.outerHTML.trim();
if (index < fallbackSections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const genericContent = tempDiv.querySelector('.generic-content');
if (genericContent) {
if (DEBUG) logDebug('Falling back to .generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
newContent.appendChild(genericContent.cloneNode(true));
combinedContent = newContent.outerHTML.trim();
} else {
if (DEBUG) logDebug('No content found in .modal-story-content, .section-hero__content, or .generic-content', 'red');
combinedContent = '<p>Content could not be parsed from the page.</p>';
}
}
}
modalBody.innerHTML = combinedContent;
modal.style.display = 'block';
modal.setAttribute('aria-hidden', 'false');
if (modalBody.children.length > 0 && closeBtn) {
closeBtn.focus();
}
if (DEBUG) logDebug('Modal opened');
}
function closeModal() {
modal.style.display = 'none';
modal.setAttribute('aria-hidden', 'true');
modalBody.innerHTML = '';
if (DEBUG && debugLog) {
debugLog.innerHTML = '';
}
if (DEBUG) logDebug('Modal closed');
}
if (modal && modalBody && closeBtn && triggers) {
triggers.forEach(trigger => {
trigger.addEventListener('click', function(e) {
e.preventDefault();
const modalId = this.getAttribute('data-modal-id');
if (modalId) {
const contentDiv = document.getElementById(modalId);
if (contentDiv) {
const content = contentDiv.innerHTML;
if (DEBUG) logDebug('Stories modal triggered, content from ID: ' + modalId);
if (DEBUG) logDebug('Modal content length: ' + content.length + ' characters', 'purple');
openModal(content);
} else {
openModal('<p>Content not found.</p>');
if (DEBUG) logDebug('Modal content not found for ID: ' + modalId, 'red');
}
return;
}
const link = this.getAttribute('data-modal-link');
if (DEBUG) logDebug('Trigger clicked, link: ' + link);
if (!link || link === '#' || link.includes('index.php')) {
openModal('<p>This link cannot be loaded in a modal to prevent recursive loading.</p>');
return;
}
let basePath = window.location.origin;
let absoluteLink;
try {
if (link.startsWith('http://') || link.startsWith('https://')) {
absoluteLink = link;
} else if (link.startsWith('/')) {
absoluteLink = new URL(link, window.location.origin).href;
} else {
absoluteLink = new URL(link, window.location.origin + '/').href;
}
absoluteLink += (absoluteLink.includes('?') ? '&' : '?') + 'modal=1';
if (DEBUG) logDebug('Fetching absolute link: ' + absoluteLink);
} catch (error) {
if (DEBUG) logDebug('URL construction error: ' + error.message, 'red');
openModal('<p>Invalid URL format.</p>');
return;
}
openModal('<p>Loading...</p>');
fetch(absoluteLink, {
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
.then(response => {
if (DEBUG) logDebug('Fetch response status: ' + response.status + ' ' + response.statusText);
if (!response.ok) {
throw new Error('Network response was not ok: ' + response.statusText);
}
return response.text();
})
.then(data => {
if (DEBUG) logDebug('Fetched HTML length: ' + data.length);
const parser = new DOMParser();
const doc = parser.parseFromString(data, 'text/html');
let combinedContent = '';
const sections = doc.querySelectorAll('.modal-story-content');
if (DEBUG) logDebug('Found ' + sections.length + ' modal-story-content sections in fetched content');
if (sections.length > 0) {
sections.forEach((content, index) => {
combinedContent += content.outerHTML.trim();
if (index < sections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const fallbackSections = doc.querySelectorAll('.section-hero__content');
if (DEBUG) logDebug('Found ' + fallbackSections.length + ' section-hero__content sections');
if (fallbackSections.length > 0) {
fallbackSections.forEach((section, index) => {
const title = section.querySelector('h1');
const image = section.querySelector('.content-image');
const content = section.querySelector('.generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
if (title) newContent.appendChild(title.cloneNode(true));
if (image) newContent.appendChild(image.cloneNode(true));
if (content) newContent.appendChild(content.cloneNode(true));
combinedContent += newContent.outerHTML.trim();
if (index < fallbackSections.length - 1) {
combinedContent += '<div class="modal-section-separator"></div>';
}
});
} else {
const genericContent = doc.querySelector('.generic-content');
if (genericContent) {
if (DEBUG) logDebug('Falling back to .generic-content');
const newContent = document.createElement('div');
newContent.className = 'modal-story-content';
newContent.appendChild(genericContent.cloneNode(true));
combinedContent = newContent.outerHTML.trim();
} else {
if (DEBUG) logDebug('No content found in .modal-story-content, .section-hero__content, or .generic-content', 'red');
combinedContent = '<p>Content could not be parsed from the page.</p>';
}
}
}
if (combinedContent) {
openModal(combinedContent);
} else {
openModal('<p>No content found.</p>');
}
})
.catch(error => {
if (DEBUG) logDebug('Fetch error: ' + error.message, 'red');
openModal('<p>Sorry, the content could not be loaded: ' + error.message + '</p>');
});
});
});
closeBtn.addEventListener('click', closeModal);
window.addEventListener('click', function(event) {
if (event.target === modal) {
closeModal();
}
});
document.addEventListener('keydown', function(event) {
if (event.key === 'Escape' && modal.style.display === 'block') {
closeModal();
}
});
} else {
if (DEBUG) logDebug('Modal elements missing (modal, modalBody, closeBtn, or triggers)', 'red');
}
});
</script>
Debug Setting:
define('DEBUG', true); for detailed logging.JavaScript (renderEmbed):
var paypalInstance = paypal.Buttons to isolate each render from the global SDK context.index * 1500 + (total * 500)) to scale the wait time based on the number of instances, reducing overlap.Version Update: Incremented to V2.61 in the file header comment.
Update pull-contents.php:
pull-contents.php with the V2.61 content above.Test Desktop View:
https://www.nlt-chaplaincy.org/index.html with position-100.Test Mobile View:
Inspect Elements:
Browser Console:
buttonMatch content and render counts) and console errors. We may need to check the code field in the web_content table for consistency.Please update to V2.61, test, and let me know the results—focus on the debug output for all sections!
Copyright © 2023 Curation Web 我的資訊「展」輯. All Rights Reserved | Powered by Bludit | Theme by BlThemes