Commit Graph

130 Commits

Author SHA1 Message Date
m038 a398bcb737 feat: add map-to-card flash highlight on marker click 2026-06-20 12:47:51 +02:00
m038 9365f46440 fix: apply flat entry-card structure to home.html.twig 2026-06-20 12:43:58 +02:00
m038 246fbfde76 fix: add missing data-type attributes to entry cards in dailies.html.twig 2026-06-20 12:40:58 +02:00
m038 2a151b710c refactor: collapse entry card article+a to flat <a>, unify hover targets across card types
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPJztrVGbwic2xTG7G9fjM
2026-06-20 12:38:28 +02:00
m038 ca920a9fe8 feat: add fixed top and footer back pills to entry page 2026-06-20 12:31:09 +02:00
m038 26182ec363 feat: apply back-pill class to story footer back link
Apply the .back-pill class to the story footer back link and add
:not(.back-pill) guard to .story-footer a rule to prevent the accent
color override. This ensures the back pill maintains its design system
styling (border, background, text color) in story footers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPJztrVGbwic2xTG7G9fjM
2026-06-20 12:23:53 +02:00
m038 5bc8d008df fix(story): end_date format Y-m-d H:i; fix guard comparison; remove test data
Blueprint: end_date format changed to Y-m-d H:i (same as start date) so
Admin2 uses the identical datepicker — avoids ambiguous d-m-Y input being
misread by PHP as m-d-Y.

Template guard: was comparing end_date string against page.date|date('Y-m-d')
which can never match. Now compares date-only parts of both fields:
page.header.end_date|date('Y-m-d') != page.date|date('Y-m-d')

Montalcino live page: removed test end_date '12-09-2026 00:00'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
2026-06-20 12:10:21 +02:00
m038 5eca310bd8 fix(story): remove spurious end_date from Montalcino; guard start==end range
Montalcino demo story had end_date: 2025-09-06 matching its start date,
causing a '06 – 06 Sep' range display. Removed from both the live page
and the demo source.

Template: added guard so end_date equal to the start date never renders
as a range, even if it appears in frontmatter.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
2026-06-20 11:54:31 +02:00
m038 13d6576a2c fix(story): smart date range formatting + blueprint end_date format fix
Blueprint: end_date format changed from 'Y-m-d H:i' to 'Y-m-d' — the
demo frontmatter stores dates without a time component so Admin was
failing to parse it and showing the field empty.

Template: three-case smart range formatting:
- Same month & year  → 01 – 03 Sep 2025
- Same year only     → 01 Jan – 03 Sep 2025
- Different years    → 01 Jan 2025 – 03 Feb 2026

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
2026-06-20 11:50:44 +02:00
m038 bc67a0ee88 fix(story): add end_date blueprint field; fix date range display
Blueprint: renamed 'Date' to 'Start Date', added optional 'End Date'
field (header.end_date) so it's editable in Admin.

Template: single date → 'd M Y'; range → 'd M Y – d M Y' (full year
on both sides — the old format silently dropped the start year).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
2026-06-20 11:45:38 +02:00
m038 cc341cc944 fix(story): nav title cross-fades scroll-driven as hero content exits viewport
Replaced IntersectionObserver (discrete threshold) with a scroll RAF loop
using getBoundingClientRect. Opacity is computed from the fraction of
.story-hero__content still visible above the viewport top — so the nav title
fades in gradually as the hero title slides off the top edge, reaching full
opacity only when the element is completely gone.

Removed CSS transition (no longer needed; per-frame JS update is smooth).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
2026-06-20 11:28:12 +02:00
m038 f4ee63282b fix(story): nav title hidden on load, DM Serif Display typography
Was visible on load because story-hero__content starts below the
viewport fold (bottom:18% of 140vh hero) — IO fired immediately
as 'not intersecting'. Fixed with hasBeenVisible flag: nav title
only appears after the element has entered then exited the viewport.

Typography changed from DM Sans/500 to DM Serif Display/400 at
--text-lg (1.375rem) with -0.01em tracking — same face as the
hero title, scaled down for the 60px nav bar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
2026-06-20 11:24:36 +02:00
m038 326f28e4ac feat(story): sticky nav title + floating back-to-top pill
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
2026-06-20 11:15:06 +02:00
m038 49c4ab0341 fix(story): smooth hero overlay fade-out and add scrolly caption background
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
2026-06-20 10:32:22 +02:00
m038 37c38e925a fix: add transport_mode to entry JSON serialisation in all three map templates; note bbox approach in isNearTrack 2026-06-20 00:54:04 +02:00
m038 3301f049cc feat: apply GPX connector algorithm to dailies feed mini-map 2026-06-20 00:47:39 +02:00
m038 b1665dad80 feat: use buildJourneySegments in trip.html.twig mini-map 2026-06-20 00:45:01 +02:00
m038 d9fd5eb74c feat: use buildJourneySegments in map.html.twig — suppress connectors covered by GPX 2026-06-20 00:42:34 +02:00
m038 3772a64a0e fix: story back button uses history.back(); add demo images; fix story dates for chronological interleaving 2026-06-20 00:05:53 +02:00
m038 14e386a122 fix: remove 1m per-step elevation threshold — Komoot data is pre-smoothed, threshold filtered nearly all gain/loss 2026-06-19 23:34:39 +02:00
m038 8152fe79b6 fix: compute GPX stats per-file to avoid spurious inter-track segments
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
2026-06-19 23:13:08 +02:00
m038 1a247e1889 fix: story template-story class, datetime attr, imageName escaping, raw content comments
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vgmzx8VTTTmCskSpQtsLTr
2026-06-19 23:12:47 +02:00
m038 103ceb62b9 fix: deterministic GPX ordering in parseGpxFiles (trip.html.twig) 2026-06-19 23:06:28 +02:00
m038 c123a035ce feat: expand trip inline stats to 6 stats + add cycling panel with GPX parsing
- Expanded stats block from 4 to 6 stats (days, entries, countries, cities, distance, temp range)
- Added date_end-aware days calculation (uses header.date_end when available)
- Added cities dedup logic (seen_city_lower) matching Task 1 pattern
- Added temperature range computation (temp_min / temp_max)
- Added has_gpx boolean flag
- Distance label is conditional: km cycled (GPX) vs km roamed (no GPX)
- Stats note text is conditional to match distance mode
- Cycling button added to filter bar (only rendered when has_gpx)
- Cycling panel (7 stat blocks) added after stats block (hidden by default, toggled independently)
- Replaced old haversine IIFE with unified haversineKm + parseGpxFiles + IIFE
- GPX Mode A: fetches GPX files, sums trackpoint distances, populates cycling panel
- GPX Mode B: haversine between entry GPS points (no GPX)
- Updated .trip-stats-grid from repeat(4) to repeat(3) columns
- Added .trip-cycling-block, .trip-cycling-header, .trip-cycling-icon, .trip-cycling-title, .trip-cycling-grid CSS

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WPJztrVGbwic2xTG7G9fjM
2026-06-19 23:01:42 +02:00
m038 dfd1c38396 feat: add stories listing page and all story/shortcode CSS 2026-06-19 22:59:17 +02:00
m038 48b877c439 fix: deterministic multi-GPX trackpoint ordering and catch-path completion
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
2026-06-19 22:56:38 +02:00
m038 0dc9095b4b feat: add story.html.twig with hero scroll effect and shortcode JS 2026-06-19 22:56:00 +02:00
m038 3b5dc18ec6 feat: expand stats page to 6 stats — cities, temp range, distance mode detection 2026-06-19 22:50:12 +02:00
m038 3ef8d48ee2 feat: add entry url to map_entries data and as data-url attribute on all markers 2026-06-19 22:18:04 +02:00
m038 997baf4cc3 fix: marker click scrolls to card on home/trip pages instead of navigating (no url field) 2026-06-19 22:14:58 +02:00
m038 044e74f5d3 feat: hover-only title tooltip on map markers; click navigates to entry 2026-06-19 22:05:52 +02:00
m038 f7df6ef37e fix: remove cooperativeGestures, increase fitBounds padding, add popups to embedded maps 2026-06-19 22:01:54 +02:00
m038 a363052f5f feat: migrate trip overview map to MapLibre GL (removes last Leaflet reference) 2026-06-19 21:57:12 +02:00
m038 b431cfc0ac feat: migrate mini-map and home map to MapLibre GL 2026-06-19 21:49:52 +02:00
m038 87a782ae12 feat: migrate full map page to MapLibre GL with animated journey line 2026-06-19 21:46:23 +02:00
m038 0d1688c6c4 Revert "revert: remove out-of-scope stats block (belongs in separate task)"
This reverts commit a9043f711e.
2026-06-19 21:40:09 +02:00
m038 a9043f711e revert: remove out-of-scope stats block (belongs in separate task) 2026-06-19 21:39:42 +02:00
m038 897da36a21 feat: add inline stats block with toggle to trip page
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.
2026-06-19 21:35:54 +02:00
m038 eb739d80ab feat: wire up feed filter — All content / Journal / Stories
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
2026-06-19 21:32:13 +02:00
m038 0478a18fa8 feat: add filter bar markup and pill button styles to trip page
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
2026-06-19 21:29:33 +02:00
m038 2508936928 feat: add data-type attributes to feed cards; restyle story card with full border 2026-06-19 21:26:50 +02:00
m038 69c9f4f939 feat: trip page matches home layout — sticky map + feed, GPX route, no sidebar
- 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
2026-06-19 20:42:41 +02:00
m038 010478b3fa fix: sort past trips descending by date (newest first)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RB86BaJBG3eGiMdfhmHRrQ
2026-06-19 17:32:47 +02:00
m038 49d10f4816 fix: home map visible on mobile, invalidateSize on both maps
- 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
2026-06-19 17:29:52 +02:00
m038 a9eda558c0 fix: nav slash, back button context, home page max-width
- 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
2026-06-19 17:01:45 +02:00
m038 16b44513f2 fix: stories escape link goes to trip page not archive 2026-06-19 15:51:51 +02:00
m038 ab8a5138dd feat: dailies merges stories, id attrs for map sync; stories escape link 2026-06-19 15:47:42 +02:00
m038 b66f1cdb2d feat: trip page — entry counts, merged feed, sticky sidebar index 2026-06-19 15:45:06 +02:00
m038 a78236bf3b feat: home page template — sticky map + merged feed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RB86BaJBG3eGiMdfhmHRrQ
2026-06-19 15:42:43 +02:00
m038 a9843a0a2d feat: past trips archive with trip cards and entry counts 2026-06-19 15:40:15 +02:00