From 5c7e3ce04151e2bb26e1e41238ee567914a7fa99 Mon Sep 17 00:00:00 2001 From: offmybach <137804812+offmybach@users.noreply.github.com> Date: Wed, 18 Feb 2026 16:05:07 -0500 Subject: [PATCH 1/2] Add conversion-proof and Clarence imagery sections --- index.html | 207 +++++++++++ script.js | 285 ++++++++++++++ style.css | 1046 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1538 insertions(+) create mode 100644 index.html create mode 100644 script.js create mode 100644 style.css diff --git a/index.html b/index.html new file mode 100644 index 0000000..94d0418 --- /dev/null +++ b/index.html @@ -0,0 +1,207 @@ + + + + + + Clarence Gets a Bargain | Kid Lit Is a Hit + + + + + + +
+ +
+

Financial Literacy Adventure Series

+

Clarence Gets a Bargain.

+

Approved by at least 3 teachers (my mother (retired), brother, and neighbor)

+ +

A clever tale for clever kids, by Jonathan Bach — author, illustrator, wordsmith supreme.

+

Clarence Wyze thinks he needs the newest robot… until Mom teaches him comparison shopping, coupons, and the superpower of saving.

+ +
+
32Pages
+
1Mission
+
Giggles
+
+ +

KID LIT IS A HIT! AND KID FIN IS A WIN!

+

Stealthy Edutainment for growing money-smart minds.

+ + +
+ Parents + Educators + Storytime Leaders +
+
+
+ +
+

Wish You Were Here!

+
+ +
+
+

Bring Clarence Front & Center

+

Drop one Clarence image below and it repeats across the page for a strong character brand feel.

+ + +
+ +
+ +
+
+

Meet Clarence Wyze

+
+
+ 1 +

The Big Robot Reward

+

Clarence finally gets his shopping day after earning top grades and finishing chores — and he wants the newest smart robot he can find.

+
+
+ 2 +

Mom's Money Lesson

+

He learns that families budget for needs, compare prices, and use sale ads and coupons before shopping trips.

+
+
+ 3 +

Clearance vs Clarence

+

A hilarious mix-up leads to the clearance aisle, where Clarence discovers that smart choices beat flashy choices.

+
+
+ 4 +

Smart Shopper Victory

+

He stacks a coupon on a clearance deal, saves more money, and leaves with confidence plus real-life financial literacy skills.

+
+
+
+ +
+
+

Step Into Clarence's Coupon Quest

+

Quick start: drag a cover image into either side card (or click the card) and it saves automatically. Then click the center magazine to pop it front-and-center.

+
+
+
+

Book Cover

+
+ +

Drop Front Cover Hereor click to choose

+
+ + +
+ +
+ +

Click here to see about Clarence's quest for the perfect smart robot

+
+ +
+

Alternate / Back Cover

+
+ +

Drop Back Cover Hereor click to choose

+
+ + +
+
+
+ +
+

Why Families & Educators Love It

+
+
+

Read Together

+

A polished, grown-up visual style made for parents and educators reading to kids.

+
+
+

Classroom Friendly

+

Built-in coupon pages support activities, incentive moments, and lesson tie-ins.

+
+
+

Fully Editable Coupons

+

Each page has multiple coupon spaces with resizable text areas and editable dotted cut-lines.

+
+
+
+ +
+

“A story with heart, humor, and practical money-smarts — perfect for read-aloud moments and classroom chats.”

+
+ +
+

What Early Readers Are Saying

+
+
“Finally, a funny story that sneaks in real money habits kids can actually use.”— Parent Reviewer
+
“The coupon mission format is classroom gold. Students stay engaged and absorb the vocabulary.”— Elementary Educator
+
“Clarence is relatable, hilarious, and perfect for read-alouds.”— Family Literacy Volunteer
+
+
+ +
+

Purchase & Pre-Order

+

Format: Soft Cover (Primary Edition)

+

Retail links can be added as soon as you pick channels. For now, use these placeholder slots.

+
+ + + + + +
+

Coming bonus: optional kid-friendly glossary/definition guide download from the end-of-book summary section.

+
+
+ + + + + + + + diff --git a/script.js b/script.js new file mode 100644 index 0000000..5eba412 --- /dev/null +++ b/script.js @@ -0,0 +1,285 @@ +const modal = document.getElementById('magazineModal'); +const openBtn = document.getElementById('openMagazine'); +const closeBtn = document.getElementById('closeMagazineBtn'); +const closeOverlay = document.getElementById('closeMagazine'); +const magazine = document.getElementById('magazineBook'); +const slotTemplate = document.getElementById('couponSlotTemplate'); +const stageTilt = document.querySelector('.stage-tilt'); +const nextHotspot = document.getElementById('turnNext'); +const prevHotspot = document.getElementById('turnPrev'); + +const frontCoverInput = document.getElementById('frontCoverInput'); +const backCoverInput = document.getElementById('backCoverInput'); +const frontCoverSlot = document.getElementById('frontCoverSlot'); +const backCoverSlot = document.getElementById('backCoverSlot'); +const frontCoverPreview = document.getElementById('frontCoverPreview'); +const backCoverPreview = document.getElementById('backCoverPreview'); +const magazineFrontPreview = document.getElementById('magazineFrontPreview'); +const clarenceImageInput = document.getElementById('clarenceImageInput'); +const clarenceImageSlot = document.getElementById('clarenceImageSlot'); +const clarenceImageMain = document.getElementById('clarenceImageMain'); +const clarenceEcho1 = document.getElementById('clarenceEcho1'); +const clarenceEcho2 = document.getElementById('clarenceEcho2'); + +const pageData = [ + { page: 1, title: 'Clarence Starts the Mission', theme: 'Earned Reward + Robot Dream' }, + { page: 2, title: "Mom's Money Lesson", theme: 'Needs, Wants, and Family Budget' }, + { page: 3, title: 'Coupon Homework', theme: 'Sale Ads + Comparison Shopping' }, + { page: 4, title: 'The Clearance Aisle Twist', theme: 'Smart Value Beats Flashy Price' }, + { page: 5, title: 'Checkout Win', theme: 'Coupon Stack + Receipt Smarts' }, + { page: 6, title: 'Wyze Shopper Mindset', theme: 'Savings Power for Life' } +]; + +const sheetCount = 3; +let current = 0; + +const memoryStore = new Map(); +function getSavedValue(key) { + try { + return localStorage.getItem(key) || memoryStore.get(key) || ''; + } catch { + return memoryStore.get(key) || ''; + } +} + +function saveValue(key, value) { + memoryStore.set(key, value); + try { + localStorage.setItem(key, value); + } catch { + // Continue with in-memory storage when localStorage is unavailable + } +} + +function setCoverImage(dataUrl, targetImg) { + if (!targetImg) return; + if (dataUrl) { + targetImg.src = dataUrl; + targetImg.hidden = false; + const txt = targetImg.parentElement?.querySelector('.cover-placeholder__text, .magazine-preview__tag'); + if (txt) txt.hidden = true; + } else { + targetImg.hidden = true; + const txt = targetImg.parentElement?.querySelector('.cover-placeholder__text, .magazine-preview__tag'); + if (txt) txt.hidden = false; + } +} + +function applyFrontCover(dataUrl) { + setCoverImage(dataUrl, frontCoverPreview); + setCoverImage(dataUrl, magazineFrontPreview); +} + +function applyBackCover(dataUrl) { + setCoverImage(dataUrl, backCoverPreview); +} + +function applyClarenceImage(dataUrl) { + [clarenceImageMain, clarenceEcho1, clarenceEcho2].forEach((img) => setCoverImage(dataUrl, img)); +} + +function readFileToDataUrl(file, done) { + if (!file || !file.type.startsWith('image/')) return; + const reader = new FileReader(); + reader.onload = () => done(String(reader.result || '')); + reader.readAsDataURL(file); +} + +function wireImageInput(input, storageKey, applyFn) { + if (!input) return; + input.addEventListener('change', () => { + const file = input.files?.[0]; + readFileToDataUrl(file, (dataUrl) => { + saveValue(storageKey, dataUrl); + applyFn(dataUrl); + }); + }); +} + +function wireDropAndClick(slot, input, storageKey, applyFn) { + if (!slot || !input) return; + + slot.addEventListener('click', () => input.click()); + slot.addEventListener('keydown', (event) => { + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault(); + input.click(); + } + }); + + ['dragenter', 'dragover'].forEach((evtName) => { + slot.addEventListener(evtName, (event) => { + event.preventDefault(); + slot.classList.add('is-dragover'); + }); + }); + + ['dragleave', 'dragend', 'drop'].forEach((evtName) => { + slot.addEventListener(evtName, () => slot.classList.remove('is-dragover')); + }); + + slot.addEventListener('drop', (event) => { + event.preventDefault(); + const file = event.dataTransfer?.files?.[0]; + readFileToDataUrl(file, (dataUrl) => { + saveValue(storageKey, dataUrl); + applyFn(dataUrl); + }); + }); +} + +window.addEventListener('dragover', (event) => event.preventDefault()); +window.addEventListener('drop', (event) => event.preventDefault()); + +applyFrontCover(getSavedValue('clarence-front-cover')); +applyBackCover(getSavedValue('clarence-back-cover')); +wireImageInput(frontCoverInput, 'clarence-front-cover', applyFrontCover); +wireImageInput(backCoverInput, 'clarence-back-cover', applyBackCover); +wireDropAndClick(frontCoverSlot, frontCoverInput, 'clarence-front-cover', applyFrontCover); +wireDropAndClick(backCoverSlot, backCoverInput, 'clarence-back-cover', applyBackCover); + +applyClarenceImage(getSavedValue('clarence-character-image')); +wireImageInput(clarenceImageInput, 'clarence-character-image', applyClarenceImage); +wireDropAndClick(clarenceImageSlot, clarenceImageInput, 'clarence-character-image', applyClarenceImage); + +function beep() { + const ctx = new (window.AudioContext || window.webkitAudioContext)(); + const osc = ctx.createOscillator(); + const gain = ctx.createGain(); + osc.type = 'triangle'; + osc.frequency.value = 510; + gain.gain.setValueAtTime(0.08, ctx.currentTime); + gain.gain.exponentialRampToValueAtTime(0.0001, ctx.currentTime + 0.12); + osc.connect(gain); + gain.connect(ctx.destination); + osc.start(); + osc.stop(ctx.currentTime + 0.12); +} + +function makeCouponSlot(index) { + const slot = slotTemplate.content.firstElementChild.cloneNode(true); + slot.querySelector('h4').textContent = `Coupon ${index}`; + slot.querySelector('p').textContent = 'Editable details. Add your own coupon language, educator note, or family challenge here.'; + slot.querySelector('.coupon-slot__offer').textContent = `$${index} OFF`; + return slot; +} + +function makeCouponPage(data) { + const page = document.createElement('section'); + page.className = 'page-face coupon-page'; + + const heading = document.createElement('h3'); + heading.className = 'coupon-page__title'; + heading.textContent = `${data.title} • ${data.theme}`; + heading.contentEditable = 'true'; + + const pageNumber = document.createElement('span'); + pageNumber.className = 'coupon-page__number'; + pageNumber.textContent = String(data.page); + + const grid = document.createElement('div'); + grid.className = 'coupon-grid'; + for (let i = 1; i <= 4; i++) { + grid.appendChild(makeCouponSlot(i)); + } + + page.append(heading, grid, pageNumber); + return page; +} + +function buildMagazine() { + magazine.innerHTML = ''; + for (let i = 0; i < sheetCount; i++) { + const sheet = document.createElement('article'); + sheet.className = 'sheet'; + sheet.style.zIndex = String(sheetCount - i); + + const front = makeCouponPage(pageData[i * 2]); + const back = makeCouponPage(pageData[i * 2 + 1]); + + front.classList.add('page-front'); + back.classList.add('page-back'); + + sheet.append(front, back); + magazine.appendChild(sheet); + } +} + +function updateFlips() { + magazine.classList.toggle('magazine--closed', current === 0); + [...magazine.children].forEach((sheet, idx) => { + sheet.classList.toggle('flipped', idx < current); + sheet.style.zIndex = idx < current ? String(idx + 1) : String(sheetCount - idx); + }); +} + +function goForward(playSound = true) { + if (current < sheetCount) { + current += 1; + updateFlips(); + if (playSound) beep(); + } +} + +function goBack(playSound = true) { + if (current > 0) { + current -= 1; + updateFlips(); + if (playSound) beep(); + } +} + +magazine.addEventListener('click', (event) => { + const bounds = magazine.getBoundingClientRect(); + const x = event.clientX - bounds.left; + const y = event.clientY - bounds.top; + if (y <= bounds.height * 0.62) return; + if (x > bounds.width * 0.72) goForward(); + if (x < bounds.width * 0.28) goBack(); +}); + +function openMagazine() { + const dockRect = openBtn.getBoundingClientRect(); + const centerX = window.innerWidth / 2; + const centerY = window.innerHeight / 2; + const dockX = dockRect.left + dockRect.width / 2; + const dockY = dockRect.top + dockRect.height / 2; + const dx = Math.round(dockX - centerX); + const dy = Math.round(dockY - centerY); + + stageTilt?.style.setProperty('--launch-x', `${dx}px`); + stageTilt?.style.setProperty('--launch-y', `${dy}px`); + + modal.classList.add('open'); + modal.setAttribute('aria-hidden', 'false'); + + if (current === 0) { + window.setTimeout(() => goForward(false), 260); + } +} + +function closeMagazineModal() { + modal.classList.remove('open'); + modal.setAttribute('aria-hidden', 'true'); +} + +openBtn.addEventListener('click', openMagazine); +openBtn.addEventListener('keydown', (event) => { + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault(); + openMagazine(); + } +}); + +closeBtn.addEventListener('click', closeMagazineModal); +closeOverlay.addEventListener('click', closeMagazineModal); +nextHotspot?.addEventListener('click', goForward); +prevHotspot?.addEventListener('click', goBack); +document.addEventListener('keydown', (event) => { + if (event.key === 'Escape') closeMagazineModal(); + if (event.key === 'ArrowRight') goForward(); + if (event.key === 'ArrowLeft') goBack(); +}); + +buildMagazine(); +updateFlips(); diff --git a/style.css b/style.css new file mode 100644 index 0000000..770af59 --- /dev/null +++ b/style.css @@ -0,0 +1,1046 @@ +@font-face { + font-family: 'OpenDyslexic'; + src: url('https://cdn.jsdelivr.net/gh/antijingoist/open-dyslexic/web/OpenDyslexic-Regular.otf') format('opentype'); + font-weight: 400; + font-style: normal; +} +@font-face { + font-family: 'OpenDyslexic'; + src: url('https://cdn.jsdelivr.net/gh/antijingoist/open-dyslexic/web/OpenDyslexic-Bold.otf') format('opentype'); + font-weight: 700; + font-style: normal; +} + +:root { + --bg: #e9f4ff; + --ink: #17385f; + --brand: #1f66c2; + --brand-2: #ff8a2d; + --brand-3: #2ea5ff; + --card: #ffffff; + --shadow: 0 18px 36px rgba(25, 16, 85, 0.18); +} + +* { box-sizing: border-box; } +body { + margin: 0; + font-family: 'Manrope', 'OpenDyslexic', sans-serif; + background: linear-gradient(180deg, #d7efff, #f4fbff 42%, #eef6ff); + color: var(--ink); + background-attachment: fixed; +} + +.hero { + position: relative; + display: grid; + grid-template-columns: 1fr; + max-width: 1400px; + margin: 0 auto; + padding: 0 2rem 4rem; +} + +.top-nav { + background: rgba(255, 255, 255, 0.65); + border-radius: 999px; + backdrop-filter: blur(6px); + box-shadow: 0 12px 24px rgba(60, 49, 125, 0.08); + + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + align-items: center; + text-align: center; + padding: 1rem 0; + color: #8b8b8f; + font-weight: 600; + font-size: clamp(1rem, 1.35vw, 1.2rem); +} +.top-nav__brand { + color: #121317; + font-weight: 800; +} +.top-nav__link { + color: inherit; + text-decoration: none; +} +.top-nav__link:hover, +.top-nav__link:focus-visible { + color: #2f3163; + text-decoration: underline; + text-underline-offset: 4px; +} + +.hero::before, +.hero::after { + content: ''; + position: absolute; + border-radius: 999px; + filter: blur(2px); + opacity: .7; + pointer-events: none; +} +.hero::before { + width: clamp(180px, 24vw, 360px); + height: clamp(180px, 24vw, 360px); + background: radial-gradient(circle at 35% 35%, #f7cdde, #f1e6ff 65%, transparent 75%); + top: 5rem; + left: 1rem; +} +.hero::after { + width: clamp(160px, 20vw, 300px); + height: clamp(160px, 20vw, 300px); + background: radial-gradient(circle at 35% 35%, #bcefff, #dcd2ff 68%, transparent 78%); + right: 3rem; + top: 16rem; +} + +.hero-statement { + max-width: 1200px; + margin: 0 auto; + text-align: center; + padding-top: clamp(4rem, 10vh, 7rem); +} + +.eyebrow { + display: none; +} +h1 { + font-family: 'OpenDyslexic', 'Manrope', sans-serif; + font-size: clamp(2.8rem, 5.2vw, 5.1rem); + margin: 0; + line-height: 1.06; +} +.tagline { + margin: clamp(2rem, 5vh, 3.25rem) 0 0; + font-weight: 800; + font-size: 1.15rem; + background: linear-gradient(90deg, var(--brand-2), var(--brand-3)); + -webkit-background-clip: text; + background-clip: text; + color: transparent; +} +.stealth-note { + margin: 1rem 0 0; + display: inline-block; + padding: .35rem .7rem; + border-radius: 999px; + background: linear-gradient(90deg, #e3f8fb, #ece8ff); + color: #2a2f63; + font-weight: 700; +} +.approval { + margin: 1rem 0 clamp(4.25rem, 12vh, 8.5rem); + font-family: 'OpenDyslexic', 'Manrope', sans-serif; + font-size: clamp(1.3rem, 3.2vw, 3rem); + color: #939399; + font-weight: 700; + line-height: 1.15; +} +.author-line { + margin: 0 0 1rem; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; + font-size: clamp(2rem, 4vw, 4.2rem); + font-weight: 700; + line-height: 1.08; + max-width: 19ch; + margin-left: auto; + margin-right: auto; +} +.mission-line { + margin: 0 0 clamp(4rem, 11vh, 8rem); + font-family: 'OpenDyslexic', 'Manrope', sans-serif; + font-size: clamp(1.75rem, 3.8vw, 3.8rem); + font-weight: 700; + line-height: 1.08; + color: #8f9095; + max-width: 20ch; + margin-left: auto; + margin-right: auto; +} +.hero-stats { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: clamp(2rem, 6vw, 8rem); + margin: 0 auto; + max-width: 960px; +} +.hero-stat { + background: transparent; + border-radius: 0; + padding: 0; + text-align: center; + box-shadow: none; +} +.hero-stat strong { + display: block; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; + font-size: clamp(3.3rem, 6vw, 6.2rem); + line-height: 1; + color: #0f1013; +} +.hero-stat span { + display: block; + margin-top: .55rem; + color: #7f8086; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; + font-weight: 700; + font-size: clamp(1.35rem, 2.2vw, 2.4rem); +} +.intro { max-width: 52ch; line-height: 1.6; color: #31345a; } +.hero__cta { + display: flex; + gap: .8rem; + margin-top: 2rem; + justify-content: center; + flex-wrap: wrap; +} +.hero-flair { + margin: 1.25rem auto 0; + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: .6rem; +} +.hero-flair span { + border-radius: 999px; + padding: .45rem .85rem; + font-weight: 700; + letter-spacing: .02em; + color: #3a2e8a; + background: linear-gradient(120deg, #fff7fb, #e7f3ff); + box-shadow: 0 8px 16px rgba(65, 49, 142, 0.12); +} + +.btn { + border: 2px solid var(--brand); + border-radius: 999px; + padding: .75rem 1.2rem; + font-weight: 700; + cursor: pointer; + text-decoration: none; +} +.btn--solid { background: linear-gradient(120deg, var(--brand), #7950f2); color: #fff; } +.btn--ghost { background: rgba(255,255,255,.55); color: var(--brand); } +.btn:hover { + transform: translateY(-2px); + box-shadow: 0 12px 20px rgba(72, 56, 158, 0.2); +} + +.cover-card { + background: linear-gradient(170deg, #ffffff, #faf9ff); + border-radius: 16px; + padding: .8rem; + box-shadow: var(--shadow); +} +.cover-card h3 { margin: .4rem 0 .8rem; font-size: 1rem; } +.cover-placeholder { + min-height: 260px; + border-radius: 12px; + display: grid; + place-items: center; + text-align: center; + color: #676b8a; + padding: 1rem; + background: linear-gradient(150deg, #f4f3ff, #ebe9ff); + box-shadow: inset 0 0 0 2px rgba(124, 106, 231, 0.18); +} + + +.cover-placeholder--image { + position: relative; + overflow: hidden; + cursor: pointer; + transition: transform 180ms ease, box-shadow 180ms ease; +} +.cover-placeholder--image:hover { + transform: translateY(-1px); +} +.cover-placeholder--image.is-dragover { + box-shadow: inset 0 0 0 3px #6956ea, 0 0 0 4px rgba(105, 86, 234, 0.18); + transform: scale(1.01); +} +.cover-placeholder--image img { + width: 100%; + height: 100%; + object-fit: cover; + border-radius: 10px; +} +.cover-placeholder__text { + margin: 0; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; + display: grid; + gap: .35rem; + text-align: center; +} +.cover-placeholder__text strong { + font-size: 1rem; + color: #5247a8; +} +.cover-placeholder__text span { + color: #75799f; + font-size: .92rem; +} +.cover-upload-btn { + display: inline-block; + margin-top: .7rem; + background: linear-gradient(130deg, #4f39ca, #6a50e6); + color: white; + padding: .5rem .8rem; + border-radius: 999px; + font-weight: 700; + cursor: pointer; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; +} +.cover-upload-input { + position: absolute; + opacity: 0; + pointer-events: none; + width: 0; + height: 0; +} + +main { max-width: 1200px; margin: 0 auto 4rem; padding: 0 2rem; } +.feature-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1rem; + margin: 2rem 0; +} +.feature-card { + background: linear-gradient(160deg, #ffffff 20%, #f9f7ff 70%, #eef9ff); + border-radius: 14px; + padding: 1.2rem; + box-shadow: var(--shadow); + min-height: 170px; + border: 1px solid rgba(124, 106, 231, 0.14); + transition: transform 180ms ease, box-shadow 180ms ease; +} +.feature-card:hover { + transform: translateY(-4px); + box-shadow: 0 20px 28px rgba(45, 31, 109, 0.16); +} + +.magazine-launch, .payment { + background: linear-gradient(165deg, #ffffff, #faf9ff 55%, #eef9ff); + border-radius: 16px; + padding: 1.5rem; + box-shadow: var(--shadow); + margin: 1rem 0; +} +.magazine-launch { + display: grid; + gap: 1rem; + justify-items: center; + position: relative; + overflow: hidden; +} +.magazine-launch::after { + content: ''; + position: absolute; + width: 220px; + height: 220px; + right: -70px; + top: -80px; + border-radius: 999px; + background: radial-gradient(circle, rgba(229, 106, 178, 0.18), transparent 70%); + pointer-events: none; +} +.quick-start { + margin: .35rem 0 0; + color: #555a86; + text-align: center; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; + font-size: .96rem; +} +.magazine-centerline { + width: 100%; + display: grid; + grid-template-columns: minmax(220px, 1fr) auto minmax(220px, 1fr); + align-items: center; + gap: 1rem; +} +.cover-card--side { + min-height: 420px; +} + +.magazine-dock { + border-radius: 18px; + width: min(370px, 88vw); + min-height: 570px; + background: linear-gradient(145deg, #1c4f90, #1e6ab7 52%, #1f83c8); + border: 2px solid #1c599f; + display: grid; + justify-items: center; + align-content: center; + gap: 1rem; + color: #f7f7ff; + cursor: pointer; + padding: 1.2rem; +} +.magazine-dock:focus-visible { outline: 3px solid #a493ff; outline-offset: 3px; } +.magazine-preview { + width: 270px; + min-height: 390px; + border-radius: 12px; + background: linear-gradient(170deg, #fefefe, #f4f9ff 56%, #deefff); + box-shadow: 0 12px 22px rgba(0,0,0,.35); + color: #2f2466; + padding: 1rem; + text-align: center; + display: grid; + align-content: start; + gap: .7rem; +} +.magazine-preview__eyebrow { + text-transform: uppercase; + letter-spacing: .08em; + font-size: .75rem; + margin: 0; + font-weight: 700; + color: #5a3cf0; +} +.magazine-preview h3 { margin: 0; font-family: 'Fredoka', 'OpenDyslexic', sans-serif; color: #1d4f8f; } +.magazine-preview__image-wrap { + min-height: 170px; + border-radius: 10px; + background: linear-gradient(160deg, #e5f4ff, #f4fbff); + display: grid; + place-items: center; + overflow: hidden; +} +.magazine-preview__image-wrap img { + width: 100%; + height: 100%; + object-fit: cover; +} +.magazine-preview__tag { margin: 0; font-weight: 700; color: #7a6cb5; padding: .4rem; text-align: center; } +.magazine-preview__burst { + margin: .4rem 0 0; + border-radius: 12px; + padding: .7rem; + font-weight: 800; + color: #1250a3; + background: linear-gradient(160deg, #e4f2ff, #fff2e8); +} +.magazine-dock__cta { + margin: 0; + text-align: center; + font-weight: 700; + max-width: 30ch; + color: #fff8ff; + text-shadow: 0 2px 8px rgba(0,0,0,.35); + font-family: 'OpenDyslexic', 'Manrope', sans-serif; +} + +.quote-band { + margin: 1.4rem 0; + border-radius: 18px; + padding: 1.15rem 1.4rem; + background: linear-gradient(120deg, #2f2864, #6c46cf 45%, #2ca8b8); + color: #fefeff; + text-align: center; + box-shadow: var(--shadow); +} +.quote-band p { + margin: 0; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; + font-size: clamp(1rem, 1.55vw, 1.3rem); + line-height: 1.35; +} + +.payment__actions { display: flex; gap: .8rem; flex-wrap: wrap; } + +.modal { + position: fixed; + inset: 0; + display: none; + align-items: center; + justify-content: center; + z-index: 99; +} +.modal.open { display: flex; } +.modal__overlay { position: absolute; inset: 0; background: rgba(9, 7, 29, .5); } +.modal__close { + position: fixed; + top: .7rem; + right: 1rem; + z-index: 3; + border: none; + background: rgba(255,255,255,.75); + width: 44px; + height: 44px; + border-radius: 99px; + font-size: 2rem; + cursor: pointer; +} +.stage-tilt { perspective: 1800px; display: grid; place-items: center; margin: 0; z-index: 2; position: relative; --launch-x: 0px; --launch-y: 0px; } +.magazine { + width: min(420px, 88vw); + height: min(620px, 84vh); + position: relative; + transform-style: preserve-3d; + transform: rotateX(9deg); + animation: shootOut 540ms ease; + transition: width 500ms ease, transform 500ms ease; +} +.magazine.magazine--closed { + width: min(250px, 64vw); +} +.turn-hotspot { + position: absolute; + bottom: 0; + width: 74px; + height: 74px; + border: 0; + border-radius: 50%; + background: rgba(255, 255, 255, 0.15); + box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25); + cursor: pointer; + z-index: 4; +} +.turn-hotspot:hover { background: rgba(255, 255, 255, 0.28); } +.turn-hotspot--prev { left: -32px; } +.turn-hotspot--next { right: -32px; } +.turn-hotspot::before { + content: ''; + position: absolute; + inset: 24px; + border-top: 3px solid #fff; + border-right: 3px solid #fff; +} +.turn-hotspot--prev::before { transform: rotate(-135deg); left: 28px; } +.turn-hotspot--next::before { transform: rotate(45deg); right: 28px; } +.magazine.magazine--closed .sheet { + clip-path: inset(0 0 0 50%); +} +@keyframes shootOut { + from { transform: rotateX(9deg) scale(.72) translate3d(var(--launch-x), var(--launch-y), 0); opacity: 0; } + to { transform: rotateX(9deg) scale(1) translate3d(0, 0, 0); opacity: 1; } +} + +.sheet { + position: absolute; + inset: 0; + transform-style: preserve-3d; + transform-origin: left center; + transition: transform 750ms ease; +} +.sheet.flipped { transform: rotateY(-178deg); } +.page-face { + position: absolute; + width: 50%; + height: 100%; + top: 0; + backface-visibility: hidden; + overflow: hidden; + background: white; + border-radius: 8px; + box-shadow: 0 8px 26px rgba(0, 0, 0, 0.15); +} +.page-front { right: 0; border-left: 1px solid #ddd; } +.page-back { + left: 0; + transform: rotateY(180deg); + border-right: 1px solid #ddd; +} +.page-face::before, +.page-face::after { + content: ''; + position: absolute; + width: 38px; + height: 38px; + bottom: 0; + opacity: .38; +} +.page-front::after { + right: 0; + background: linear-gradient(135deg, transparent 50%, #b9b9d1 51%); +} +.page-back::before { + left: 0; + background: linear-gradient(225deg, transparent 50%, #b9b9d1 51%); +} + +.coupon-page { + padding: .75rem; + display: grid; + gap: .65rem; + background: linear-gradient(180deg, #f2f8ff, #dbefff 68%, #cae6ff); + border-radius: 12px; +} +.coupon-page__title { margin: 0; color: #18467b; font-size: .9rem; } +.coupon-page__number { + justify-self: end; + align-self: end; + width: 36px; + height: 36px; + border-radius: 50%; + background: #ff8b2b; + color: #fff; + display: grid; + place-items: center; + font-weight: 800; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; +} + +.coupon-grid { + display: grid; + grid-template-columns: 1fr; + gap: .55rem; +} +.coupon-slot { + border: 2px solid #8ebee9; + border-radius: 22px; + padding: .5rem; + min-height: 80px; + resize: vertical; + overflow: auto; + background: #fff; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; +} +.coupon-slot h4 { margin: 0 0 .2rem; color: #4326c6; font-size: .85rem; } +.coupon-slot p { margin: 0 0 .3rem; font-size: .72rem; } +.coupon-slot__offer { + border: 2px solid #8f74ff; + border-radius: 8px; + text-align: center; + font-weight: 800; + font-size: .72rem; + padding: .3rem; + margin-bottom: .3rem; +} +.coupon-slot__line { color: #545676; } +.coupon-slot__cutline { + border: 2px dotted #8f74ff; + border-radius: 8px; + padding: .35rem; + text-align: center; + font-weight: 600; + font-size: .68rem; +} +.hint { + position: fixed; + bottom: 10px; + left: 50%; + transform: translateX(-50%); + color: #fff; + z-index: 2; + margin: 0; + font-size: .9rem; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; +} + +.feature-card p, .payment p { + color: #31345a; +} + +@media (max-width: 900px) { + .feature-grid { grid-template-columns: 1fr; } + .magazine-centerline { grid-template-columns: 1fr; } + .hero-stats { max-width: 680px; gap: 2rem; } + .top-nav { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: .6rem; } + .approval { margin-bottom: 3.2rem; } + .mission-line { margin-bottom: 3rem; } + .hero-flair { justify-content: center; } + .top-nav { border-radius: 18px; } +} + +.cover-placeholder--image:focus-visible { + outline: 3px solid #8f81f2; + outline-offset: 3px; +} + +/* Storybook-inspired flair update */ +.hero--storybook { + max-width: 100%; + padding-bottom: 2rem; + background: + radial-gradient(circle at 10% 25%, rgba(117, 211, 255, 0.35), transparent 32%), + radial-gradient(circle at 90% 20%, rgba(247, 205, 222, 0.5), transparent 30%), + linear-gradient(180deg, #8bd7ff 0%, #d8f4ff 38%, #f3f3f5 88%); +} +.hero--storybook .top-nav { + max-width: 1200px; + margin: 0 auto; + background: rgba(13, 34, 99, 0.88); + color: #e8f1ff; +} +.hero--storybook .top-nav__brand, +.hero--storybook .top-nav__link:hover, +.hero--storybook .top-nav__link:focus-visible { + color: #ffffff; +} +.story-ribbon { + background: linear-gradient(120deg, #2c1d67, #5d2ca1 50%, #1c8ca7); + color: #ffe66d; + text-align: center; + padding: .95rem 1rem; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; + font-size: clamp(1.3rem, 2.2vw, 2rem); + letter-spacing: .02em; + text-transform: uppercase; + text-shadow: 0 3px 8px rgba(0, 0, 0, .35); +} +.story-ribbon p { margin: 0; } + +main { + max-width: 1200px; + margin: 0 auto 4rem; + padding: 0 2rem; +} +.section-card { + border: 2px solid rgba(105, 86, 234, 0.14); +} +.magazine-launch.section-card { + margin-top: 2rem; + background: linear-gradient(170deg, #fefefe, #f2f9ff 54%, #dfefff); +} +.magazine-launch h2 { + font-size: clamp(1.7rem, 2.4vw, 2.5rem); + margin: 0; + color: #1f2d55; +} +.dark-showcase { + margin: 2rem 0; + border-radius: 28px; + padding: 1.4rem; + background: linear-gradient(180deg, #1b5b9f 0%, #1d4f8b 100%); + color: #f4f6ff; + box-shadow: var(--shadow); +} +.section-title { + margin: .2rem 0 1rem; + text-align: center; + color: #64e8ff; + text-transform: uppercase; + letter-spacing: .08em; + font-size: clamp(1.05rem, 1.8vw, 1.4rem); +} +.dark-showcase .feature-grid { + margin: 0; +} +.dark-showcase .feature-card { + background: linear-gradient(165deg, #2e78c4, #1f5b9d 78%); + border: 1px solid rgba(178, 228, 255, 0.45); + color: #f2f5ff; +} + +.dark-showcase .feature-card h3, +.dark-showcase .feature-card p { + color: #f2f5ff; +} +.scene-strip { + margin: 1.6rem 0; + border-radius: 18px; + padding: 4.3rem 1.2rem; + text-align: center; + background: + linear-gradient(0deg, rgba(8, 71, 101, 0.35), rgba(8, 71, 101, 0.35)), + linear-gradient(145deg, #53c7ff, #5fd18f 45%, #396eb3); + color: #fff6a8; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; + font-size: clamp(1.25rem, 2vw, 1.7rem); + text-transform: uppercase; + text-shadow: 0 3px 10px rgba(0, 0, 0, .4); +} +.scene-strip p { margin: 0; } +.faq { + margin: 1.6rem 0; + background: #fff; + border-radius: 16px; + padding: 1.4rem; + box-shadow: var(--shadow); +} +.faq h2 { margin-top: 0; } +.faq details { + border: 1px solid #d6d9ef; + border-radius: 10px; + padding: .75rem .9rem; + background: #fafbff; +} +.faq details + details { margin-top: .6rem; } +.faq summary { + cursor: pointer; + font-weight: 700; +} +.faq p { margin: .6rem 0 0; color: #3f4467; } +.newsletter { + margin: 1.7rem 0; + border-radius: 16px; + padding: 1.5rem; + text-align: center; + color: #f4f4ff; + background: linear-gradient(160deg, #2a185f, #1e1450); +} +.newsletter h2 { + margin: 0 0 .4rem; + font-size: clamp(1.25rem, 2.2vw, 2rem); +} +.newsletter p { margin: 0 0 1rem; color: #d5d7f8; } +.newsletter__form { + display: flex; + gap: .6rem; + justify-content: center; + flex-wrap: wrap; +} +.newsletter__form input { + width: min(360px, 90vw); + border-radius: 999px; + border: none; + padding: .78rem 1rem; + font: inherit; +} + +@media (max-width: 900px) { + .story-ribbon { font-size: 1.05rem; } + .scene-strip { padding: 2.8rem 1rem; } +} + +.book-story { + margin: 2rem 0; + padding: 1.5rem; + background: linear-gradient(170deg, #ffffff, #eaf5ff 70%, #d6ebff); + border-radius: 30px; + box-shadow: var(--shadow); +} +.book-story h2 { + margin-top: 0; + font-family: 'Fredoka', 'OpenDyslexic', sans-serif; + color: #0f4d8d; + text-align: center; + font-size: clamp(1.7rem, 3vw, 2.4rem); +} +.story-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1rem; +} +.story-card { + position: relative; + background: linear-gradient(165deg, #f8fcff, #e1f0ff); + border: 2px solid #afd5f7; + border-radius: 24px; + padding: 1rem 1rem 1rem 1.1rem; + min-height: 180px; +} +.story-card__number { + position: absolute; + top: -14px; + right: 12px; + width: 34px; + height: 34px; + border-radius: 50%; + background: #ff8b2b; + color: #fff; + display: grid; + place-items: center; + font-weight: 800; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; +} +.story-card h3 { + margin: 0 0 .45rem; + color: #1250a3; + font-family: 'Fredoka', 'OpenDyslexic', sans-serif; +} +.story-card p { margin: 0; color: #214566; line-height: 1.45; } +.hero--storybook { + max-width: 100%; + padding-bottom: 2.8rem; + background: + radial-gradient(circle at 12% 18%, rgba(255, 160, 70, 0.45), transparent 26%), + radial-gradient(circle at 87% 17%, rgba(34, 159, 255, 0.35), transparent 34%), + linear-gradient(180deg, #70c9ff 0%, #b7e7ff 38%, #f3f9ff 88%); +} +.story-ribbon { + background: linear-gradient(120deg, #ff8a2d, #ff9b3a 45%, #1f73c7); + color: #fffef5; +} +@media (max-width: 900px) { + .story-grid { grid-template-columns: 1fr; } +} + +/* Energetic color refresh */ +body { + background: radial-gradient(circle at 15% 10%, #ffd487 0, transparent 28%), + radial-gradient(circle at 85% 15%, #ff9fd2 0, transparent 30%), + radial-gradient(circle at 78% 80%, #9dd7ff 0, transparent 30%), + linear-gradient(180deg, #76c9ff 0%, #bdeaff 35%, #fff7ef 100%); +} + +.hero--storybook { + background: + radial-gradient(circle at 12% 16%, rgba(255, 163, 66, 0.66), transparent 30%), + radial-gradient(circle at 88% 17%, rgba(255, 112, 179, 0.42), transparent 34%), + radial-gradient(circle at 55% 0%, rgba(94, 205, 255, 0.5), transparent 40%), + linear-gradient(180deg, #63c2ff 0%, #9fe1ff 42%, #f7fcff 92%); +} + +.story-ribbon { + background: linear-gradient(100deg, #ff7d2f, #ff4f87 40%, #5a56ff 80%, #11a8d6); + color: #fff9ef; + box-shadow: 0 10px 24px rgba(119, 57, 0, 0.25); +} + +.btn--solid { + background: linear-gradient(120deg, #ff7f2a, #ff4f87 48%, #3767ff); + border-color: #ff6a45; +} + +.btn--ghost { + background: rgba(255, 255, 255, 0.82); + color: #1d4ea1; + border-color: #1d74d8; +} + +.book-story { + background: linear-gradient(150deg, #fff4dc, #ffeaf7 35%, #daf0ff 72%, #d5ebff 100%); + border: 2px solid rgba(255, 136, 45, 0.35); +} + +.story-card { + background: linear-gradient(165deg, #fff8ee, #ffe3f4 52%, #dbf0ff); + border: 2px solid #ffc180; +} + +.story-card__number, +.coupon-page__number { + background: linear-gradient(180deg, #ff972e, #ff6f1d); + box-shadow: 0 6px 16px rgba(181, 78, 0, 0.35); +} + +.magazine-launch.section-card { + background: linear-gradient(165deg, #fff5df, #ffe8f3 45%, #dff2ff 100%); + border: 2px solid rgba(255, 128, 44, 0.34); +} + +.magazine-dock { + background: linear-gradient(155deg, #5f2cff, #ff4f87 45%, #ff8928 88%); + border: 3px solid rgba(255, 255, 255, 0.5); + box-shadow: 0 22px 30px rgba(78, 23, 115, 0.35); +} + +.dark-showcase { + background: linear-gradient(180deg, #5939c7 0%, #2b7dd5 56%, #19a7c8 100%); +} + +.dark-showcase .feature-card { + background: linear-gradient(170deg, rgba(255,255,255,.16), rgba(255,255,255,.08)); + border: 1px solid rgba(255, 255, 255, .45); + backdrop-filter: blur(2px); +} + +.quote-band { + background: linear-gradient(115deg, #ff8a2d, #ff5f7f 42%, #4f64ff 85%); +} + +.coupon-page { + background: linear-gradient(180deg, #e8f6ff, #d8ecff 55%, #ffe8d4); +} + +.coupon-slot { + border-color: #6cb3f0; + background: linear-gradient(180deg, #ffffff, #f7fcff); +} + +/* Conversion and character upgrades */ +.hero::before, +.hero::after { + display: none; +} + +.clarence-strip { + max-width: 1200px; + margin: 1.3rem auto 1.8rem; + padding: 1.2rem; + border-radius: 26px; + background: linear-gradient(145deg, #fff3df, #ffdff2 45%, #d9f2ff 100%); + border: 2px solid rgba(255, 129, 39, 0.35); +} +.clarence-strip__head { + text-align: center; + margin-bottom: .9rem; +} +.clarence-strip__head h2 { + margin: 0 0 .3rem; + font-family: 'Fredoka', 'OpenDyslexic', sans-serif; + color: #214a9a; +} +.clarence-strip__head p { + margin: 0 0 .7rem; + color: #3f5170; +} +.clarence-gallery { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: .8rem; +} +.clarence-tile { + border: 2px dashed #ff8f35; + border-radius: 20px; + min-height: 210px; + background: linear-gradient(165deg, #fffaf3, #eef8ff); + display: grid; + place-items: center; + text-align: center; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; + color: #4b5870; + padding: .8rem; + overflow: hidden; +} +.clarence-tile img { width: 100%; height: 100%; object-fit: cover; border-radius: 14px; } +.clarence-tile.is-mirror { border-style: solid; border-color: #8ec3ff; } +.clarence-tile:focus-visible { outline: 3px solid #7c67ff; outline-offset: 3px; } + +.magazine-centerline { + gap: 1.4rem; + align-items: stretch; +} +.cover-card--side { + min-height: auto; + padding: 1rem; + background: linear-gradient(160deg, rgba(255,255,255,.82), rgba(255,255,255,.65)); + border: 1px solid rgba(78, 109, 183, 0.18); + box-shadow: 0 10px 16px rgba(21, 48, 119, 0.11); +} +.cover-placeholder { + min-height: 320px; +} + +.proof-strip { + margin: 1.7rem 0; + border-radius: 24px; + padding: 1.2rem; + background: linear-gradient(140deg, #5f35c8, #2c74d2 58%, #1fb6c9); + color: #fff; +} +.proof-strip h2 { + margin: .1rem 0 1rem; + text-align: center; + font-family: 'Fredoka', 'OpenDyslexic', sans-serif; +} +.proof-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: .8rem; +} +.proof-grid blockquote { + margin: 0; + border-radius: 16px; + padding: .9rem; + background: rgba(255,255,255,.16); + border: 1px solid rgba(255,255,255,.4); +} +.proof-grid cite { display: block; margin-top: .6rem; font-style: normal; font-weight: 700; color: #fff3d5; } + +.payment .glossary-note { + margin-top: .9rem; + padding: .65rem .8rem; + border-radius: 12px; + background: rgba(255, 255, 255, 0.65); + color: #274363; + font-weight: 600; +} + +@media (max-width: 900px) { + .clarence-gallery, + .proof-grid { grid-template-columns: 1fr; } +} From 3573e9617e9b8ab4fb8531875d90472782134f5c Mon Sep 17 00:00:00 2001 From: offmybach <137804812+offmybach@users.noreply.github.com> Date: Thu, 26 Feb 2026 10:05:39 -0500 Subject: [PATCH 2/2] Reshape covers and rebuild 6-page magazine to match reference style --- index.html | 21 +++-- script.js | 243 +++++++++++++++++++++++++++++++++++------------------ style.css | 201 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 375 insertions(+), 90 deletions(-) diff --git a/index.html b/index.html index 94d0418..ab356de 100644 --- a/index.html +++ b/index.html @@ -98,10 +98,11 @@

Smart Shopper Victory

Step Into Clarence's Coupon Quest

Quick start: drag a cover image into either side card (or click the card) and it saves automatically. Then click the center magazine to pop it front-and-center.

+

-

Book Cover

+

Front Cover Upload (3:2)

Drop Front Cover Hereor click to choose

@@ -112,19 +113,23 @@

Book Cover

-

Alternate / Back Cover

+

Back Cover Upload (3:2)

Drop Back Cover Hereor click to choose

diff --git a/script.js b/script.js index 5eba412..51343b2 100644 --- a/script.js +++ b/script.js @@ -14,26 +14,28 @@ const frontCoverSlot = document.getElementById('frontCoverSlot'); const backCoverSlot = document.getElementById('backCoverSlot'); const frontCoverPreview = document.getElementById('frontCoverPreview'); const backCoverPreview = document.getElementById('backCoverPreview'); -const magazineFrontPreview = document.getElementById('magazineFrontPreview'); const clarenceImageInput = document.getElementById('clarenceImageInput'); const clarenceImageSlot = document.getElementById('clarenceImageSlot'); const clarenceImageMain = document.getElementById('clarenceImageMain'); const clarenceEcho1 = document.getElementById('clarenceEcho1'); const clarenceEcho2 = document.getElementById('clarenceEcho2'); - -const pageData = [ - { page: 1, title: 'Clarence Starts the Mission', theme: 'Earned Reward + Robot Dream' }, - { page: 2, title: "Mom's Money Lesson", theme: 'Needs, Wants, and Family Budget' }, - { page: 3, title: 'Coupon Homework', theme: 'Sale Ads + Comparison Shopping' }, - { page: 4, title: 'The Clearance Aisle Twist', theme: 'Smart Value Beats Flashy Price' }, - { page: 5, title: 'Checkout Win', theme: 'Coupon Stack + Receipt Smarts' }, - { page: 6, title: 'Wyze Shopper Mindset', theme: 'Savings Power for Life' } -]; +const uploadStatus = document.getElementById('uploadStatus'); const sheetCount = 3; let current = 0; const memoryStore = new Map(); + +function setUploadStatus(message, tone = 'ok') { + if (!uploadStatus) return; + uploadStatus.textContent = message; + uploadStatus.dataset.tone = tone; +} + +function hasMagazineMarkup() { + return Boolean(modal && openBtn && closeBtn && closeOverlay && magazine && slotTemplate && stageTilt); +} + function getSavedValue(key) { try { return localStorage.getItem(key) || memoryStore.get(key) || ''; @@ -47,27 +49,30 @@ function saveValue(key, value) { try { localStorage.setItem(key, value); } catch { - // Continue with in-memory storage when localStorage is unavailable + // Keep in memory when local storage is unavailable } } +function isImageFile(file) { + if (!file) return false; + return (file.type && file.type.startsWith('image/')) || /\.(png|jpe?g|gif|webp|svg|bmp|avif|heic|heif)$/i.test(file.name || ''); +} + function setCoverImage(dataUrl, targetImg) { if (!targetImg) return; + const placeholderText = targetImg.parentElement?.querySelector('.cover-placeholder__text'); if (dataUrl) { targetImg.src = dataUrl; targetImg.hidden = false; - const txt = targetImg.parentElement?.querySelector('.cover-placeholder__text, .magazine-preview__tag'); - if (txt) txt.hidden = true; + if (placeholderText) placeholderText.hidden = true; } else { targetImg.hidden = true; - const txt = targetImg.parentElement?.querySelector('.cover-placeholder__text, .magazine-preview__tag'); - if (txt) txt.hidden = false; + if (placeholderText) placeholderText.hidden = false; } } function applyFrontCover(dataUrl) { setCoverImage(dataUrl, frontCoverPreview); - setCoverImage(dataUrl, magazineFrontPreview); } function applyBackCover(dataUrl) { @@ -75,13 +80,26 @@ function applyBackCover(dataUrl) { } function applyClarenceImage(dataUrl) { - [clarenceImageMain, clarenceEcho1, clarenceEcho2].forEach((img) => setCoverImage(dataUrl, img)); + [clarenceImageMain, clarenceEcho1, clarenceEcho2].forEach((img) => { + if (!img) return; + img.src = dataUrl; + img.hidden = !dataUrl; + const fallback = img.parentElement?.querySelector('span'); + if (fallback) fallback.hidden = Boolean(dataUrl); + }); } function readFileToDataUrl(file, done) { - if (!file || !file.type.startsWith('image/')) return; + if (!isImageFile(file)) { + setUploadStatus('Please choose an image file (PNG, JPG, WEBP, etc).', 'error'); + return; + } const reader = new FileReader(); - reader.onload = () => done(String(reader.result || '')); + reader.onload = () => { + done(String(reader.result || '')); + setUploadStatus(`Uploaded: ${file.name}`, 'ok'); + }; + reader.onerror = () => setUploadStatus('Could not read that image file. Please try another one.', 'error'); reader.readAsDataURL(file); } @@ -128,84 +146,124 @@ function wireDropAndClick(slot, input, storageKey, applyFn) { }); } -window.addEventListener('dragover', (event) => event.preventDefault()); -window.addEventListener('drop', (event) => event.preventDefault()); - -applyFrontCover(getSavedValue('clarence-front-cover')); -applyBackCover(getSavedValue('clarence-back-cover')); -wireImageInput(frontCoverInput, 'clarence-front-cover', applyFrontCover); -wireImageInput(backCoverInput, 'clarence-back-cover', applyBackCover); -wireDropAndClick(frontCoverSlot, frontCoverInput, 'clarence-front-cover', applyFrontCover); -wireDropAndClick(backCoverSlot, backCoverInput, 'clarence-back-cover', applyBackCover); - -applyClarenceImage(getSavedValue('clarence-character-image')); -wireImageInput(clarenceImageInput, 'clarence-character-image', applyClarenceImage); -wireDropAndClick(clarenceImageSlot, clarenceImageInput, 'clarence-character-image', applyClarenceImage); - function beep() { const ctx = new (window.AudioContext || window.webkitAudioContext)(); const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.type = 'triangle'; - osc.frequency.value = 510; + osc.frequency.value = 500; gain.gain.setValueAtTime(0.08, ctx.currentTime); - gain.gain.exponentialRampToValueAtTime(0.0001, ctx.currentTime + 0.12); + gain.gain.exponentialRampToValueAtTime(0.0001, ctx.currentTime + 0.13); osc.connect(gain); gain.connect(ctx.destination); osc.start(); - osc.stop(ctx.currentTime + 0.12); + osc.stop(ctx.currentTime + 0.13); } -function makeCouponSlot(index) { - const slot = slotTemplate.content.firstElementChild.cloneNode(true); - slot.querySelector('h4').textContent = `Coupon ${index}`; - slot.querySelector('p').textContent = 'Editable details. Add your own coupon language, educator note, or family challenge here.'; - slot.querySelector('.coupon-slot__offer').textContent = `$${index} OFF`; - return slot; +function createCouponBlock(text = 'Editable coupon text goes here') { + const block = document.createElement('article'); + block.className = 'coupon-slot'; + block.contentEditable = 'true'; + + const copy = document.createElement('p'); + copy.textContent = text; + block.appendChild(copy); + + const cut = document.createElement('div'); + cut.className = 'coupon-slot__cutline'; + cut.contentEditable = 'true'; + cut.textContent = 'Editable dotted cut-line text'; + block.appendChild(cut); + + return block; } -function makeCouponPage(data) { - const page = document.createElement('section'); - page.className = 'page-face coupon-page'; +function createPageHeader() { + const header = document.createElement('div'); + header.className = 'coupon-page__header'; + + const mast = document.createElement('div'); + mast.className = 'coupon-page__masthead'; + mast.contentEditable = 'true'; + mast.setAttribute('aria-label', 'Store title'); + mast.textContent = ''; + + const sub = document.createElement('div'); + sub.className = 'coupon-page__sub'; + sub.contentEditable = 'true'; + sub.textContent = 'Extra Savings'; - const heading = document.createElement('h3'); - heading.className = 'coupon-page__title'; - heading.textContent = `${data.title} • ${data.theme}`; - heading.contentEditable = 'true'; + const title = document.createElement('div'); + title.className = 'coupon-page__hero-title'; + title.contentEditable = 'true'; + title.textContent = 'COUPONS'; - const pageNumber = document.createElement('span'); - pageNumber.className = 'coupon-page__number'; - pageNumber.textContent = String(data.page); + header.append(mast, sub, title); + return header; +} + +function makeCouponPage(pageNumber) { + const page = document.createElement('section'); + page.className = 'page-face coupon-page'; + const header = createPageHeader(); const grid = document.createElement('div'); grid.className = 'coupon-grid'; - for (let i = 1; i <= 4; i++) { - grid.appendChild(makeCouponSlot(i)); - } - page.append(heading, grid, pageNumber); + const starter = [ + 'TAKE AN EXTRA 10% OFF ALL CLEARANCE TOYS!', + '$5.00 OFF ALL SMART ROBOTS', + 'BUY ONE GAME, GET ONE HALF PRICE!' + ]; + + starter.forEach((line) => grid.appendChild(createCouponBlock(line))); + + const num = document.createElement('span'); + num.className = 'coupon-page__number'; + num.textContent = String(pageNumber); + + page.append(header, grid, num); + return page; +} + +function makeOpenNotePage(pageNumber) { + const page = document.createElement('section'); + page.className = 'page-face coupon-page coupon-page--open'; + const header = createPageHeader(); + const note = document.createElement('div'); + note.className = 'coupon-page__open-note'; + note.contentEditable = 'true'; + note.textContent = 'Open page space for upcoming content.'; + const num = document.createElement('span'); + num.className = 'coupon-page__number'; + num.textContent = String(pageNumber); + page.append(header, note, num); return page; } function buildMagazine() { + if (!magazine) return; magazine.innerHTML = ''; - for (let i = 0; i < sheetCount; i++) { + for (let i = 0; i < sheetCount; i += 1) { const sheet = document.createElement('article'); sheet.className = 'sheet'; sheet.style.zIndex = String(sheetCount - i); - const front = makeCouponPage(pageData[i * 2]); - const back = makeCouponPage(pageData[i * 2 + 1]); + const leftPageNo = i * 2 + 1; + const rightPageNo = leftPageNo + 1; + + const front = leftPageNo <= 4 ? makeCouponPage(leftPageNo) : makeOpenNotePage(leftPageNo); + const back = rightPageNo <= 4 ? makeCouponPage(rightPageNo) : makeOpenNotePage(rightPageNo); front.classList.add('page-front'); back.classList.add('page-back'); - sheet.append(front, back); magazine.appendChild(sheet); } } function updateFlips() { + if (!magazine) return; magazine.classList.toggle('magazine--closed', current === 0); [...magazine.children].forEach((sheet, idx) => { sheet.classList.toggle('flipped', idx < current); @@ -229,57 +287,78 @@ function goBack(playSound = true) { } } -magazine.addEventListener('click', (event) => { - const bounds = magazine.getBoundingClientRect(); - const x = event.clientX - bounds.left; - const y = event.clientY - bounds.top; - if (y <= bounds.height * 0.62) return; - if (x > bounds.width * 0.72) goForward(); - if (x < bounds.width * 0.28) goBack(); -}); - function openMagazine() { + if (!hasMagazineMarkup()) return; const dockRect = openBtn.getBoundingClientRect(); const centerX = window.innerWidth / 2; const centerY = window.innerHeight / 2; const dockX = dockRect.left + dockRect.width / 2; const dockY = dockRect.top + dockRect.height / 2; - const dx = Math.round(dockX - centerX); - const dy = Math.round(dockY - centerY); - - stageTilt?.style.setProperty('--launch-x', `${dx}px`); - stageTilt?.style.setProperty('--launch-y', `${dy}px`); + stageTilt.style.setProperty('--launch-x', `${Math.round(dockX - centerX)}px`); + stageTilt.style.setProperty('--launch-y', `${Math.round(dockY - centerY)}px`); modal.classList.add('open'); modal.setAttribute('aria-hidden', 'false'); if (current === 0) { - window.setTimeout(() => goForward(false), 260); + window.setTimeout(() => goForward(false), 230); } } function closeMagazineModal() { + if (!modal) return; modal.classList.remove('open'); modal.setAttribute('aria-hidden', 'true'); } -openBtn.addEventListener('click', openMagazine); -openBtn.addEventListener('keydown', (event) => { +window.addEventListener('dragover', (event) => event.preventDefault()); +window.addEventListener('drop', (event) => event.preventDefault()); + +applyFrontCover(getSavedValue('clarence-front-cover')); +applyBackCover(getSavedValue('clarence-back-cover')); +wireImageInput(frontCoverInput, 'clarence-front-cover', applyFrontCover); +wireImageInput(backCoverInput, 'clarence-back-cover', applyBackCover); +wireDropAndClick(frontCoverSlot, frontCoverInput, 'clarence-front-cover', applyFrontCover); +wireDropAndClick(backCoverSlot, backCoverInput, 'clarence-back-cover', applyBackCover); + +applyClarenceImage(getSavedValue('clarence-character-image')); +wireImageInput(clarenceImageInput, 'clarence-character-image', applyClarenceImage); +wireDropAndClick(clarenceImageSlot, clarenceImageInput, 'clarence-character-image', applyClarenceImage); + +setUploadStatus('Tip: cover slots use a 3:2 shape. Drop or click to upload.', 'ok'); + +if (magazine) { + magazine.addEventListener('click', (event) => { + const bounds = magazine.getBoundingClientRect(); + const x = event.clientX - bounds.left; + const y = event.clientY - bounds.top; + if (y <= bounds.height * 0.58) return; + if (x > bounds.width * 0.72) goForward(); + if (x < bounds.width * 0.28) goBack(); + }); +} + +openBtn?.addEventListener('click', openMagazine); +openBtn?.addEventListener('keydown', (event) => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); openMagazine(); } }); - -closeBtn.addEventListener('click', closeMagazineModal); -closeOverlay.addEventListener('click', closeMagazineModal); +closeBtn?.addEventListener('click', closeMagazineModal); +closeOverlay?.addEventListener('click', closeMagazineModal); nextHotspot?.addEventListener('click', goForward); prevHotspot?.addEventListener('click', goBack); + document.addEventListener('keydown', (event) => { if (event.key === 'Escape') closeMagazineModal(); if (event.key === 'ArrowRight') goForward(); if (event.key === 'ArrowLeft') goBack(); }); -buildMagazine(); -updateFlips(); +if (hasMagazineMarkup()) { + buildMagazine(); + updateFlips(); +} else { + setUploadStatus('Files are out of sync. Please copy newest index.html, style.css, and script.js together.', 'error'); +} diff --git a/style.css b/style.css index 770af59..67d7c5e 100644 --- a/style.css +++ b/style.css @@ -1044,3 +1044,204 @@ body { .clarence-gallery, .proof-grid { grid-template-columns: 1fr; } } + +/* Magazine refresh per latest visual direction */ +.cover-placeholder { + aspect-ratio: 3 / 2; + min-height: 0; +} +.cover-placeholder--image img { + width: 100%; + height: 100%; + object-fit: contain; + background: #f8f5ee; +} + +.magazine-preview { + background: linear-gradient(180deg, #f0dff8, #e8d9f4 65%, #e2d2ef); + border: 2px solid #2c8ac1; + box-shadow: 0 18px 32px rgba(61, 27, 112, 0.22); + font-family: 'Fredoka', 'Manrope', sans-serif; +} +.magazine-preview h3 { + color: #2d2450; + margin-bottom: 0.45rem; +} +.magazine-preview__eyebrow { + color: #365886; +} +.magazine-preview__mock { + background: #eee8dc; + border: 3px solid #2f8ec4; + border-radius: 8px; + padding: 0.45rem; +} +.magazine-preview__bar { + height: 24px; + background: linear-gradient(90deg, #3049c7, #2c87ce); + border-radius: 4px; + margin-bottom: 0.45rem; +} +.magazine-preview__save { + text-align: center; + margin: 0; + color: #cf4b2d; + font-weight: 700; +} +.magazine-preview__title { + text-align: center; + margin: 0.1rem 0 0.5rem; + color: #11275a; + font-size: clamp(1.5rem, 2.5vw, 2rem); + font-weight: 700; +} +.magazine-preview__dash { + border: 2px dashed rgba(86, 69, 54, 0.8); + border-radius: 8px; + height: 30px; + margin-bottom: 0.35rem; +} +.magazine-preview__dash:last-child { margin-bottom: 0; } +.magazine-preview__burst { + color: #35205f; + background: rgba(255, 255, 255, 0.55); + border-radius: 999px; + padding: 0.35rem 0.7rem; +} + +.modal__overlay { + background: rgba(18, 9, 34, 0.62); +} +.stage-tilt { + width: min(94vw, 1480px); +} +.magazine { + width: min(90vw, 1320px); + height: min(76vh, 860px); +} +.magazine.magazine--closed { + width: min(48vw, 540px); + height: min(72vh, 760px); +} +.sheet { + transform-origin: left center; +} +.page-face { + background: #efe9dc; + border: 3px solid #2c8ac1; + border-radius: 4px; + padding: 0; +} +.coupon-page { + display: grid; + grid-template-rows: auto 1fr auto; +} +.coupon-page__header { + padding: 0; +} +.coupon-page__masthead { + min-height: 52px; + background: linear-gradient(90deg, #2a53cc, #1d90d4); + border-bottom: 2px solid #1c669f; + color: #ffffff; + font-family: 'Fredoka', 'Manrope', sans-serif; + font-size: clamp(1.6rem, 3.2vw, 3.2rem); + font-weight: 600; + line-height: 1; + text-align: center; + padding: 0.3em 0.2em; +} +.coupon-page__sub { + text-align: center; + color: #cf4b2d; + font-family: 'Fredoka', 'Manrope', sans-serif; + font-size: clamp(1.3rem, 2.2vw, 2.2rem); + font-weight: 600; + margin-top: 0.25rem; +} +.coupon-page__hero-title { + text-align: center; + color: #11275a; + font-family: 'Fredoka', 'Manrope', sans-serif; + font-size: clamp(2.3rem, 4.9vw, 5.3rem); + line-height: 1; + font-weight: 700; + margin-bottom: 0.3rem; +} +.coupon-grid { + padding: 0.25rem 0.75rem 0.65rem; + display: grid; + grid-template-columns: 1fr; + gap: 0.45rem; +} +.coupon-slot { + border: 3px dashed rgba(93, 75, 57, 0.84); + border-radius: 8px; + background: transparent; + min-height: 96px; + padding: 0.55rem 0.7rem; + display: grid; + grid-template-rows: 1fr auto; +} +.coupon-slot p { + margin: 0; + color: #1a2452; + font-family: 'Fredoka', 'Manrope', sans-serif; + font-size: clamp(1.05rem, 2vw, 2rem); + font-weight: 600; + text-transform: uppercase; + text-shadow: 0 2px 0 rgba(255, 255, 255, 0.4); +} +.coupon-slot__cutline { + border-top: 2px dashed rgba(86, 67, 49, 0.8); + padding-top: 0.25rem; + color: #5d5567; + font-size: 0.75rem; +} +.coupon-page__number { + width: 42px; + height: 42px; + right: 12px; + bottom: 10px; + background: #ff972e; + color: #fff; + border: 2px solid #d66f0f; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.18); +} +.coupon-page--open .coupon-page__open-note { + margin: 0.6rem; + border: 3px dashed rgba(93, 75, 57, 0.8); + border-radius: 10px; + display: grid; + place-items: center; + font-family: 'Fredoka', 'Manrope', sans-serif; + color: #4f4961; + font-size: clamp(1rem, 1.8vw, 1.4rem); + min-height: 220px; + text-align: center; + padding: 1rem; +} + +.upload-status { + margin: 0.45rem 0 0; + min-height: 1.2rem; + font-family: 'OpenDyslexic', 'Manrope', sans-serif; + font-size: 0.92rem; + color: #2f5e95; + text-align: center; +} +.upload-status[data-tone='error'] { + color: #b1381f; + font-weight: 700; +} + +@media (max-width: 900px) { + .magazine { + width: min(96vw, 1080px); + height: min(72vh, 730px); + } + .magazine.magazine--closed { + width: min(66vw, 420px); + height: min(66vh, 620px); + } +}