From d7a772ae02a9ba45001fd6377f022187e611f15f Mon Sep 17 00:00:00 2001 From: Mischa Date: Sat, 27 Jun 2026 18:54:56 +0200 Subject: [PATCH] feat(header): mobile hamburger menu + alignment & typography pass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Header: offset the 4px green ::before bar so content centres in the visible dark area, not the geometric box (fixes wordmark/nav/icon sitting ~2px high — the root cause behind the whole alignment saga) - Mobile (≤768px): collapse nav into a slide-down hamburger panel (standalone js/nav.js); inline nav retained on desktop - Nav: use the display serif in sentence case so it shares the wordmark's anatomy and aligns naturally (no optical nudge needed) - Typography tokens: three-tier display tracking (--tracking-display, --tracking-display-sm), --tracking-caps, --color-error, paper-glass overlays, --text-story/--leading-story; applied across components - trip-dates: move inline styles to a class Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01BftDn9vu9SonFAY4vxu4uk --- themes/intotheeast/css/style.css | 174 ++++++++++++++---- themes/intotheeast/css/tokens.css | 30 ++- themes/intotheeast/js/nav.js | 37 ++++ .../templates/partials/base.html.twig | 8 +- themes/intotheeast/templates/trip.html.twig | 2 +- 5 files changed, 207 insertions(+), 44 deletions(-) create mode 100644 themes/intotheeast/js/nav.js diff --git a/themes/intotheeast/css/style.css b/themes/intotheeast/css/style.css index 500164c..71cbf7a 100644 --- a/themes/intotheeast/css/style.css +++ b/themes/intotheeast/css/style.css @@ -39,7 +39,10 @@ body::after { display: flex; align-items: center; justify-content: space-between; - padding: 0 var(--space-5); + box-sizing: border-box; + /* 4px top offsets the green ::before gradient (top 4px of the bar) so all + content centres in the VISIBLE dark area, not the geometric header box. */ + padding: 4px var(--space-5) 0; height: var(--site-header-height); background: var(--color-canvas); border-bottom: 1px solid var(--color-border); @@ -63,7 +66,7 @@ body::after { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 400; - letter-spacing: 0.06em; + letter-spacing: var(--tracking-display-sm); text-decoration: none; color: var(--color-ink); line-height: 1; @@ -76,9 +79,12 @@ body::after { } .site-nav a { - font-family: var(--font-ui); - font-size: var(--text-sm); - font-weight: 500; + /* Nav uses the display serif (not the UI sans) so it shares the wordmark's + anatomy: with one typeface, logo and nav centre identically — no optical + nudge needed. Sentence case keeps it quiet support beneath the wordmark. */ + font-family: var(--font-display); + font-size: var(--text-base); + font-weight: 400; color: var(--color-ink-2); text-decoration: none; padding: var(--space-2) var(--space-3); @@ -90,11 +96,69 @@ body::after { } .site-nav a:hover { color: var(--color-ink); background: var(--color-paper); } -.site-nav a[aria-current="page"] { color: var(--color-accent); font-weight: 600; } +.site-nav a[aria-current="page"] { color: var(--color-accent); } -@media (max-width: 380px) { - .site-title { font-size: var(--text-md); } - .site-nav a { padding: var(--space-2); font-size: 0.8rem; } +/* ── Hamburger toggle ────────────────────────────────────────────────────────── */ +.nav-toggle { + display: none; /* shown only on mobile, via the media query below */ + flex-direction: column; + justify-content: center; + gap: 5px; + width: 44px; + height: 44px; + padding: 11px 10px; + margin-right: -10px; /* cancel inner padding so the bars align to the bar edge */ + background: none; + border: 0; + cursor: pointer; + -webkit-tap-highlight-color: transparent; +} +.nav-toggle__bar { + display: block; + width: 100%; + height: 2px; + border-radius: 2px; + background: var(--color-ink-2); + transition: transform 0.25s ease, opacity 0.2s ease, background 0.15s; +} +.nav-toggle:hover .nav-toggle__bar { background: var(--color-ink); } +.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) { transform: translateY(7px) rotate(45deg); } +.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { opacity: 0; } +.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); } + +@media (max-width: 768px) { + .nav-toggle { display: flex; } + + /* Nav collapses into a slide-down panel beneath the header bar. */ + .site-nav { + position: absolute; + top: 100%; + left: 0; + right: 0; + flex-direction: column; + align-items: stretch; + gap: 0; + padding: var(--space-2) var(--space-5) var(--space-4); + background: var(--color-canvas); + border-bottom: 1px solid var(--color-border); + box-shadow: var(--shadow-lg); + transform: translateY(-8px); + opacity: 0; + visibility: hidden; + transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s; + } + .site-nav[data-open="true"] { + transform: translateY(0); + opacity: 1; + visibility: visible; + } + .site-nav a { + font-size: var(--text-lg); + padding: var(--space-3) 0; + min-height: 0; + border-radius: 0; + } + .site-nav a:hover { background: none; color: var(--color-ink); } } /* ── Feed ────────────────────────────────────────────────────────────────────── */ @@ -142,6 +206,7 @@ body::after { font-size: var(--text-xl); font-weight: 400; line-height: var(--leading-snug); + letter-spacing: var(--tracking-display); color: var(--color-ink); margin-bottom: var(--space-3); transition: color 0.15s; @@ -173,6 +238,7 @@ body::after { font-size: var(--text-xl); font-weight: 400; line-height: var(--leading-snug); + letter-spacing: var(--tracking-display); color: var(--color-ink); margin-bottom: var(--space-2); } @@ -479,6 +545,8 @@ body::after { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: 400; + line-height: var(--leading-tight); + letter-spacing: var(--tracking-display); margin-bottom: var(--space-8); color: var(--color-ink); } @@ -517,7 +585,7 @@ body::after { font-weight: 600; color: var(--color-ink-muted); text-transform: uppercase; - letter-spacing: 0.07em; + letter-spacing: var(--tracking-caps); } .stats-countries { @@ -534,7 +602,7 @@ body::after { color: var(--color-ink); text-transform: uppercase; font-size: var(--text-xs); - letter-spacing: 0.07em; + letter-spacing: var(--tracking-caps); } .stats-note { @@ -662,6 +730,8 @@ body::after { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 400; + line-height: var(--leading-snug); + letter-spacing: var(--tracking-display); margin-bottom: var(--space-6); color: var(--color-ink); } @@ -731,13 +801,13 @@ body::after { /* Inline field validation */ .post-form-wrap .field-invalid { - border-color: #c0392b !important; - outline-color: #c0392b !important; + border-color: var(--color-error) !important; + outline-color: var(--color-error) !important; } .post-form-wrap .field-error { display: block; - color: #c0392b; + color: var(--color-error); font-size: var(--text-sm); margin-top: var(--space-1); } @@ -775,7 +845,7 @@ body::after { } .form-status--ok { color: var(--color-accent); } -.form-status--err { color: #B44A2A; } +.form-status--err { color: var(--color-error); } /* ── Accessibility & motion ──────────────────────────────────────────────────── */ @@ -863,10 +933,18 @@ body::after { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: 400; + line-height: var(--leading-tight); + letter-spacing: var(--tracking-display); color: var(--color-ink); margin-bottom: var(--space-2); } +.trip-dates { + font-size: var(--text-sm); + color: var(--color-ink-muted); + margin: var(--space-1) 0 var(--space-2); +} + .home-trip-counts { font-size: var(--text-sm); color: var(--color-ink-muted); @@ -975,6 +1053,8 @@ body::after { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: 400; + line-height: var(--leading-tight); + letter-spacing: var(--tracking-display); color: var(--color-ink); margin-bottom: var(--space-8); } @@ -1028,6 +1108,8 @@ body::after { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 400; + line-height: var(--leading-snug); + letter-spacing: var(--tracking-display); color: var(--color-ink); margin-bottom: var(--space-2); } @@ -1069,7 +1151,7 @@ body::after { font-size: var(--text-xs); font-weight: 600; text-transform: uppercase; - letter-spacing: 0.08em; + letter-spacing: var(--tracking-caps); color: var(--color-ink-muted); margin-bottom: var(--space-3); } @@ -1119,7 +1201,7 @@ body::after { font-size: var(--text-xs); font-weight: 600; font-variant: small-caps; - letter-spacing: 0.08em; + letter-spacing: var(--tracking-caps); color: var(--color-accent); margin-bottom: var(--space-2); } @@ -1216,6 +1298,8 @@ body::after { .trip-cycling-title { font-family: var(--font-display); font-size: var(--text-lg); + line-height: var(--leading-snug); + letter-spacing: var(--tracking-display-sm); color: var(--color-ink); } @@ -1245,7 +1329,7 @@ body::after { font-size: var(--text-sm); font-weight: 500; color: rgba(255,255,255,0.85); - background: rgba(26,24,20,0.55); + background: var(--color-paper-glass-high); backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); border: 1px solid rgba(255,255,255,0.12); @@ -1254,7 +1338,7 @@ body::after { text-decoration: none; transition: background 0.2s; } -.story-escape:hover { background: rgba(26,24,20,0.8); } +.story-escape:hover { background: var(--color-paper-glass-hover); } /* Hero */ .story-hero { position: relative; } @@ -1303,7 +1387,7 @@ body::after { .story-hero__title { font-family: var(--font-display); font-size: clamp(2.2rem, 6vw, 4.5rem); - font-weight: 900; + font-weight: 400; line-height: 1.08; letter-spacing: -0.02em; margin-bottom: var(--space-3); @@ -1354,13 +1438,27 @@ body::after { } .story-body p { font-family: var(--font-ui); - font-size: 1.0625rem; - line-height: 1.85; + font-size: var(--text-story); + line-height: var(--leading-story); color: var(--color-ink-2); margin-bottom: var(--space-6); } -.story-body h2, .story-body h3 { +.story-body h2 { font-family: var(--font-display); + font-size: var(--text-xl); + font-weight: 400; + line-height: var(--leading-snug); + letter-spacing: var(--tracking-display); + color: var(--color-ink); + margin-top: var(--space-10); + margin-bottom: var(--space-4); +} +.story-body h3 { + font-family: var(--font-display); + font-size: var(--text-lg); + font-weight: 400; + line-height: var(--leading-snug); + letter-spacing: var(--tracking-display-sm); color: var(--color-ink); margin-top: var(--space-10); margin-bottom: var(--space-4); @@ -1404,7 +1502,7 @@ body::after { font-family: var(--font-ui); font-size: var(--text-sm); color: var(--color-ink-muted); - letter-spacing: 0.06em; + letter-spacing: var(--tracking-caps); text-transform: uppercase; } @@ -1421,7 +1519,7 @@ body::after { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 400; - letter-spacing: -0.01em; + letter-spacing: var(--tracking-display-sm); color: var(--color-ink); white-space: nowrap; max-width: 40%; @@ -1505,7 +1603,7 @@ body::after { align-items: center; gap: var(--space-2); padding: var(--space-10) var(--space-12); - background: rgba(26,24,20,0.25); + background: var(--color-paper-glass-mid); backdrop-filter: blur(18px) saturate(1.4); -webkit-backdrop-filter: blur(18px) saturate(1.4); border: 1px solid rgba(255,255,255,0.12); @@ -1533,8 +1631,9 @@ body::after { .chapter-break__title { font-family: var(--font-display); font-size: clamp(1.6rem, 4vw, 2.6rem); - font-weight: 700; + font-weight: 400; line-height: 1.15; + letter-spacing: var(--tracking-display); color: #fff; text-shadow: 0 2px 16px rgba(0,0,0,0.4); margin: 0; @@ -1623,8 +1722,8 @@ body::after { } .scrolly-step__inner p { font-family: var(--font-ui); - font-size: 1.05rem; - line-height: 1.8; + font-size: var(--text-story); + line-height: var(--leading-story); color: var(--color-ink-2); margin-bottom: var(--space-3); } @@ -1671,7 +1770,7 @@ body::after { padding: var(--space-10) var(--space-8); backdrop-filter: blur(14px) saturate(1.3); -webkit-backdrop-filter: blur(14px) saturate(1.3); - background: rgba(26,24,20,0.08); + background: var(--color-paper-glass-low); text-align: center; } .pull-quote__inner--no-image { @@ -1692,6 +1791,7 @@ body::after { font-family: var(--font-display); font-size: clamp(1.2rem, 3vw, 1.6rem); font-style: italic; + letter-spacing: var(--tracking-display-sm); color: #fff; line-height: 1.5; margin: var(--space-4) 0; @@ -1843,6 +1943,8 @@ body::after { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: 400; + line-height: var(--leading-tight); + letter-spacing: var(--tracking-display); color: var(--color-ink); margin-bottom: 0; } @@ -1875,7 +1977,7 @@ body::after { font-size: var(--text-xs); color: var(--color-ink-muted); text-transform: uppercase; - letter-spacing: 0.06em; + letter-spacing: var(--tracking-caps); margin-bottom: var(--space-1); } .story-card__location { @@ -1889,9 +1991,10 @@ body::after { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 400; + line-height: var(--leading-snug); + letter-spacing: var(--tracking-display-sm); color: var(--color-ink); margin-bottom: var(--space-3); - line-height: var(--leading-snug); } .story-card__cta { font-family: var(--font-ui); @@ -1916,6 +2019,8 @@ body::after { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: 400; + line-height: var(--leading-tight); + letter-spacing: var(--tracking-display); color: var(--color-ink); margin-bottom: var(--space-2); } @@ -1973,7 +2078,7 @@ body::after { font-size: var(--text-xs); font-weight: 600; font-variant: small-caps; - letter-spacing: 0.08em; + letter-spacing: var(--tracking-caps); color: var(--color-accent); } @@ -1985,9 +2090,10 @@ body::after { font-family: var(--font-display); font-size: var(--text-lg); font-weight: 400; + line-height: var(--leading-snug); + letter-spacing: var(--tracking-display-sm); color: var(--color-ink); text-decoration: none; - line-height: 1.3; } .home-highlight-title:hover { color: var(--color-accent); } diff --git a/themes/intotheeast/css/tokens.css b/themes/intotheeast/css/tokens.css index 2737267..8100b46 100644 --- a/themes/intotheeast/css/tokens.css +++ b/themes/intotheeast/css/tokens.css @@ -13,25 +13,39 @@ --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 */ + --color-error: #c0392b; /* validation errors, form error status */ + + /* ── Glass overlays (paper colour at opacity, for story components) ── */ + --color-paper-glass-low: color-mix(in srgb, var(--color-paper) 8%, transparent); + --color-paper-glass-mid: color-mix(in srgb, var(--color-paper) 25%, transparent); + --color-paper-glass-high: color-mix(in srgb, var(--color-paper) 55%, transparent); + --color-paper-glass-hover: color-mix(in srgb, var(--color-paper) 80%, transparent); /* ── Fonts ───────────────────────────────────────────────── */ --font-display: 'DM Serif Display', Georgia, serif; --font-ui: 'DM Sans', -apple-system, BlinkMacSystemFont, sans-serif; /* ── Type scale ──────────────────────────────────────────── */ - --text-xs: 0.75rem; - --text-sm: 0.875rem; - --text-base: 1rem; - --text-md: 1.125rem; - --text-lg: 1.375rem; - --text-xl: 1.75rem; - --text-2xl: 2.25rem; - --text-3xl: 3rem; + --text-xs: 0.75rem; + --text-sm: 0.875rem; + --text-base: 1rem; + --text-md: 1.125rem; + --text-lg: 1.375rem; + --text-xl: 1.75rem; + --text-2xl: 2.25rem; + --text-3xl: 3rem; + --text-story: 1.0625rem; /* long-form reading size: story body + scrolly steps */ /* ── Leading ─────────────────────────────────────────────── */ --leading-tight: 1.2; --leading-snug: 1.35; --leading-normal: 1.65; + --leading-story: 1.85; /* relaxed reading rhythm for story long-form */ + + /* ── Tracking ────────────────────────────────────────────── */ + --tracking-caps: 0.07em; /* uppercase UI labels: dates, badges, sidebar headings */ + --tracking-display: -0.015em; /* display headings: text-xl and text-2xl */ + --tracking-display-sm: -0.01em; /* display headings: text-lg and smaller; site logotype */ /* ── Spacing (4px grid) ──────────────────────────────────── */ --space-1: 0.25rem; diff --git a/themes/intotheeast/js/nav.js b/themes/intotheeast/js/nav.js new file mode 100644 index 0000000..84a19bf --- /dev/null +++ b/themes/intotheeast/js/nav.js @@ -0,0 +1,37 @@ +/* Mobile nav: hamburger toggle for the slide-down menu panel. + Standalone (not part of the esbuild bundle) — a small progressive + enhancement for the header. Loaded via base.html.twig. */ +(function () { + var toggle = document.querySelector('.nav-toggle'); + var nav = document.getElementById('site-nav'); + if (!toggle || !nav) return; + + function setOpen(open) { + toggle.setAttribute('aria-expanded', open ? 'true' : 'false'); + toggle.setAttribute('aria-label', open ? 'Close menu' : 'Open menu'); + nav.setAttribute('data-open', open ? 'true' : 'false'); + } + + toggle.addEventListener('click', function (e) { + e.stopPropagation(); + setOpen(toggle.getAttribute('aria-expanded') !== 'true'); + }); + + /* Tapping a link closes the panel before navigating. */ + nav.addEventListener('click', function (e) { + if (e.target.closest('a')) setOpen(false); + }); + + /* Close on outside tap or Escape. */ + document.addEventListener('click', function (e) { + if (!nav.contains(e.target) && !toggle.contains(e.target)) setOpen(false); + }); + document.addEventListener('keydown', function (e) { + if (e.key === 'Escape') setOpen(false); + }); + + /* Reset to closed if the viewport grows back to desktop. */ + window.addEventListener('resize', function () { + if (window.innerWidth > 768) setOpen(false); + }); +})(); diff --git a/themes/intotheeast/templates/partials/base.html.twig b/themes/intotheeast/templates/partials/base.html.twig index 3aceff4..1789947 100644 --- a/themes/intotheeast/templates/partials/base.html.twig +++ b/themes/intotheeast/templates/partials/base.html.twig @@ -8,6 +8,7 @@ {% do assets.addCss('theme://css/style.css') %} {% do assets.addCss('theme://css-compiled/main.css') %} {% do assets.addJs('theme://js/main.js', {group: 'bottom'}) %} + {% do assets.addJs('theme://js/nav.js', {group: 'bottom'}) %} {% block map_assets %}{% endblock %} {{ assets.css()|raw }} {{ assets.js()|raw }} @@ -17,7 +18,12 @@