docs: mark frontend polish plan as complete

This commit is contained in:
2026-06-25 00:05:27 +02:00
parent b2e9dcadb9
commit 41e303e6bc
@@ -0,0 +1,422 @@
# Frontend Polish Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [x]`) syntax for tracking.
**Status:** ✅ Complete — implemented 2026-06-24
**Spec:** `docs/working/specs/2026-06-24-frontend-polish-design.md`
**Goal:** Visual polish across the five primary page templates: pill grammar, stats field-notes style, header identity, emoji replacement, trip card cover images, story progress bar, and story opening transition.
**Architecture:** Tasks 12 are pure CSS (style.css only). Task 3 touches one partial (emoji). Task 4 adds a blueprint field and updates one template. Tasks 56 each add CSS + a small Twig block to story.html.twig.
**Already done (this session):**
- `entry.html.twig` unified with feed partial — hero removed, PhotoSwipe replaces broken lightbox
- Dead CSS from old entry layout stripped from `style.css`
---
## Global Constraints
- All changes in `user/` — commit with `git -C user`, not main-repo git
- All new CSS uses token variables only — no hardcoded hex values
- Changes must degrade gracefully when optional data (cover image, location) is absent
- `prefers-reduced-motion` must be respected for any animations in Tasks 56
- Clear Grav cache after each template change: `make remote-cache-clear` or via Admin
---
## Task 1: Pure CSS — Pill grammar + Stats style + Header identity
**Files:**
- Modify: `user/themes/intotheeast/css/style.css`
**Interfaces:**
- Produces: visual changes to trip filter buttons, stats blocks, and site header across all pages
- [x] **Step 1: Pill grammar — change filter/sort buttons to rounded-rect**
Find `.trip-filter-btn,` selector block:
```css
.trip-filter-btn,
.trip-stats-btn {
...
border-radius: var(--radius-full);
...
}
```
Change only `border-radius` to `var(--radius-sm)`. Leave all other properties unchanged.
- [x] **Step 2: Stats — remove box, add left rule**
Find `.stat-block` rule:
```css
.stat-block {
background: var(--color-canvas);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
padding: var(--space-6) var(--space-5);
text-align: center;
box-shadow: var(--shadow-sm);
}
```
Replace with:
```css
.stat-block {
border-left: 2px solid var(--color-accent);
padding: var(--space-2) 0 var(--space-2) var(--space-4);
text-align: left;
}
```
- [x] **Step 3: Stats — change number color from accent to ink**
Find `.stat-value` rule. It contains `color: var(--color-accent)`. Change to `color: var(--color-ink)`. Leave all other properties unchanged.
- [x] **Step 4: Header — widen site title tracking and size**
Find `.site-title` rule:
```css
.site-title {
font-family: var(--font-display);
font-size: var(--text-lg);
font-weight: 400;
letter-spacing: -0.01em;
...
}
```
Change:
- `font-size: var(--text-lg)``font-size: var(--text-xl)`
- `letter-spacing: -0.01em``letter-spacing: 0.06em`
- [x] **Step 5: Header — thicken and gradient the accent stripe**
Find `.site-header` rule. It contains `border-top: 3px solid var(--color-accent)`.
Change to:
```css
border-top: 4px solid transparent;
border-image: linear-gradient(90deg, var(--color-accent), var(--color-accent-hover)) 1;
```
- [x] **Step 6: Visual smoke check**
Open browser and verify:
- `/trips` — trip filter buttons are square-cornered (not pill-shaped)
- `/trips/<any-trip>` — stats panel shows left accent stripe, cream numbers, no box border
- Header — "into the east" is slightly larger with wider tracking; accent stripe has gradient
- [x] **Step 7: Commit**
```bash
git -C user add themes/intotheeast/css/style.css
git -C user commit -m "style: pill grammar, stats field-notes, header identity"
```
---
## Task 2: Replace emoji icons in journal entry partial
**Files:**
- Modify: `user/themes/intotheeast/templates/partials/entry-journal.html.twig`
**Interfaces:**
- Affects: every journal entry in the home feed, trip feed, and standalone entry page
- [x] **Step 1: Replace location emoji with SVG pin**
Find in the partial:
```twig
· 📍
```
Replace with:
```twig
· <svg width="11" height="13" viewBox="0 0 12 14" fill="currentColor" aria-hidden="true" style="flex-shrink:0;vertical-align:-1px"><path d="M6 0C3.24 0 1 2.24 1 5c0 3.75 5 9 5 9s5-5.25 5-9c0-2.76-2.24-5-5-5zm0 6.75A1.75 1.75 0 1 1 6 3.25a1.75 1.75 0 0 1 0 3.5z"/></svg>
```
- [x] **Step 2: Strip weather emoji prefix**
Find in the partial:
```twig
<span class="journal-post-weather">· {{ weather_icons[entry.header.weather_desc] ?? '' }} {{ entry.header.weather_desc }}</span>
```
Replace with:
```twig
<span class="journal-post-weather">· {{ entry.header.weather_desc }}</span>
```
The `weather_icons` map at the top of the partial can stay (removing it is optional cleanup); it will simply go unused.
- [x] **Step 3: Smoke check**
Open any trip page in browser. Confirm:
- Location shows small SVG pin instead of 📍
- Weather shows plain text (e.g. "· Sunny") with no emoji
- [x] **Step 4: Commit**
```bash
git -C user add themes/intotheeast/templates/partials/entry-journal.html.twig
git -C user commit -m "style: replace emoji icons with SVG pin and plain weather text"
```
---
## Task 3: Trip cards — cover image
**Files:**
- Modify: `user/themes/intotheeast/blueprints/trip.yaml`
- Modify: `user/themes/intotheeast/templates/trips.html.twig`
- Modify: `user/themes/intotheeast/css/style.css`
**Interfaces:**
- Produces: optional cover image banner on each trip card
- Consumes: `trip.header.cover_image` (new field) or first image from first published entry
- [x] **Step 1: Read the current trip blueprint**
```bash
cat user/themes/intotheeast/blueprints/trip.yaml
```
Locate the correct position to insert the new field (after `tagline` or near other media fields).
- [x] **Step 2: Add cover_image field to blueprint**
Insert in `trip.yaml` at an appropriate location:
```yaml
cover_image:
type: filepicker
label: Cover Image
preview_images: true
folder: '@self'
accept:
- image/*
```
- [x] **Step 3: Add cover image CSS to style.css**
In the `/* ── Past trips archive */` section, add after `.trip-card-counts`:
```css
.trip-card-cover {
aspect-ratio: 3 / 1;
overflow: hidden;
border-radius: var(--radius-md) var(--radius-md) 0 0;
background: var(--color-border);
margin: calc(-1 * var(--space-6)) calc(-1 * var(--space-6)) var(--space-5);
}
.trip-card-cover img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
transition: transform 0.45s ease;
}
.trip-card:hover .trip-card-cover img { transform: scale(1.04); }
```
- [x] **Step 4: Update trips.html.twig to render cover image**
Inside the `{% for trip in trips %}` loop, before the `.trip-card-title` div, add:
```twig
{# Cover image: explicit field first, then first entry's first image #}
{% 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 %}
<div class="trip-card-cover">
<img src="{{ cover.cropResize(720, 240).url }}" alt="{{ trip.title }}" loading="lazy">
</div>
{% endif %}
```
- [x] **Step 5: Smoke check**
Open `/trips` in browser. Confirm:
- Trips with media show a 3:1 cover photo banner
- Trips without media show text-only card (no broken image element)
- Hover scales the image slightly
- [x] **Step 6: Commit**
```bash
git -C user add themes/intotheeast/blueprints/trip.yaml themes/intotheeast/templates/trips.html.twig themes/intotheeast/css/style.css
git -C user commit -m "feat: trip cards show cover image with 3:1 crop and hover zoom"
```
---
## Task 4: Story opening transition
**Files:**
- Modify: `user/themes/intotheeast/templates/story.html.twig`
- Modify: `user/themes/intotheeast/css/style.css`
**Interfaces:**
- Consumes: `date_str` and `location` already computed at the top of `story.html.twig`
- Produces: a centered location/date block at the top of `.story-body` with fade-in animation
- [x] **Step 1: Add story-opener CSS to style.css**
In the `/* ── Story pages */` section, after `.story-body p` rules, add:
```css
.story-opener {
text-align: center;
padding-bottom: var(--space-12);
margin-bottom: var(--space-12);
border-bottom: 1px solid var(--color-border);
opacity: 0;
animation: storyReveal 0.9s cubic-bezier(.16,1,.3,1) 0.8s both;
}
.story-opener__text {
font-family: var(--font-ui);
font-size: var(--text-sm);
color: var(--color-ink-muted);
letter-spacing: 0.06em;
text-transform: uppercase;
}
@media (prefers-reduced-motion: reduce) {
.story-opener { opacity: 1; animation: none; }
}
```
- [x] **Step 2: Add opener block to story.html.twig**
Inside `.story-body`, immediately before `{{ page.content|raw }}`, add:
```twig
{% if location or date_str %}
<div class="story-opener">
<span class="story-opener__text">
{{- date_str -}}
{%- if location and date_str %} · {% endif -%}
{{- location -}}
</span>
</div>
{% endif %}
```
- [x] **Step 3: Smoke check**
Open any published story in browser. Confirm:
- A small uppercase line showing date and location appears below the hero spacer
- It is separated from the prose by a thin horizontal rule
- It fades in after the hero title animation completes
- On a story with no location set: only date appears (or nothing if both are absent)
- [x] **Step 4: Commit**
```bash
git -C user add themes/intotheeast/templates/story.html.twig themes/intotheeast/css/style.css
git -C user commit -m "feat: story opening transition with location and date eyebrow"
```
---
## Task 5: Reading progress bar on story pages
**Files:**
- Modify: `user/themes/intotheeast/templates/story.html.twig`
- Modify: `user/themes/intotheeast/css/style.css`
**Interfaces:**
- Produces: 2px teal bar fixed at bottom of site header, progress tied to `.story-body` scroll position
- No bar rendered at all if `prefers-reduced-motion` is set (JS skips creating it)
- [x] **Step 1: Add progress bar CSS to style.css**
In the `/* ── Story pages */` section, add:
```css
.story-progress {
position: fixed;
top: var(--site-header-height);
left: 0;
height: 2px;
width: 0%;
background: var(--color-accent);
z-index: 200;
pointer-events: none;
will-change: width;
}
```
- [x] **Step 2: Add progress bar element and JS to story.html.twig**
Immediately after `{% block content %}` (before the hero markup), add:
```twig
<div class="story-progress" id="story-progress"></div>
```
In the `<script>` block at the bottom (after the existing scroll/reveal scripts), add:
```javascript
/* ── Reading progress bar ────────────────────────────────── */
(function () {
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
var bar = document.getElementById('story-progress');
var body = document.querySelector('.story-body');
if (!bar || !body) return;
function update() {
var rect = body.getBoundingClientRect();
var total = body.offsetHeight - window.innerHeight;
var scrolled = -rect.top;
var pct = total > 0 ? Math.min(100, Math.max(0, (scrolled / total) * 100)) : 0;
bar.style.width = pct.toFixed(1) + '%';
}
window.addEventListener('scroll', update, { passive: true });
update();
})();
```
- [x] **Step 3: Smoke check**
Open any published story in browser. Confirm:
- A thin teal line appears at the top of the content area (below the sticky header) as you scroll into the story body
- Bar is at 0% when the hero is visible, fills to 100% as you reach the story footer
- Bar is invisible (absent) on a device with `prefers-reduced-motion`
- [x] **Step 4: Commit**
```bash
git -C user add themes/intotheeast/templates/story.html.twig themes/intotheeast/css/style.css
git -C user commit -m "feat: reading progress bar on story pages"
```
---
## Final Verification
After all tasks complete:
1. Visual check list (browser):
- `/trips` — cover images on trip cards, hover scales; text-only fallback if no media
- `/trips/<any-trip>` — filter buttons square-cornered; stats left-rule style with cream numbers
- `/trips/<any-trip>/dailies/<any-entry>` (standalone URL) — SVG location pin, plain weather text, photo strip + PhotoSwipe, no hero image
- `/trips/<any-trip>/<any-story>` — opener block visible below hero; progress bar fills on scroll; no emoji anywhere
- Any page header — "into the east" wider-tracked; accent stripe slightly thicker with gradient
2. Reduced-motion check: simulate `prefers-reduced-motion: reduce` in browser devtools and confirm no animations fire on story pages (opener snaps visible immediately, progress bar absent).
3. Empty-data check: visit a trip with no media attached and confirm `/trips` degrades to text-only card without errors.