diff --git a/backend/app/prompts.py b/backend/app/prompts.py index 432f568..aeb91f6 100644 --- a/backend/app/prompts.py +++ b/backend/app/prompts.py @@ -121,10 +121,11 @@ def get_art_style_phrase(style_id: str) -> str: that they are anatomically correct in each image. CRITICAL — every image_prompt MUST end with this exact negative constraint (fill in the character name(s) for that page): "Only [name(s)] should appear as prominent, named characters - in this image. Do not include any other animals or living creatures in the scene — only - the characters listed in character_descriptions may appear as animals or creatures. - Anonymous background figures (crowds, townspeople, soldiers, passersby, etc.) - are acceptable when the narrative describes them, but they should remain small, non-detailed, + in this image. Do not invent any additional NAMED characters that are not in + character_descriptions. Anonymous background figures and creatures + (crowds, townspeople, soldiers, passersby, woodland animals, birds, insects, fish, + fantastical creatures, etc.) ARE welcome whenever the narrative text or scene + description references them — but they must remain small, non-detailed, unnamed, and clearly secondary to the named characters." """ @@ -386,9 +387,19 @@ def get_art_style_phrase(style_id: str) -> str: - Background details present in the image but not mentioned in the text (decorative flowers, atmospheric mist, distant scenery) are NEVER an art-text contradiction unless they directly conflict with the text. - - Anonymous background figures (crowds, townspeople, neighbours, soldiers) - are fine when the narrative calls for them. A NEW named character not - in the canonical list, drawn as a prominent figure, IS a failure. + - Anonymous background figures and creatures (crowds, townspeople, + neighbours, soldiers, woodland animals, birds, insects, fish, fantastical + creatures, etc.) are fine when the narrative calls for them — and they + are EXPECTED in the illustration whenever the page text or scene + description references them (e.g. "wobbling silhouettes", + "fluttering fireflies", "darting fish in the stream", "a few curious + forest critters watched from the bushes"). DO NOT flag such background + creatures as "unauthorized characters", "extra figures", or art-text + mismatches just because they aren't in character_descriptions; the + canonical character list only governs PROMINENT, NAMED characters. The + only real failure here is a NEW named character (or an unmistakably + prominent, focal new creature/person that the text does not reference at + all) drawn alongside the canonical cast. 3. age_appropriateness_pass — does the image contain anything genuinely frightening, gory, or unsuitable for ages 5–8? Mild tension and "spooky" diff --git a/frontend/src/assets/bodybackground.png b/frontend/src/assets/bodybackground.png new file mode 100644 index 0000000..140828f Binary files /dev/null and b/frontend/src/assets/bodybackground.png differ diff --git a/frontend/src/components/StoryBook.module.css b/frontend/src/components/StoryBook.module.css index d3f1862..8a86baf 100644 --- a/frontend/src/components/StoryBook.module.css +++ b/frontend/src/components/StoryBook.module.css @@ -16,13 +16,15 @@ .title { font-size: 2.2rem; - color: var(--color-primary); + color: #ffffff; margin-bottom: 6px; + text-shadow: 0 2px 6px rgba(0, 0, 0, 0.55); } .meta { font-size: 0.9rem; - color: var(--color-text-muted); + color: rgba(255, 255, 255, 0.85); + text-shadow: 0 1px 4px rgba(0, 0, 0, 0.5); } /* Revision / review notes banner */ @@ -174,3 +176,20 @@ justify-content: center; margin-top: 8px; } + +/* Light-on-dark override for the Save Story / Create Another Story buttons, + * which sit directly on the navy body background (outside any white card). + * Scoped to .actions so the .btn-secondary used inside cards elsewhere + * (e.g. the "Try Again" button on the generating screen) is unaffected. */ +.actions :global(.btn-secondary) { + color: #ffffff; + border-color: rgba(255, 255, 255, 0.75); + background: rgba(255, 255, 255, 0.08); + backdrop-filter: blur(2px); +} + +.actions :global(.btn-secondary):hover { + background: rgba(255, 255, 255, 0.95); + color: var(--color-primary); + border-color: #ffffff; +} diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index 5b51b75..c0132a3 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -56,7 +56,16 @@ body { html, body { font-family: var(--font-body); - background-color: var(--color-bg); + /* Starry-sky body background. background-attachment: fixed keeps the + * sky pinned to the viewport so the content scrolls over it (rather + * than stretching the image to the full page height). Fallback color + * roughly matches the average sky tone if the image fails to load. */ + background-color: #0e1e74; + background-image: url('../assets/bodybackground.png'); + background-size: cover; + background-position: center center; + background-repeat: no-repeat; + background-attachment: fixed; color: var(--color-text); font-size: 16px; line-height: 1.6; @@ -106,6 +115,12 @@ button { box-shadow: var(--shadow-md); overflow: hidden; min-height: 180px; + /* Feather the bottom edge of the header so the sky imagery blends into + * the matching navy body background. Top 80% fully opaque, bottom 20% + * fades to transparent. (Only affects the header element; form fields + * live in .app-main and are not touched by this mask.) */ + -webkit-mask-image: linear-gradient(to bottom, black 80%, transparent 100%); + mask-image: linear-gradient(to bottom, black 80%, transparent 100%); } /* Castle/book illustration anchored to the right edge, layered on top of