Nav title: absolutely centered in the site-header, fades in via
IntersectionObserver when .story-hero__content scrolls above the fold.
Hidden on mobile (< 640px) where there is no room.
Back-to-top: fixed bottom-right pill, appears after 80% of the hero
viewport is scrolled past, smooth-scrolls to top on click.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
Overlay previously hard-hid with display:none when scrollY = 100vh, while
the title was still visible (it exits at ~115vh). Now fades in 0→0.65 over
the first 70vh then fades back out to 0 by 140vh (full hero height).
Scrolly caption changed from full-width to centered pill with
rgba(0,0,0,0.45) background — readable against any image regardless of tone.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
Adds haversineKm, extractTrackpoints, isNearTrack, buildJourneySegments, and
addJourneySegments to the shared MapLibre GL IIFE. Updates MapUtils export to
expose the new functions. ES5-only; no arrow functions, const/let, or modules.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPJztrVGbwic2xTG7G9fjM
Both stats.html.twig and trip.html.twig previously flattened all GPX
trackpoints into a single masterPts array before computing haversine
distance, elevation, and moving time. This caused the junction between
file N's last point and file N+1's first point to be treated as a real
segment — e.g. Florence→coast (~79 km, ~42 h) for Italy's 3-file demo
data, overstating distance and moving time significantly.
Fix: compute all metrics within each file independently and sum the
results. fileResults collection and callback consumption are unchanged.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPJztrVGbwic2xTG7G9fjM
Pre-allocate fileResults[idx] slots so GPX files always concatenate in URL
order regardless of fetch arrival order (Bug 1). Both .then and .catch now
call computeDistance() after decrementing pending so a failed last fetch no
longer leaves the distance element permanently blank (Bug 2).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPJztrVGbwic2xTG7G9fjM
Adds Twig computation for days on road, countries visited, and GPS
points; an expandable stats panel (hidden by default) with haversine
distance calculation; and toggle JS that activates the Stats button.
Added JavaScript to the trip.html.twig template that:
- Adds event listeners to filter buttons (.trip-filter-btn)
- Shows/hides article cards based on data-type attribute (journal/story)
- Manages active state of filter buttons
- Displays empty state message when no results match the filter
- Uses ES5 syntax (no arrow functions, const/let, or template literals)
Also added hidden feed-filter-empty element to display appropriate
empty messages for each filter type.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RB86BaJBG3eGiMdfhmHRrQ
Replace the old trip-nav links with a new filter bar component featuring:
- Three pill buttons for filtering (All content, Journal, Stories)
- "All content" button active by default with teal accent styling
- Separate Stats button with matching pill styling
- CSS for buttons with hover and active states
- Responsive flexbox layout that wraps on narrow screens
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RB86BaJBG3eGiMdfhmHRrQ
- Same home-layout (45% sticky map / 55% scrollable feed) on every trip page
- GPX route overlay loaded from trip page media
- Marker click scrolls to entry card (same as home page)
- Map sub-nav link removed (map is now embedded)
- Separate /map page remains accessible by URL but has no nav link
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RB86BaJBG3eGiMdfhmHRrQ
- Explicit height: 40vh on .home-map (not just 100% of parent) so Leaflet
can measure the container reliably before CSS inheritance is resolved
- align-self: stretch on .home-map-col so it spans full width in flex column
- setTimeout invalidateSize(100ms) on home and dailies maps as safety net
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RB86BaJBG3eGiMdfhmHRrQ
- Past Trips nav link: add missing / (base_url_absolute has no trailing slash)
- Entry back link: history.back() with journal fallback, label → "← Back"
- Home page: max-width 1400px instead of none — narrows layout on wide screens
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RB86BaJBG3eGiMdfhmHRrQ
- entry.html.twig: replace hardcoded /tracker href with page.parent().url
- post-form.md: add comment to keep pageconfig.parent in sync with active_trip in site.yaml
Adds leaflet-gpx@2.1.2 CDN script to map template, collects *.gpx
media files from the trip page, and renders them as teal polylines
beneath entry pins. Also fixes user/config/media.yaml to use the
required types: key so Grav's Media class correctly discovers .gpx
files. Map remains functional when no GPX files are present.
- Rename tracker.html.twig to dailies.html.twig; update dailies.md template key
- Fix map.html.twig and stats.html.twig: find dailies via page.parent().route
- Update base.html.twig nav to use config.site.active_trip for all hrefs
- Fix dailies.html.twig mini-map link to use page.parent().url/map
- Create trip.html.twig, trips.html.twig, stories.html.twig
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New demo entry: Arashiyama with single hero image (bamboo.jpg)
- New demo entry: Gyeongbokgung with four gallery images (palace-gate,
throne-hall, hanok-rooftops, bugaksan)
- post-form.md: add upload: true to process block so filepond photo
uploads are handled after page creation; simplify list-of-maps to
flat map (Symfony YAML preserves insertion order)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Changes dateformat.default from 'd M Y' to 'Y-m-d H:i' so dates
submitted via the post form are stored as '2026-06-19 10:30' rather
than '18 Jun 2026'. This ensures add-page-by-form generates slugs in
YYYY-MM-DD-HHmm-title order, preserving chronological sort.
All templates use explicit |date() filters so display is unaffected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add blueprints.yaml for cache-on-save plugin with Grav 2.0 support
- Update system.yaml GPM setting from stable to testing channel
- Update .gitignore to allow cache-on-save plugin tracking
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Seven fixture entries (March 25 Narita through April 1 Seoul) used as
Playwright test fixtures for tracker ordering and entry-page tests.
Removes the leftover June 18 test entry.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
page.children ignores the order.by/dir frontmatter config; page.collection()
applies it, so entries now render newest-first as intended.
Also wire Grav asset pipeline into base template (assets.css/js tags).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two root-cause bugs:
1. Wrong action name: 'add-page-by-form' is not handled by the plugin;
the plugin only matches 'addpage' or 'add_page'. Using the wrong name
meant the action silently no-oped while 'message' still fired, showing
'Entry posted successfully!' for a post that was never written.
2. Config in wrong place: parent/slug/template must be in 'pageconfig' and
'pagefrontmatter' frontmatter blocks on the form page — the plugin reads
from page->header(), not from the process block params.
Fix: move config to pageconfig/pagefrontmatter, change action to 'add_page'.
Slug is built from date+title fields (e.g. 2026-06-18-1430-my-title).
Photos destination changed to '@self' so the plugin copies from flash to
the new entry folder correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- entry.html.twig: add |raw to page.content (autoescape: true in
system.yaml was escaping all HTML output including rendered markdown)
- tracker.html.twig: use |striptags|slice(0,250) for clean plain-text
excerpts instead of raw HTML summary
- Both templates: fix location display whitespace (Tokyo , Japan → Tokyo, Japan)
using parts array pattern with Twig whitespace control
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>