diff --git a/docs/reference/design-system-light.md b/docs/reference/design-system-light.md index b6519d9..06f8d41 100644 --- a/docs/reference/design-system-light.md +++ b/docs/reference/design-system-light.md @@ -1,368 +1,34 @@ -# Into the East — Design Spec +# Design System — Light Mode Color Palette -**Date:** 2026-06-18 -**Status:** Approved for implementation +Light-mode counterpart to `design-system.md`. Only color tokens differ between themes — typography, spacing, radius, shadows, and layout are identical. --- -## 1. Direction +## Color palette -**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 | +| Token | Light | Dark | Usage | |---|---|---|---| -| 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) | +| `--color-paper` | `#F7F5F2` | `#1A1814` | Page background | +| `--color-canvas` | `#FFFFFF` | `#22201B` | Card surfaces, form backgrounds | +| `--color-ink` | `#17171A` | `#EDE8DF` | Primary text | +| `--color-ink-2` | `#4A4850` | `#B8B0A4` | Body text — muted | +| `--color-ink-muted` | `#9896A0` | `#90887E` | Labels, timestamps, captions | +| `--color-border` | `#E8E6E3` | `#2E2B25` | Standard dividers | +| `--color-border-soft` | `#F0EDEA` | `#252219` | Subtle dividers | +| `--color-accent` | `#1F6B5A` | `#2E9880` | Teal — brand color, links, CTAs | +| `--color-accent-hover` | `#185647` | `#287A68` | Hover/pressed teal | +| `--color-accent-light` | `#EBF5F2` | `#1A2E29` | Pale teal tint backgrounds | +| `--color-accent-on` | `#FFFFFF` | `#FFFFFF` | Text on accent surfaces | +| `--color-surface-raised` | ⚠️ not specified | `#2A2720` | Elevated surfaces: tooltips, hover | +| `--color-ink-inverse` | ⚠️ not specified | `#17171A` | Text on accent-coloured buttons | + +### Notes on accent values + +The dark accent is `#2E9880` — a lightened version of the original `#1F6B5A` to maintain contrast against near-black backgrounds. + +### Gaps to resolve + +Two tokens were added during dark-theme implementation without light counterparts: + +- **`--color-surface-raised`**: dark is `#2A2720` (slightly above canvas). Light equivalent would be a warm off-white slightly darker than `--color-canvas` (`#FFFFFF`). +- **`--color-ink-inverse`**: dark is `#17171A` (dark text on the bright `#2E9880` accent). Light equivalent would likely be `#FFFFFF` (white text on the dark `#1F6B5A` accent) — same as `--color-accent-on`.