docs: update reference docs to match implementation (dark theme, MapLibre, /dailies)

This commit is contained in:
2026-06-21 14:34:45 +02:00
parent 4be7a52fd8
commit 11167e9a65
3 changed files with 390 additions and 25 deletions
+1 -1
View File
@@ -70,7 +70,7 @@ templates/
└─ gpx-manager.html.twig ← extends base; admin UI for GPX file management
```
Partials live in `templates/partials/`. Key partials: `entry-card.html.twig` (feed card), `map-init.html.twig` (shared MapLibre bootstrap).
Partials live in `templates/partials/`. Currently one partial: `base.html.twig` (the site shell extended by all page templates).
---
+368
View File
@@ -0,0 +1,368 @@
# Into the East — Design Spec
**Date:** 2026-06-18
**Status:** Approved for implementation
---
## 1. Direction
**The brief:** A personal travel journal, sole author, trip to East Asia. Three weeks to implement before departure. Audience is both friends/family and the occasional curious stranger.
**The position:** Neither Polarsteps nor FindPenguins. Both optimize for social sharing of travel data. This site optimizes for **the story** — and should feel like reading a well-edited travel journal, not using an app.
**What we steal from each:**
- Polarsteps: photography-first hierarchy, airy whitespace, map as the emotional spine of the trip
- FindPenguins: typography as brand identity, stats as trophy case, hierarchical trip → entry structure
**What we do better than both:**
- Web-native: fast, linkable, no install, works on any browser
- Single author = pure editorial voice, no social noise
- Full CSS control = real typographic identity, not generic app chrome
- Editorial feel: more travel magazine, less productivity dashboard
**Aesthetic direction:** Field notes. The kind of journal a thoughtful traveler would carry — clean, direct, lets the photography speak. Sophisticated without effort.
**The one aesthetic risk:** Full-bleed hero photography with a translucent date+location overlay at the bottom of each card. The photo IS the entry card — not a thumbnail beside text. This is the single element that distinguishes this design from both reference apps and from typical blog layouts.
---
## 2. Color System
### Palette
| Token | Hex | Usage |
|---|---|---|
| `--color-ink` | `#17171A` | Primary text (near-black with cool undertone, like ink) |
| `--color-ink-2` | `#4A4850` | Secondary text, body paragraphs |
| `--color-ink-muted` | `#9896A0` | Labels, timestamps, captions, placeholder text |
| `--color-paper` | `#F7F5F2` | Page background (warm paper white, not blue-white) |
| `--color-canvas` | `#FFFFFF` | Card backgrounds, modals, form surfaces |
| `--color-border` | `#E8E6E3` | Standard dividers, card borders |
| `--color-border-soft` | `#F0EDEA` | Subtle section dividers |
| `--color-accent` | `#1F6B5A` | Deep teal — brand color, links, CTAs, active states |
| `--color-accent-hover` | `#185647` | Darkened accent for hover/pressed states |
| `--color-accent-light` | `#EBF5F2` | Pale teal for highlight backgrounds |
| `--color-accent-on` | `#FFFFFF` | Text on accent-colored surfaces |
### Rationale for accent color
Deep teal `#1F6B5A` was chosen over:
- Blue (#0066cc current): too generic, too tech
- Orange/saffron: clichéd for "Asia" travel design
- Terracotta/cream: the most common default for lifestyle/travel blogs
Teal evokes bamboo, celadon porcelain, ancient jade, the color of temple gardens — all without being literal or kitsch. It works cleanly against both the warm paper background and white card surfaces.
---
## 3. Typography
### Fonts
| Role | Family | Fallback | Source |
|---|---|---|---|
| Display / Headings | DM Serif Display | Georgia, serif | Google Fonts |
| UI / Body / Labels | DM Sans | -apple-system, BlinkMacSystemFont, sans-serif | Google Fonts |
**Google Fonts URL:**
```
https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,400;0,9..40,500;0,9..40,600;1,9..40,400&family=DM+Serif+Display:ital@0;1&display=swap
```
**Why this pairing:**
DM Serif Display has a calligraphic quality — slightly editorial, authoritative but not stiff. Paired with DM Sans (its designed companion) the system is cohesive. DM Sans is neutral and highly legible at all sizes. Both are under-used relative to Inter/Lato/Playfair, so the combination has a distinctive voice without being trendy.
### Type Scale
| Token | Size | Line Height | Usage |
|---|---|---|---|
| `--text-xs` | 0.75rem (12px) | 1.5 | Badges, captions |
| `--text-sm` | 0.875rem (14px) | 1.5 | Meta, timestamps, labels |
| `--text-base` | 1rem (16px) | 1.65 | Body paragraphs |
| `--text-md` | 1.125rem (18px) | 1.55 | Lead text, intro paragraphs |
| `--text-lg` | 1.375rem (22px) | 1.35 | Subheadings, card titles (mobile) |
| `--text-xl` | 1.75rem (28px) | 1.25 | Entry card titles |
| `--text-2xl` | 2.25rem (36px) | 1.2 | Page headings, entry titles (desktop) |
| `--text-3xl` | 3rem (48px) | 1.1 | Hero entry title |
### Usage rules
- Entry titles: `--font-display`, `--text-xl` (mobile) / `--text-2xl` (desktop)
- Site title in header: `--font-display`, `--text-lg`
- All other UI text: `--font-ui`
- Body paragraphs: `--font-ui`, `--text-base`, `--leading-normal`
- Timestamps/badges: `--font-ui`, `--text-xs`, uppercase, `letter-spacing: 0.07em`
---
## 4. Spacing & Layout
### Spacing scale (4px base unit)
| Token | Value |
|---|---|
| `--space-1` | 0.25rem (4px) |
| `--space-2` | 0.5rem (8px) |
| `--space-3` | 0.75rem (12px) |
| `--space-4` | 1rem (16px) |
| `--space-5` | 1.25rem (20px) |
| `--space-6` | 1.5rem (24px) |
| `--space-8` | 2rem (32px) |
| `--space-10` | 2.5rem (40px) |
| `--space-12` | 3rem (48px) |
| `--space-16` | 4rem (64px) |
### Layout
- Content max-width: `720px` (comfortable reading at any font size)
- Page horizontal padding: `1.25rem` (mobile), `1.5rem` (desktop ≥520px)
- Header height: `60px` (fixed, for JS offset calculations)
- Map page: full viewport, no content max-width constraint
### Border radius
| Token | Value | Usage |
|---|---|---|
| `--radius-sm` | 4px | Photo corners, small chips |
| `--radius-md` | 8px | Cards, buttons, inputs |
| `--radius-lg` | 12px | Large cards, modals |
| `--radius-full` | 9999px | Pills, badges |
### Shadows
| Token | Value | Usage |
|---|---|---|
| `--shadow-sm` | `0 1px 3px rgba(0,0,0,0.08)` | Stat blocks, subtle elevation |
| `--shadow-md` | `0 4px 12px rgba(0,0,0,0.10)` | Cards on hover, dropdowns |
| `--shadow-lg` | `0 8px 24px rgba(0,0,0,0.14)` | Lightbox, modals |
---
## 5. Component Inventory
### 5.1 Site Header
```
[ into the east ] [ Journal Map Stats ]
← accent bar across top (3px) ───────────────────────────────
```
- Top border: `3px solid var(--color-accent)` — thin accent bar signals the brand color without decorating
- Site title: DM Serif Display, `--text-lg`, no decoration
- Nav links: DM Sans, `--text-sm`, weight 500, `--color-ink-2`
- Active nav link: `--color-accent`, weight 600
- Mobile: same layout, title slightly smaller, nav links compact
- Background: `--color-canvas` (white), bottom border `1px solid var(--color-border)`
### 5.2 Entry Feed Card — With Photo
```
┌─────────────────────────────────────┐
│ │
│ [photo] │ ← full-width, 16:9, rounded corners
│ │
│ 18 JUN · 📍 Kyoto, Japan │ ← overlaid at bottom, gradient mask
└─────────────────────────────────────┘
Arrived in Tokyo ← DM Serif Display, --text-xl
After 14 hours of flying I finally ← body excerpt, --color-ink-2
set foot on Japanese soil...
Read entry → ← --color-accent, --text-sm
```
- Photo: `aspect-ratio: 16/9`, `object-fit: cover`, `border-radius: var(--radius-md)`
- Photo has a `linear-gradient(to top, rgba(0,0,0,0.55), transparent)` overlay at the bottom 40%
- Date + location sit on top of gradient in white text (`rgba(255,255,255,0.92)`)
- On hover: photo scales to 1.03 (subtle zoom, 0.4s ease)
- Title below photo: DM Serif Display, hover turns `--color-accent`
- Card separation: `padding-bottom: var(--space-12)` + `border-bottom: 1px solid var(--color-border)`
### 5.3 Entry Feed Card — No Photo
When no photo is available, fall back to a text-only layout:
```
18 JUN 2026 · 📍 Kyoto, Japan ← meta row, --text-sm, --color-ink-muted
Arrived in Tokyo ← DM Serif Display, --text-xl
After 14 hours of flying...
Read entry →
```
- No photo container
- Meta (date + location) on one line above title, small + muted
### 5.4 Single Entry Page
```
Wednesday, 18 June 2026 ← --text-sm, --color-ink-muted, uppercase
📍 Kyoto, Japan · ⛅ Partly cloudy · 22°C
Arrived in Tokyo ← DM Serif Display, --text-2xl / --text-3xl
─────────────────────────────────────
Body text content... ← --font-ui, --text-base/md
[Photo gallery — 2 or 3 col grid]
← Back to journal
```
- The entry title uses `--font-display` at largest scale
- A thin `--color-border` rule separates the header from the body
- Body text is `--text-md` (18px) for comfortable long-form reading
- Full-bleed hero option: if a `hero_image` is set, it spans the full content width with a bottom margin
### 5.5 Post Form (Author View)
```
New Entry
Title * [________________________]
Date & Time [2026-06-18 14:30 ]
What happened [ ]
today? [ ]
[ ]
Photos [ + Add photos (max 4) ]
City [________________________]
Country [________________________]
[ 📍 Get Location ] [ 🌤 Get Weather ]
✓ Location captured: Kyoto, Japan ← status line
[ Post Entry ]
```
UX changes from current:
- Lat/lng inputs **hidden from the UI** (remain in the form as `display:none` for data capture, filled by JS)
- Location status shows captured city/country + coordinates in a single line (not separate status paragraphs)
- Photo upload area: larger touch target, visual indication of count
- "Post Entry" button: `--color-accent` background, full-width on mobile, `min-height: 52px`
- Form fields: `--radius-md` corners, `--color-border` border, focus ring in `--color-accent`
- Section spacing: generous vertical rhythm on mobile
### 5.6 Stats Page
```
┌────────────┐ ┌────────────┐
│ 42 │ │ 18 │
│ days on │ │ entries │
│ the road │ │ posted │
└────────────┘ └────────────┘
┌────────────┐ ┌────────────┐
│ 6 │ │ ~14,200 │
│ countries │ │ km │
│ visited │ │ traveled │
└────────────┘ └────────────┘
Countries visited
Japan · South Korea · Mongolia · Russia · Finland · Estonia
```
- Numbers: `--font-display`, `--text-3xl`, `--color-accent`
- Labels: `--font-ui`, `--text-xs`, uppercase, `--color-ink-muted`
- Cards: white, `--shadow-sm`, `--radius-md`, centered
### 5.7 Map Page
Minimal changes — the map itself is good. Style improvements:
- Leaflet popups: match the new design (DM Sans, `--radius-md`, `--shadow-md`)
- Markers: keep current circle style, update color to `--color-accent`
- Feed mini-map wrapper: match `--radius-md`, `--border`
---
## 6. UX Flows
### 6.1 Reader — First Visit
1. Land on `/tracker` (journal feed)
2. See mini-map above fold (if entries exist) — route tells the geographic story at a glance
3. First entry card: full-bleed hero photo with date/location overlay — immediate emotional pull
4. Scroll through chronological entries
5. Tap/click entry → entry detail page
6. Navigate back via "← Back to journal"
**Key principle:** The reader should understand the journey spatially (mini-map) and emotionally (hero photo) before reading a single word.
### 6.2 Reader — Navigation
- Journal: primary destination, the feed
- Map: geographic exploration mode
- Stats: quick numbers, satisfying progress indicator
- No account required, no social friction, no login prompt for readers
### 6.3 Author — Posting from Mobile
1. Navigate to `/post` (bookmark on home screen)
2. Already logged in (Grav session persists) — form loads directly
3. **Title**: tap → type (autofocused)
4. **Date & Time**: auto-filled to now, adjust if needed
5. **Content**: write what happened
6. **Photos**: tap "Add photos" → camera or gallery → select up to 4
7. **Location**: tap "📍 Get Location" → GPS fires → status shows "Kyoto, Japan · 34.985, 135.758" in one line
8. **Weather**: tap "🌤 Get Weather" (works only if location was captured) → status shows "Partly cloudy · 22°C"
9. **City/Country**: auto-populated from GPS is a nice-to-have for v2; in v1 type manually if needed
10. Tap "Post Entry" → success message → 2-second pause → redirect to /tracker (new entry visible at top)
**Key principles:**
- One-thumb operation for all critical actions on mobile
- Location/weather are conveniences, not blockers — can skip both
- Visual feedback is immediate (status line updates on GPS response)
- After submit: don't leave author on a success message page; redirect to see their new post
---
## 7. Mobile Specifics
### Touch targets
- All interactive elements: `min-height: 44px`, `min-width: 44px` (Apple HIG standard)
- Form buttons: `min-height: 52px` on the post form (primary CTA)
- Nav links: `padding: 0.5rem 0.75rem`
### Viewport concerns
- Map page: `height: calc(100vh - 60px)`, `touch-action: none` on map container — prevents scroll trap
- Photo lightbox: full viewport overlay, swipe-friendly (keyboard + click already implemented)
- Form on mobile: single-column, generous input padding `0.875rem 1rem`, `font-size: 1rem` (prevents iOS zoom on focus)
### Performance
- Google Fonts: loaded with `preconnect` hints
- Images: `loading="lazy"` on all non-above-fold images (already in place)
- Leaflet: loaded from CDN, only on pages that need it
- No new JS frameworks — vanilla JS throughout
---
## 8. Tech Stack Decision
**Keep Grav CMS.** With a 3-week timeline, replacing it would consume all available time on migration rather than design improvements.
| Layer | Decision | Rationale |
|---|---|---|
| Backend | Grav CMS (PHP, Twig) — unchanged | Works, flat-file, no DB |
| CSS | Vanilla CSS + custom properties (design tokens) | No build step, full control, ships as one file |
| JS | Vanilla JS — unchanged | Current JS is well-structured, scope doesn't justify a framework |
| Icons | Unicode + emoji (current) | No dependency, works everywhere |
| Fonts | Google Fonts via CDN | Two fonts, display-swap, negligible impact |
| Maps | Leaflet.js (current) | Already in use, no reason to change |
| Build | None — no build pipeline | Grav's asset pipeline handles minification if needed |
**No Alpine.js, no TypeScript, no Tailwind.** The site has clean vanilla JS and CSS today; a redesign is about visual quality, not framework migration. Introducing a build pipeline on a 3-week timeline is a distraction.
---
## 9. What Changes From Current Design
| Area | Current | New |
|---|---|---|
| Typography | System sans-serif only | DM Serif Display for headings + DM Sans for UI |
| Accent color | `#0066cc` (generic blue) | `#1F6B5A` (deep teal) |
| Background | `#ffffff` (pure white) | `#F7F5F2` (warm paper) |
| Entry cards | Thumbnail + text below | Full-bleed 16:9 photo with overlay |
| Header | No visual identity | Accent top-border, typographic title |
| Design tokens | Hardcoded values throughout | CSS custom properties throughout |
| Post form | Lat/lng visible inputs | Lat/lng hidden, single status line |
| Font loading | None | Google Fonts DM pairing |
| Hover states | Minimal | Photo zoom, title color change |
| Stat numbers | `#0066cc` | `--color-accent` (#1F6B5A) |
+21 -24
View File
@@ -1,7 +1,7 @@
# Into the East — Design Spec
**Date:** 2026-06-18
**Status:** Approved for implementation
**Status:** Implemented — dark theme (see `design-system-light.md` for the original light-mode palette)
---
@@ -29,30 +29,27 @@
## 2. Color System
### Palette
### Palette (dark theme — as implemented)
| Token | Hex | Usage |
|---|---|---|
| `--color-ink` | `#17171A` | Primary text (near-black with cool undertone, like ink) |
| `--color-ink-2` | `#4A4850` | Secondary text, body paragraphs |
| `--color-ink-muted` | `#9896A0` | Labels, timestamps, captions, placeholder text |
| `--color-paper` | `#F7F5F2` | Page background (warm paper white, not blue-white) |
| `--color-canvas` | `#FFFFFF` | Card backgrounds, modals, form surfaces |
| `--color-border` | `#E8E6E3` | Standard dividers, card borders |
| `--color-border-soft` | `#F0EDEA` | Subtle section dividers |
| `--color-accent` | `#1F6B5A` | Deep teal — brand color, links, CTAs, active states |
| `--color-accent-hover` | `#185647` | Darkened accent for hover/pressed states |
| `--color-accent-light` | `#EBF5F2` | Pale teal for highlight backgrounds |
| `--color-accent-on` | `#FFFFFF` | Text on accent-colored surfaces |
| `--color-paper` | `#1A1814` | Page background — warm near-black |
| `--color-canvas` | `#22201B` | Card surfaces, form backgrounds |
| `--color-ink` | `#EDE8DF` | Primary text — warm cream |
| `--color-ink-2` | `#B8B0A4` | Body text — muted warm |
| `--color-ink-muted` | `#90887E` | Labels, timestamps, captions |
| `--color-border` | `#2E2B25` | Standard dividers |
| `--color-border-soft` | `#252219` | Subtle dividers |
| `--color-accent` | `#2E9880` | Teal — lightened for dark-background contrast |
| `--color-accent-hover` | `#287A68` | Hover/pressed teal |
| `--color-accent-light` | `#1A2E29` | Pale teal tint backgrounds |
| `--color-accent-on` | `#FFFFFF` | Text on accent surfaces |
| `--color-surface-raised` | `#2A2720` | Elevated surfaces: tooltips, hover |
| `--color-ink-inverse` | `#17171A` | Text on accent-coloured buttons |
### Rationale for accent color
Deep teal `#1F6B5A` was chosen over:
- Blue (#0066cc current): too generic, too tech
- Orange/saffron: clichéd for "Asia" travel design
- Terracotta/cream: the most common default for lifestyle/travel blogs
Teal evokes bamboo, celadon porcelain, ancient jade, the color of temple gardens — all without being literal or kitsch. It works cleanly against both the warm paper background and white card surfaces.
Teal was chosen for its associations with bamboo, celadon porcelain, ancient jade, and temple gardens — without being literal or kitsch. On the dark palette, the original `#1F6B5A` was too low-contrast; it was lightened to `#2E9880` to maintain readable contrast against the warm near-black backgrounds. See `design-system-light.md` for the original light-palette values.
---
@@ -267,7 +264,7 @@ UX changes from current:
### 5.7 Map Page
Minimal changes — the map itself is good. Style improvements:
- Leaflet popups: match the new design (DM Sans, `--radius-md`, `--shadow-md`)
- MapLibre popups: match the new design (DM Sans, `--radius-md`, `--shadow-md`)
- Markers: keep current circle style, update color to `--color-accent`
- Feed mini-map wrapper: match `--radius-md`, `--border`
@@ -277,7 +274,7 @@ Minimal changes — the map itself is good. Style improvements:
### 6.1 Reader — First Visit
1. Land on `/tracker` (journal feed)
1. Land on `/dailies` (journal feed)
2. See mini-map above fold (if entries exist) — route tells the geographic story at a glance
3. First entry card: full-bleed hero photo with date/location overlay — immediate emotional pull
4. Scroll through chronological entries
@@ -304,7 +301,7 @@ Minimal changes — the map itself is good. Style improvements:
7. **Location**: tap "📍 Get Location" → GPS fires → status shows "Kyoto, Japan · 34.985, 135.758" in one line
8. **Weather**: tap "🌤 Get Weather" (works only if location was captured) → status shows "Partly cloudy · 22°C"
9. **City/Country**: auto-populated from GPS is a nice-to-have for v2; in v1 type manually if needed
10. Tap "Post Entry" → success message → 2-second pause → redirect to /tracker (new entry visible at top)
10. Tap "Post Entry" → success message → 2-second pause → redirect to /dailies (new entry visible at top)
**Key principles:**
- One-thumb operation for all critical actions on mobile
@@ -329,7 +326,7 @@ Minimal changes — the map itself is good. Style improvements:
### Performance
- Google Fonts: loaded with `preconnect` hints
- Images: `loading="lazy"` on all non-above-fold images (already in place)
- Leaflet: loaded from CDN, only on pages that need it
- MapLibre: loaded from CDN, only on pages that need it
- No new JS frameworks — vanilla JS throughout
---
@@ -345,7 +342,7 @@ Minimal changes — the map itself is good. Style improvements:
| JS | Vanilla JS — unchanged | Current JS is well-structured, scope doesn't justify a framework |
| Icons | Unicode + emoji (current) | No dependency, works everywhere |
| Fonts | Google Fonts via CDN | Two fonts, display-swap, negligible impact |
| Maps | Leaflet.js (current) | Already in use, no reason to change |
| Maps | MapLibre GL JS | Replaced Leaflet; all 3 map templates use it |
| Build | None — no build pipeline | Grav's asset pipeline handles minification if needed |
**No Alpine.js, no TypeScript, no Tailwind.** The site has clean vanilla JS and CSS today; a redesign is about visual quality, not framework migration. Introducing a build pipeline on a 3-week timeline is a distraction.