diff --git a/themes/intotheeast/blueprints/trip.yaml b/themes/intotheeast/blueprints/trip.yaml index 3e697ef..6e22b60 100644 --- a/themes/intotheeast/blueprints/trip.yaml +++ b/themes/intotheeast/blueprints/trip.yaml @@ -38,10 +38,9 @@ form: help: 'Leave blank if trip is ongoing' header.cover_image: - type: text - label: 'Cover Image Filename' - placeholder: 'cover.jpg' - help: 'Used in the trips listing page' + type: pagemediaselect + label: 'Cover Image' + help: 'Pick from images uploaded to this trip page. Shown on the trips listing and the trip-page banner. Falls back to the first journal entry photo if left unset.' header.album_url: type: text diff --git a/themes/intotheeast/css/style.css b/themes/intotheeast/css/style.css index 71cbf7a..ac6ab6c 100644 --- a/themes/intotheeast/css/style.css +++ b/themes/intotheeast/css/style.css @@ -950,6 +950,66 @@ body::after { color: var(--color-ink-muted); } +/* ── Trip page header extras: one-liner, description, banner ──────────────────── */ + +.home-trip-tagline { + font-size: var(--text-md); + line-height: var(--leading-snug); + color: var(--color-ink-2); + margin: 0 0 var(--space-2); +} + +.trip-header-desc { + margin: var(--space-3) 0 var(--space-4); +} + +.trip-header-desc-body { + font-size: var(--text-sm); + line-height: var(--leading-normal); + color: var(--color-ink-2); +} + +.trip-header-desc-body > :first-child { margin-top: 0; } +.trip-header-desc-body > :last-child { margin-bottom: 0; } +.trip-header-desc-body p { margin: 0 0 var(--space-2); } + +/* Collapsed preview ≈3 lines. Uses max-height (not -webkit-line-clamp) so it + holds across the multiple

that markdown content renders. */ +.trip-header-desc[data-collapsed="true"] .trip-header-desc-body { + max-height: 4.8em; + overflow: hidden; +} + +.trip-header-desc-toggle { + display: inline-block; + margin-top: var(--space-1); + padding: 0; + background: none; + border: none; + font: inherit; + font-size: var(--text-sm); + color: var(--color-accent); + cursor: pointer; +} + +.trip-header-desc-toggle:hover { color: var(--color-accent-hover); } + +.trip-header-banner { + width: 100%; + height: 200px; + margin: var(--space-4) 0 0; + border-radius: var(--radius-md); + overflow: hidden; + background: var(--color-border); +} + +.trip-header-banner img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + /* ── Trip page filter bar ────────────────────────────────────────────────────── */ .feed-sort-bar { @@ -1045,6 +1105,7 @@ body::after { .home-map-col { position: static; height: 40vh; align-self: stretch; } .home-map { height: 40vh; } .home-feed-col { padding: var(--space-6) var(--space-5); } + .trip-header-banner { height: 130px; } } /* ── Past trips archive ──────────────────────────────────────────────────────── */ @@ -1114,6 +1175,13 @@ body::after { margin-bottom: var(--space-2); } +.trip-card-tagline { + font-size: var(--text-sm); + line-height: var(--leading-snug); + color: var(--color-ink-muted); + margin: 0 0 var(--space-3); +} + .trip-card-meta { display: flex; gap: var(--space-4); diff --git a/themes/intotheeast/templates/macros/cover.html.twig b/themes/intotheeast/templates/macros/cover.html.twig new file mode 100644 index 0000000..bd0ed64 --- /dev/null +++ b/themes/intotheeast/templates/macros/cover.html.twig @@ -0,0 +1,45 @@ +{# + Shared trip cover: one source of truth for cover resolution + retina + rendering, used by both the trip-list card (trips.html.twig) and the + trip-page banner strip (trip-feed-col.html.twig) so the two surfaces + cannot drift (KTD2). + + Resolution (R7 / R11): + 1. author-selected header.cover_image, when it resolves to page media; + 2. else the first published journal entry's first image; + 3. else nothing. + A set-but-missing cover_image (deleted/moved file) is `is not defined` in + page media, so it falls through to the auto-pick rather than rendering a + broken image (R11). + + Twig macros can only emit strings — they cannot return a Medium object — + so resolution and rendering live together in one macro: it emits the + wrapper + retina when a cover exists, and nothing at all when none + does (which gives R9/AE4 a clean text-only header for free). + + Retina (R6 / R14): two explicit cropResize derivatives (1x at w×h, 2x at + 2w×2h) as an explicit `srcset` with w-descriptors; `alt` is the trip title. +#} +{% macro render(trip_page, alt, w, h, wrapper_class, sizes) %} +{%- set cover = null -%} +{%- if trip_page.header.cover_image and trip_page.media[trip_page.header.cover_image] is defined -%} + {%- set cover = trip_page.media[trip_page.header.cover_image] -%} +{%- else -%} + {%- set dailies_page = grav.pages.find(trip_page.route ~ '/dailies') -%} + {%- if dailies_page -%} + {%- set first_entry = dailies_page.children.published()|first -%} + {%- if first_entry and first_entry.media.images|length > 0 -%} + {%- set cover = first_entry.media.images|first -%} + {%- endif -%} + {%- endif -%} +{%- endif -%} +{%- if cover -%} +

+ {{ alt }} +
+{%- endif -%} +{% endmacro %} diff --git a/themes/intotheeast/templates/partials/trip-feed-col.html.twig b/themes/intotheeast/templates/partials/trip-feed-col.html.twig index 8c024ef..a91cbf2 100644 --- a/themes/intotheeast/templates/partials/trip-feed-col.html.twig +++ b/themes/intotheeast/templates/partials/trip-feed-col.html.twig @@ -1,8 +1,16 @@ {% import 'macros/stats.html.twig' as stats_m %} {% import 'macros/cycling.html.twig' as cycling_m %} +{% import 'macros/cover.html.twig' as cover %} +{# trip_header_extras: gated one-liner + description + banner for the trip-page + caller only. Home's active-trip include omits it (`only`), so it defaults off + and that header renders exactly as before (KTD4 / R12). #} +{% set trip_header_extras = trip_header_extras|default(false) %}

{{ trip_page.title }}

+ {% if trip_header_extras and trip_page.header.tagline %} +

{{ trip_page.header.tagline }}

+ {% endif %} {% if trip_page.header.date_start %}

{{ trip_page.header.date_start|date('d M Y') }} @@ -13,6 +21,15 @@ {{ journal_count }} journal {{ journal_count == 1 ? 'entry' : 'entries' }} {% if story_count > 0 %} · {{ story_count }} {{ story_count == 1 ? 'story' : 'stories' }}{% endif %} + {% if trip_header_extras and trip_page.content|striptags|trim %} +

+
{{ trip_page.content|raw }}
+ +
+ {% endif %} + {% if trip_header_extras %} + {{ cover.render(trip_page, trip_page.title, 720, 220, 'trip-header-banner', '100vw') }} + {% endif %}
@@ -62,4 +79,27 @@ }); }); + {% if trip_header_extras %} + + {% endif %}
diff --git a/themes/intotheeast/templates/trip.html.twig b/themes/intotheeast/templates/trip.html.twig index 5d68118..0185e7c 100644 --- a/themes/intotheeast/templates/trip.html.twig +++ b/themes/intotheeast/templates/trip.html.twig @@ -78,7 +78,8 @@ has_gpx: has_gpx, gpx_urls: gpx_urls, gps_points: gps_points, - show_sort: true + show_sort: true, + trip_header_extras: true } only %}
diff --git a/themes/intotheeast/templates/trips.html.twig b/themes/intotheeast/templates/trips.html.twig index 5c77ed1..ca616ce 100644 --- a/themes/intotheeast/templates/trips.html.twig +++ b/themes/intotheeast/templates/trips.html.twig @@ -1,6 +1,7 @@ {% extends 'partials/base.html.twig' %} {% block content %} +{% import 'macros/cover.html.twig' as cover %}

Past Trips

{% set trips = page.children.published()|sort((a, b) => a.date < b.date ? 1 : -1) %} {% if trips|length == 0 %} @@ -13,21 +14,11 @@ {% set journal_count = dailies_page ? dailies_page.children.published()|length : 0 %} {% set story_count = stories_page ? stories_page.children.published()|length : 0 %} - {% set cover = null %} - {% if trip.header.cover_image and trip.media[trip.header.cover_image] is defined %} - {% set cover = trip.media[trip.header.cover_image] %} - {% elseif dailies_page %} - {% set first_entry = dailies_page.children.published()|first %} - {% if first_entry and first_entry.media.images|length > 0 %} - {% set cover = first_entry.media.images|first %} - {% endif %} - {% endif %} - {% if cover %} -
- {{ trip.title }} -
- {% endif %} + {{ cover.render(trip, trip.title, 720, 240, 'trip-card-cover', '(max-width: 700px) 100vw, 360px') }}
{{ trip.title }}
+ {% if trip.header.tagline %} +
{{ trip.header.tagline }}
+ {% endif %}
{% if trip.header.date_start %}