Fix story scrolly text rendering; story/trip blueprint media upload

Scrolly-section text never rendered: the inline Scrollama block ran before
the main.js bundle published window.scrollama, so it always hit its guard
and the panel text stayed display:none, leaving a blank column beside the
pinned image. Defer to DOMContentLoaded, and build the step panels before
the scrollama check so a missing bundle costs the animation, not the text.

Also fixes an invalid calc(-(...)) that dropped the mobile scrolly offset,
and drops the duplicate inline back-to-top in favour of main.js's version
(which pushes a history entry).

Blueprint changes carried over from an earlier session: story.yaml and
trip.yaml now extend the default page form so both can upload media.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-29 23:12:45 +02:00
co-authored by Claude Opus 5
parent 0ebb770bc7
commit e81c73a9ba
4 changed files with 104 additions and 49 deletions
+19 -22
View File
@@ -132,23 +132,11 @@
update();
})();
/* ── Back to top button ─────────────────────────────────── */
(function () {
var btn = document.getElementById('story-totop');
if (!btn) return;
var threshold = window.innerHeight * 0.8;
var shown = false;
btn.addEventListener('click', function () {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
window.addEventListener('scroll', function () {
var shouldShow = window.scrollY > threshold;
if (shouldShow !== shown) {
shown = shouldShow;
btn.classList.toggle('is-visible', shown);
}
}, { passive: true });
})();
/* ── Back to top button ───────────────────────────────────
Owned by initBackToTop('story-totop') in js/src/main.js, called from its
DOMContentLoaded boot. An inline copy used to live here and double-bound
both the click and scroll handlers; it also lacked the history.pushState
that makes Back return to the reading position. Do not re-add it. */
/* ── ChapterBreak scroll-reveal ─────────────────────────── */
(function () {
@@ -216,11 +204,17 @@
update();
})();
/* ── ScrollySection (Scrollama) ──────────────────────────── */
(function () {
/* ── ScrollySection (Scrollama) ────────────────────────────
Deferred to DOMContentLoaded on purpose: `scrollama` is published by the
js/main.js bundle, which Grav emits via assets.js('bottom') *after* this
inline script (base.html.twig renders block content first). Running inline
would hit the scrollama guard every time, leaving .scrolly__steps-content
hidden and the text column blank. DOMContentLoaded fires only after all
classic scripts have executed, so scrollama is available by then. */
document.addEventListener('DOMContentLoaded', function () {
var reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
var sections = document.querySelectorAll('.scrolly');
if (!sections.length || typeof scrollama === 'undefined') return;
if (!sections.length) return;
var panOffsets = ['50% 40%', '50% 50%', '50% 60%', '50% 45%', '50% 55%'];
@@ -252,7 +246,10 @@
stepsWrap.appendChild(step);
});
if (reduced) {
/* Step-building above must never be gated on scrollama: the slot content is
display:none in CSS, so bailing before this point loses the text entirely.
Degrade to plain visible panels instead — no pinning, but readable. */
if (reduced || typeof scrollama === 'undefined') {
section.querySelectorAll('.scrolly-step').forEach(function (s) { s.classList.add('is-active'); });
return;
}
@@ -281,6 +278,6 @@
if (d.direction === 'up') d.element.classList.remove('is-active');
});
});
})();
});
</script>
{% endblock %}