Add editable PRISM homepage section

This commit is contained in:
nmemmert
2026-05-20 09:00:22 -04:00
parent c66be30b20
commit 67f3caf40b
5 changed files with 193 additions and 3 deletions
Binary file not shown.
+15 -3
View File
@@ -189,7 +189,7 @@ type AdminView =
| 'emails' | 'subscribers' | 'contacts' | 'emails' | 'subscribers' | 'contacts'
| 'seo' | 'legal' | 'security' | 'brand' | 'global' | 'seo' | 'legal' | 'security' | 'brand' | 'global'
type MainContentSection = 'hero' | 'start-here' | 'about' | 'contact' | 'series' | 'share' | 'global' type MainContentSection = 'hero' | 'start-here' | 'about' | 'contact' | 'series' | 'share' | 'prism' | 'global'
const BRAND_KIT_SWATCHES = [ const BRAND_KIT_SWATCHES = [
{ name: 'Rich Black', hex: '#0a0a08', role: 'Primary background' }, { name: 'Rich Black', hex: '#0a0a08', role: 'Primary background' },
@@ -276,6 +276,18 @@ const FIELDS: Array<{ key: StringField; label: string; multiline?: boolean; sect
{ key: 'studyGuideUrl', label: 'Study Guide URL (Amazon link)', section: 'series' }, { key: 'studyGuideUrl', label: 'Study Guide URL (Amazon link)', section: 'series' },
{ key: 'shareHeading', label: 'Share Section — Heading', section: 'share' }, { key: 'shareHeading', label: 'Share Section — Heading', section: 'share' },
{ key: 'shareP', label: 'Share Section — Paragraph', multiline: true, section: 'share' }, { key: 'shareP', label: 'Share Section — Paragraph', multiline: true, section: 'share' },
{ key: 'prismVideoUrl', label: 'PRISM — Video URL', section: 'prism' },
{ key: 'prismEyebrow', label: 'PRISM — Eyebrow', section: 'prism' },
{ key: 'prismHeading', label: 'PRISM — Heading', section: 'prism' },
{ key: 'prismIntro', label: 'PRISM — Intro Text', multiline: true, section: 'prism' },
{ key: 'prismPatternIntro', label: 'PRISM — Pattern Intro', multiline: true, section: 'prism' },
{ key: 'prismStep1', label: 'PRISM — Step 1', section: 'prism' },
{ key: 'prismStep2', label: 'PRISM — Step 2', section: 'prism' },
{ key: 'prismStep3', label: 'PRISM — Step 3', section: 'prism' },
{ key: 'prismStep4', label: 'PRISM — Step 4', section: 'prism' },
{ key: 'prismStep5', label: 'PRISM — Step 5', section: 'prism' },
{ key: 'prismOutro', label: 'PRISM — Outro Text', multiline: true, section: 'prism' },
{ key: 'prismClosing', label: 'PRISM — Closing Line', multiline: true, section: 'prism' },
// Global / Footer / Platform // Global / Footer / Platform
{ key: 'footerTitle', label: 'Footer — Brand Title', section: 'global' }, { key: 'footerTitle', label: 'Footer — Brand Title', section: 'global' },
{ key: 'footerSubtitle', label: 'Footer — Subtitle', section: 'global' }, { key: 'footerSubtitle', label: 'Footer — Subtitle', section: 'global' },
@@ -2457,9 +2469,9 @@ export default function AdminPage({ content, onSave, onLogout }: Props) {
<section className="admin-panel-section"> <section className="admin-panel-section">
<div className="admin-panel-head"> <div className="admin-panel-head">
<h2>Homepage</h2> <h2>Homepage</h2>
<p>Controls the hero, button labels, share section, and "Where to Next" navigation cards.</p> <p>Controls the hero, share section, PRISM video block, and "Where to Next" navigation cards.</p>
</div> </div>
{FIELDS.filter(f => f.section === 'hero' || f.section === 'share').map(({ key, label, multiline }) => ( {FIELDS.filter(f => f.section === 'hero' || f.section === 'share' || f.section === 'prism').map(({ key, label, multiline }) => (
<div className="admin-field" key={key}> <div className="admin-field" key={key}>
<label htmlFor={`field-${key}`}>{label}</label> <label htmlFor={`field-${key}`}>{label}</label>
{multiline {multiline
+107
View File
@@ -307,6 +307,94 @@
font-style: normal; font-style: normal;
} }
/* ── PRISM ── */
.section-prism {
background:
radial-gradient(circle at top, rgba(201, 168, 76, 0.12), transparent 46%),
linear-gradient(180deg, rgba(13, 13, 11, 0.98), rgba(7, 7, 7, 1));
border-bottom: 1px solid rgba(201, 168, 76, 0.12);
padding: 5rem 0;
}
.prism-feature {
max-width: 1280px;
display: grid;
grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
gap: 2.5rem;
align-items: center;
}
.prism-copy {
max-width: 36rem;
width: 100%;
justify-self: start;
text-align: left;
}
.prism-copy .eyebrow {
margin-bottom: 0.8rem;
}
.prism-heading {
text-align: left;
margin-bottom: 1rem;
}
.prism-description {
color: rgba(255, 255, 255, 0.72);
line-height: 1.7;
margin: 0 0 1rem;
}
.prism-steps {
display: grid;
gap: 0.55rem;
margin: 1.35rem 0 1.3rem;
}
.prism-steps p {
margin: 0;
padding: 0.7rem 0.85rem;
border-radius: 12px;
border: 1px solid rgba(201, 168, 76, 0.18);
background: rgba(201, 168, 76, 0.05);
color: var(--brand-warm-white);
font-family: var(--brand-font-body);
font-size: 0.93rem;
letter-spacing: 0.03em;
}
.prism-steps strong {
color: var(--brand-gold);
font-weight: 700;
}
.prism-emphasis {
color: var(--brand-warm-white);
font-weight: 600;
}
.prism-video-shell {
position: relative;
width: 100%;
max-width: none;
border-radius: 18px;
padding: 0.75rem;
background: linear-gradient(180deg, rgba(201, 168, 76, 0.14), rgba(255, 255, 255, 0.02));
box-shadow:
0 0 0 1px rgba(201, 168, 76, 0.18),
0 18px 70px rgba(0, 0, 0, 0.45);
}
.prism-video {
display: block;
width: 100%;
aspect-ratio: 16 / 9;
border: 0;
border-radius: 12px;
background: #000;
}
/* ── Player ── */ /* ── Player ── */
.section-player { .section-player {
background: #070707; background: #070707;
@@ -3797,6 +3885,25 @@
max-width: 280px; max-width: 280px;
} }
.prism-feature {
grid-template-columns: 1fr;
gap: 1.2rem;
}
.prism-heading {
text-align: center;
}
.prism-copy {
max-width: none;
text-align: center;
justify-self: stretch;
}
.prism-steps {
text-align: left;
}
.hero-title { .hero-title {
white-space: normal; white-space: normal;
} }
+43
View File
@@ -990,6 +990,49 @@ function LandingPage({ content }: { content: SiteContent }) {
</div> </div>
</section> </section>
<section className="section-prism" aria-label="PRISM featured video">
<div className="section-inner prism-feature">
<div className="prism-video-shell">
<video
className="prism-video"
controls
playsInline
preload="metadata"
poster="/images/banner.png"
>
<source src={content.prismVideoUrl || '/images/PRISM.mp4'} type="video/mp4" />
Your browser does not support embedded video playback.
</video>
</div>
<div className="prism-copy">
<p className="eyebrow">{content.prismEyebrow || 'Featured Video'}</p>
<h2 className="section-heading prism-heading">
<span className="ornament"></span> {content.prismHeading || 'PRISM'} <span className="ornament"></span>
</h2>
<p className="prism-description">
{content.prismIntro || 'What if every time you opened your Bible, you had a clear, repeatable method to actually dig in?'}
</p>
<p className="prism-description">
{content.prismPatternIntro || 'In this bonus episode, I walk you through P.R.I.S.M. — a five-step daily Bible study pattern designed to help you slow down, go deep, and let the Word do its work.'}
</p>
<div className="prism-steps" aria-label="P.R.I.S.M. steps">
<p>{content.prismStep1 || 'P — Pray before you read'}</p>
<p>{content.prismStep2 || 'R — Read slowly and observe'}</p>
<p>{content.prismStep3 || 'I — Interpret with context'}</p>
<p>{content.prismStep4 || 'S — Study and apply specifically'}</p>
<p>{content.prismStep5 || 'M — Memorize one verse at a time'}</p>
</div>
<p className="prism-description">
{content.prismOutro || "Whether you're brand new to daily Bible reading or you've been at it for years, P.R.I.S.M. gives you a consistent framework for every passage, every day."}
</p>
<p className="prism-description prism-emphasis">
{content.prismClosing || "The goal isn't to get through the text — it's to let the text get through to you."}
</p>
</div>
</div>
</section>
<section className="section-series" id="series" aria-label="Current series"> <section className="section-series" id="series" aria-label="Current series">
<div className="section-inner"> <div className="section-inner">
<h2 className="section-heading"> <h2 className="section-heading">
+28
View File
@@ -174,6 +174,19 @@ export interface SiteContent {
// ── Share ── // ── Share ──
shareHeading: string shareHeading: string
shareP: string shareP: string
// ── PRISM Video ──
prismVideoUrl: string
prismEyebrow: string
prismHeading: string
prismIntro: string
prismPatternIntro: string
prismStep1: string
prismStep2: string
prismStep3: string
prismStep4: string
prismStep5: string
prismOutro: string
prismClosing: string
// ── Homepage navigation cards ── // ── Homepage navigation cards ──
whereToNextEyebrow: string whereToNextEyebrow: string
whereToNextHeading: string whereToNextHeading: string
@@ -319,6 +332,21 @@ export const DEFAULTS: SiteContent = {
colossiansStudySections: DEFAULT_COLOSSIANS_STUDY_SECTIONS, colossiansStudySections: DEFAULT_COLOSSIANS_STUDY_SECTIONS,
shareHeading: 'Help one more person hear the Word this week.', shareHeading: 'Help one more person hear the Word this week.',
shareP: 'Scan the QR code or text the show link to a friend who needs encouragement today.', shareP: 'Scan the QR code or text the show link to a friend who needs encouragement today.',
prismVideoUrl: '/images/PRISM.mp4',
prismEyebrow: 'Featured Video',
prismHeading: 'PRISM',
prismIntro:
'What if every time you opened your Bible, you had a clear, repeatable method to actually dig in?',
prismPatternIntro:
'In this bonus episode, I walk you through P.R.I.S.M. — a five-step daily Bible study pattern designed to help you slow down, go deep, and let the Word do its work.',
prismStep1: 'P — Pray before you read',
prismStep2: 'R — Read slowly and observe',
prismStep3: 'I — Interpret with context',
prismStep4: 'S — Study and apply specifically',
prismStep5: 'M — Memorize one verse at a time',
prismOutro:
"Whether you're brand new to daily Bible reading or you've been at it for years, P.R.I.S.M. gives you a consistent framework for every passage, every day.",
prismClosing: "The goal isn't to get through the text - it's to let the text get through to you.",
whereToNextEyebrow: 'Where to Next', whereToNextEyebrow: 'Where to Next',
whereToNextHeading: 'Choose the page you need.', whereToNextHeading: 'Choose the page you need.',
whereToNextCards: [ whereToNextCards: [