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.
+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 @@ + + +
+ + +Financial Literacy Adventure Series
+Approved by at least 3 teachers (my mother (retired), brother, and neighbor)
+ + +Clarence Wyze thinks he needs the newest robot… until Mom teaches him comparison shopping, coupons, and the superpower of saving.
+ +KID LIT IS A HIT! AND KID FIN IS A WIN!
+Stealthy Edutainment for growing money-smart minds.
+ + +Wish You Were Here!
+Drop one Clarence image below and it repeats across the page for a strong character brand feel.
+ + +Clarence finally gets his shopping day after earning top grades and finishing chores — and he wants the newest smart robot he can find.
+He learns that families budget for needs, compare prices, and use sale ads and coupons before shopping trips.
+A hilarious mix-up leads to the clearance aisle, where Clarence discovers that smart choices beat flashy choices.
+He stacks a coupon on a clearance deal, saves more money, and leaves with confidence plus real-life financial literacy skills.
+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.
+Drop Front Cover Hereor click to choose
+Click here to see about Clarence's quest for the perfect smart robot
+Drop Back Cover Hereor click to choose
+A polished, grown-up visual style made for parents and educators reading to kids.
+Built-in coupon pages support activities, incentive moments, and lesson tie-ins.
+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.”
+“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+
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.
+Editable coupon details go here.
+Terms & notes
+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.
+Drop Front Cover Hereor click to choose
@@ -112,19 +113,23 @@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); + } +}