Skip to content

Latest commit

 

History

History
687 lines (640 loc) · 23.8 KB

File metadata and controls

687 lines (640 loc) · 23.8 KB
name Alpine Editorial
description An editorial, Munich-themed product surface for a small-team step tracker. Calm Bavarian-blue brand voice, generous whitespace, hairline rules instead of heavy shadows, and two carefully-rationed warm/cool accents (Alpenglow + Meadow) that signal completion and progress. Light by default, full dark theme available.
colors
brand ink surface hero accent semantic medal dark
bayern bayern-deep bayern-soft
#1761A0
#114F84
#E8F0F8
ink muted hairline
#0B1620
#6B7785
#E5E9EE
canvas raised hover translucent translucent-soft
#FFFFFF
#FFFFFF
#F5F5F4
rgba(255, 255, 255, 0.9)
rgba(255, 255, 255, 0.7)
stop-1 stop-2 stop-3 glow
#F4F8FC
#FBFCFD
#FFFFFF
rgba(224, 138, 74, 0.10)
alpenglow alpenglow-soft meadow meadow-soft
#E08A4A
#FDEEDE
#6B9E78
#E7F1E9
success warn bar-rest
#2E7D5A
#C97A1A
#9FB6CC
gold gold-soft silver silver-soft bronze bronze-soft
#C8A548
#F7EECF
#8A96A3
#ECF0F4
#A87148
#F3E3D4
bayern bayern-deep bayern-soft ink muted hairline canvas raised hover hero-stop-1 hero-stop-2 hero-stop-3 hero-glow success warn alpenglow meadow gold silver bronze
#5BA3DB
#3E86BD
#14304A
#F1F5FA
#8FA1B5
#1F3142
#08111A
#11202D
#18293A
#0E1A26
#0B1620
#08111A
rgba(240, 165, 114, 0.07)
#58C29A
#E0A55C
#F0A572
#8CC09A
#E0C478
#B1BCC8
#D09269
typography
font-family weights display-xl display-lg display-md display-sm headline-md numeric-xl title body-lg prose body ui caption micro eyebrow eyebrow-tight
sans mono
Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, sans-serif
ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace
regular medium semibold
400
500
600
fontFamily fontSize fontWeight lineHeight letterSpacing usage
Inter
56px
600
1.0
-0.02em
Top Stomp aggregate counter
fontFamily fontSize fontWeight lineHeight letterSpacing usage
Inter
44px
600
1.05
-0.02em
Hero greeting (sm and up)
fontFamily fontSize fontWeight lineHeight letterSpacing usage
Inter
40px
600
1.05
-0.015em
Page H1 (sm and up)
fontFamily fontSize fontWeight lineHeight letterSpacing usage
Inter
36px
600
1.05
-0.015em
Hero greeting (mobile)
fontFamily fontSize fontWeight lineHeight letterSpacing usage
Inter
32px
600
1.05
-0.015em
Page H1 (mobile)
fontFamily fontSize fontWeight lineHeight letterSpacing fontVariantNumeric usage
Inter
28px
500
1.1
-0.01em
tabular-nums
Quick-entry input field
fontFamily fontSize fontWeight lineHeight letterSpacing usage
Inter
22px
500
1.2
-0.01em
Section H2 in editorial layouts
fontFamily fontSize fontWeight lineHeight usage
Inter
18px
500
1.4
Profile form inputs
fontFamily fontSize fontWeight lineHeight usage
Inter
14.5px
400
1.65
About-page long-form copy
fontFamily fontSize fontWeight lineHeight usage
Inter
15px
400
1.5
Subtitles and supporting paragraphs
fontFamily fontSize fontWeight lineHeight letterSpacing usage
Inter
13px
500
1.4
-0.005em
Nav labels, table cells, primary buttons
fontFamily fontSize fontWeight lineHeight usage
Inter
12.5px
500
1.4
Pills, chips, secondary chrome
fontFamily fontSize fontWeight lineHeight usage
Inter
12px
500
1.4
Footer text, fine print
fontFamily fontSize fontWeight lineHeight letterSpacing textTransform usage
Inter
12px
500
1.4
0.18em
uppercase
Section eyebrow above every H1/H2
fontFamily fontSize fontWeight lineHeight letterSpacing textTransform usage
Inter
11px
500
1.3
0.16em
uppercase
Form-field labels, micro-eyebrows
spacing
unit scale layout grid
4px
0.5 1 1.5 2 2.5 3 4 5 6 8 10 12 16
2px
4px
6px
8px
10px
12px
16px
20px
24px
32px
40px
48px
64px
container-max container-padding-mobile container-padding-desktop section-py-mobile section-py-desktop column-gap-mobile column-gap-desktop
1200px
24px
40px
48px
56px
24px
48px
columns gutter-mobile gutter-desktop
12
24px
40px
rounded
none xs sm md lg pill brand-tile glyph-tile
0px
4px
6px
8px
12px
9999px
8px
8px
elevation
none hairline brand-tile card modal
none
inset 0 0 0 1px var(--color-hairline)
0 1px 0 rgba(255,255,255,0.18) inset, 0 1px 2px rgba(17,79,132,0.35)
0 1px 0 rgba(11,22,32,0.04)
0 24px 48px -12px rgba(11,22,32,0.18), 0 8px 16px -8px rgba(11,22,32,0.10)
borders
hairline hairline-bottom brand-ring focus-ring
1px solid var(--color-hairline)
border-bottom: 1px solid var(--color-hairline)
2px solid var(--color-bayern)
width color offset style
2px
var(--color-bayern)
0px
solid
motion
durations easings transitions hover reduced-motion
snap base soft
150ms
200ms
250ms
standard out in-out
cubic-bezier(0.4, 0, 0.2, 1)
cubic-bezier(0, 0, 0.2, 1)
cubic-bezier(0.4, 0, 0.2, 1)
color surface theme glyph-lift
color 200ms ease
background-color 150ms ease
background-color 200ms ease, color 200ms ease
transform 200ms cubic-bezier(0, 0, 0.2, 1)
glyph-translate-y
-1px
Honoured: animations and transitions collapse to 0.01ms when prefers-reduced-motion: reduce.
breakpoints
sm md lg xl
640px
768px
1024px
1280px
icons
family weight sizes
lucide-react
1.5px stroke (1.75px on accented chips and section eyebrows)
xs sm md lg
12px
14px
16px
20px
components
top-nav brand-tile pill-meadow pill-alpenglow pill-bayern pill-status hero section card-quiet button-primary button-secondary button-ghost input-text input-numeric modal-sheet bar-progress ring-progress leaderboard-row podium-tile footer
backgroundColor backdropFilter borderBottom height position safeArea
{colors.surface.translucent}
blur(8px)
{borders.hairline}
56px
sticky top-0 z-20
padding-left/right via env(safe-area-inset-*)
width height rounded background shadow glyph hoverTransform motionSafe
28px
28px
{rounded.md}
linear-gradient(160deg, #1F75B8 0%, #114F84 100%)
{elevation.brand-tile}
Inline Alpine ridge SVG (white snow + Alpenglow tint)
translateY(-1px)
true
height paddingX rounded backgroundColor textColor typography iconSize usage
28px
12px
{rounded.pill}
{colors.accent.meadow-soft}
{colors.accent.meadow}
{typography.caption}
{icons.sizes.sm}
Date / event chips. 'Progress' semantics.
height paddingX rounded backgroundColor textColor typography iconSize usage
28px
12px
{rounded.pill}
{colors.accent.alpenglow-soft}
{colors.accent.alpenglow}
{typography.caption}
{icons.sizes.sm}
Place / completion chips. 'Celebration' semantics.
height paddingX rounded backgroundColor textColor typography usage
28px
12px
{rounded.pill}
{colors.brand.bayern-soft}
{colors.brand.bayern}
{typography.caption}
Inline brand tags, code-style highlights.
height paddingX rounded border backgroundColor textColor secondaryTextColor iconSize iconStrokeWidth usage
36px
12px
{rounded.pill}
{borders.hairline}
{colors.surface.translucent-soft}
{colors.ink.ink}
{colors.ink.muted}
{icons.sizes.md}
1.5px
Hero weather chip and Profile cloud-sync indicator.
background paddingTop paddingBottom layout
base glow decoration
linear-gradient(180deg, {colors.hero.stop-1} 0%, {colors.hero.stop-2} 70%, {colors.hero.stop-3} 100%)
radial-gradient(60rem 28rem at 88% -10%, {colors.hero.glow} 0%, transparent 65%)
Mountain silhouette SVG, fixed to bottom edge, hairline-light
mobile desktop
48px
64px
mobile desktop
80px
96px
Two-column flex; greeting + date eyebrow on the left, status pills on the right; stacks below sm.
paddingY borderBottom grid eyebrow contentVisibility
mobile desktop
48px
56px
{borders.hairline}
12-col with col-span 12 / md:4 (label) + col-span 12 / md:8 (body)
{typography.eyebrow}
auto on the About long-read sections (contain-intrinsic-size: 1px 600px)
backgroundColor border rounded padding shadow
{colors.surface.raised}
{borders.hairline}
{rounded.md}
20px
{elevation.card}
backgroundColor textColor typography rounded height paddingX focusRing touchAction
{colors.brand.bayern}
#FFFFFF
{typography.ui}
{rounded.md}
44px
20px
{borders.focus-ring}
manipulation
backgroundColor textColor border typography rounded height paddingX hoverBackground
transparent
{colors.ink.ink}
{borders.hairline}
{typography.ui}
{rounded.md}
44px
20px
{colors.surface.hover}
backgroundColor textColor typography rounded height paddingX hoverBackground
transparent
{colors.ink.muted}
{typography.ui}
{rounded.md}
44px
12px
{colors.surface.hover}
backgroundColor textColor typography borderBottom borderBottomFocus height minFontSize
transparent
{colors.ink.ink}
{typography.body-lg}
1px solid {colors.ink.hairline}
2px solid {colors.brand.bayern}
48px
16px (anti-iOS-zoom guarantee)
backgroundColor textColor typography fontVariantNumeric borderBottom inputMode placeholder
transparent
{colors.ink.ink}
{typography.numeric-xl}
tabular-nums
1px solid {colors.ink.hairline}
numeric
0
desktop mobile backdropColor
maxWidth rounded shadow anchor
480px
{rounded.lg}
{elevation.modal}
viewport center
anchor rounded maxHeight overscrollBehavior
viewport bottom (sheet)
16px 16px 0 0
92vh
contain
rgba(11, 22, 32, 0.55)
trackColor fillColor height rounded
{colors.semantic.bar-rest}
{colors.brand.bayern}
6px
{rounded.pill}
trackColor fillColor fillCompleteColor strokeWidth capStyle
{colors.ink.hairline}
{colors.brand.bayern}
{colors.accent.meadow}
8px
round
paddingY borderBottom rankColor rankColorTop3 nameTypography stepsTypography youHighlightBackground youHighlightTextColor
14px
{borders.hairline}
{colors.ink.muted}
{colors.medal.gold | silver | bronze}
{typography.ui}
{typography.ui} with tabular-nums
{colors.brand.bayern-soft}
{colors.brand.bayern}
rounded paddingX paddingY backgroundColors labelColors
{rounded.md}
16px
12px
{colors.medal.[gold|silver|bronze]-soft}
{colors.medal.[gold|silver|bronze]}
paddingY borderTop typography textColor bullets safeArea
40px
{borders.hairline}
{typography.micro}
{colors.ink.muted}
1 2
{colors.accent.meadow}
{colors.accent.alpenglow}
padding-bottom via env(safe-area-inset-bottom)
accessibility
contrast focus motion touch-target ios
All ink-on-surface and brand-on-soft pairings clear AA at body sizes; eyebrow + caption sizes meet AA Large.
Keyboard focus uses a 2px Bayern ring (focus-visible only); tap-highlight is suppressed and replaced by the same ring.
All transforms and transitions collapse to 0.01ms under prefers-reduced-motion: reduce.
Interactive elements minimum 44x44 (top-nav buttons h-11; primary buttons h-11).
viewport-fit=cover; safe-area insets on body; input font-size floor 16px to prevent focus-zoom.

Brand & voice

This is the visual identity of a small, internal step-tracker built for a team offsite in Munich. The brief is "Bavarian alpine, but editorial" — calm, confident, sparing, and grown-up. Nothing here shouts. Color is rationed; the page does most of its work with whitespace, hairlines, and restraint, letting two warm/cool accents and a single brand blue carry the personality.

The product feels like a well-made print magazine that happens to live in a browser: a generous hero spread, a 12-column editorial body, and quiet section breaks instead of cards-everywhere. The reader's eye should always know where to land first.

Color

The system has one primary brand colour and four supporting palettes, each with a deliberate role. Saturation is held back across the board.

Bayern Blue (#1761A0) is the brand. It carries every primary action, every progress fill, every link, and the brand mark itself. Its deep variant (#114F84) is reserved for gradient endpoints on the brand mark; the soft variant (#E8F0F8) backs inline tags and code-style chips. In dark mode it shifts up to #5BA3DB so the same semantic role still has the contrast it needs.

Ink and hairlines are the page's neutrals. Ink (#0B1620) is a near-black with a faint blue cast — never pure #000. Muted (#6B7785) handles secondary text, eyebrows, and meta. Hairlines (#E5E9EE) replace shadows almost everywhere; a single 1px line is the dominant divider in the system. In dark mode the hairline is #1F3142 and the canvas is a deep navy (#08111A) — the alpine twilight, not pure black.

Two accents are rationed for meaning, not decoration:

  • Alpenglow (#E08A4A) — warm sunrise on peaks. Reserved for celebration / completion / place semantics: a podium-tile chip, the "Microsoft München" location pill, the radial glow that warms the hero's top-right corner.
  • Meadow (#6B9E78) — cool alpine green. Reserved for progress / time / calm semantics: the date chip, the success state, the first decorative dot in the footer rule.

The two are intentionally complementary and intentionally never appear together at full saturation in the same component — they trade off across page regions to give the eye somewhere to travel.

Medal hues (gold / silver / bronze) appear only on the top three leaderboard rows and the Top Stomp podium tiles. They are desaturated (gold #C8A548, not #FFD700) so they read as editorial trophy marks rather than novelty stickers.

Surface white is true white (#FFFFFF) in light mode. Cards and modals use the same surface colour as the canvas — depth is hairlines, not shadow. The only systemic use of translucency is the sticky top-nav, which sits over the hero glow at 90% opacity with an 8px backdrop blur so the gradient bleeds through gently when you scroll.

Typography

Inter, three weights only: 400 / 500 / 600. There is no 700 — the type system tops out at semibold and uses size, leading, and tracking to do the rest. This keeps the page feeling considered rather than loud.

The hierarchy is deliberately wide so editorial pages have a clear spine:

  • Display sizes (36 / 40 / 44 / 56 px) are tight: line-height 1.0 – 1.05, letter-spacing -0.015 to -0.02 em, semibold. They're used sparingly — one display size per screen.
  • Numeric display uses font-variant-numeric: tabular-nums so step counts don't shimmer as digits change.
  • Body prose is set at 14.5 px / 1.65 — a comfortable reading measure for the long-form About page; subtitles step up to 15 px with shorter line-height because they're rarely more than two lines.
  • Eyebrows are the system's most recognizable type marker: uppercase, 12 px, weight 500, letter-spacing 0.18em, muted ink. Every section has one, and it's always 12 px above the H1/H2 it introduces — that vertical rhythm is part of the brand.
  • UI type is 13 px / weight 500 with a faint -0.005em tracking; used for nav labels, primary buttons, and table cells.

Inputs default to a 16 px floor regardless of intent, to prevent iOS Safari from auto-zooming on focus.

Layout & rhythm

Every page sits in a 1200 px max-width container with 24 px gutters on mobile and 40 px on desktop. Within the container, content is laid out on a 12-column grid. Editorial sections (About, Profile, the hero) consistently use a 4 + 8 split: a label/eyebrow column on the left, a content column on the right — the same shape as a print sidebar.

Vertical rhythm is governed by section padding (48 px mobile, 56 px desktop) and a single hairline between sections. There are no card walls between sections; the page reads top-to-bottom like a long column of magazine spreads. The result is that long pages feel unhurried and short pages feel generous.

The hero is the one place where the page breaks discipline — it's allowed to be quietly cinematic. A three-stop vertical gradient (near-white → white) provides a soft canvas; on top, a large radial Alpenglow glow anchored to the top-right tints the corner without ever lighting up the type behind it. A subtle mountain-silhouette SVG sits flush to the bottom edge as a horizon line. The whole thing is a layered watercolour, never a hero "image".

Shape

Corners are restrained. The system's vocabulary is:

  • rounded-md (8 px) — the default for cards, buttons, and the brand tile. The "house" radius.
  • rounded-pill (full) — chips, status indicators, progress bars. Pills always read as "metadata" — never primary actions.
  • rounded-lg (12 px) — modals and the onboarding sheet only.
  • No rounded-xl or larger. Soft, but not toy-like.

The brand mark itself follows the same vocabulary: a 28×28 rounded-md tile with a Bayern-blue gradient and an inline white-snow Alpine ridge. The same shape language repeats in the favicon, the OG image, and the maskable PWA icon, so the system feels coherent across operating-system surfaces.

Elevation & depth

Depth in this system is built from hairlines, not shadow. The hierarchy is:

  1. Canvas — the page itself, plain surface color.
  2. Hairline-bounded surface — sections, leaderboard rows, cards. No background change, just a 1 px hairline rule.
  3. Soft-tinted surface — pills and chips, with *-soft color tokens (~10–12% saturation tints of the parent accent).
  4. Inset-glow surface — the brand tile only. A 1 px inner highlight at the top edge plus a small Bayern-deep drop shadow gives it the look of an enamel pin.
  5. Modal / sheet — the only place the system uses a real outer shadow. A two-stop shadow (0 24px 48px / 0 8px 16px) on a 12 px-radius surface, with a rgba(11,22,32,0.55) scrim behind.

That's the whole stack. Nothing else casts a shadow.

Motion

Motion is purposeful and short. The system uses three durations (150 / 200 / 250 ms) and a single easing family (cubic-bezier(0.4, 0, 0.2, 1) for both directions, with the "out" curve (0, 0, 0.2, 1) for entrances).

The few places motion appears:

  • Theme toggle — body color and background cross-fade over 200 ms.
  • Hover on the brand tile — translates up 1 px over 200 ms with the "out" curve. A small physical lift, not a bounce.
  • Brand glyph pan — on hover/focus, the snowy ridge inside the brand tile pans horizontally on a seamless 6 s linear loop (two ridge copies tiled at 28 px so it never seams). A second motion axis on the same hit-target as the lift, separating "you can click this" from "this is decorative".
  • Hero parallax — two ridge layers in the mountain silhouette ease in opposing directions (back ~+18 px / front ~−10 px) as the pointer moves across the hero. On touch (no fine pointer) the same layers drift continuously on a slow ~14 s sine wave. Transform-only, written via CSS custom properties so React doesn't re-render.
  • Hover surfaces — buttons, list rows, and ghost actions tint to surface-hover over 150 ms. Color only, no transform.
  • Modal entrance — the desktop dialog fades in; the mobile bottom sheet slides up from the edge. (Both via Tailwind defaults inside the system.)

Everything else is static. The whole site collapses motion to 0.01 ms under prefers-reduced-motion: reduce.

Iconography

Lucide line icons throughout, drawn at 1.75 px stroke (slightly heavier than the previous 1.5 to read crisp at 16 px on retina). Icons appear at four sizes — 12 / 14 / 16 / 20 px. They inherit color from their parent text or pill in most places, with one deliberate exception: the four primary tab icons in the top nav each carry a brand-family tint to give the chrome quick visual landmarks — Dashboard = Bayern blue, Leaderboard = Gold, Profile = Meadow green, About = Alpenglow. The active underline beneath each tab mirrors that same colour. The colour is paired with the label (visible from sm up) so it's never the only signal.

The brand glyph (top-nav and favicon) is the system's only custom-drawn mark: a three-peak Alpine ridge in white snow with a single Alpenglow-tinted face on the tallest peak. It's the visual shorthand for the whole identity.

Components in summary

The vocabulary is small on purpose:

  • Top nav — sticky, translucent, hairline-bottom; brand tile + short label; 4 tab icons; theme toggle.
  • Hero — once per page that has it, layered watercolour gradient with mountain silhouette and rationed status pills.
  • Section — eyebrow + H1/H2 in the left column, body in the right column, hairline at the bottom. That's the whole grammar of the editorial pages.
  • Pills — tinted (Meadow / Alpenglow / Bayern) for metadata, hairline-bordered with a leading icon for live status.
  • Leaderboard rows — hairline-divided, tabular-nums for steps, medal-color rank only on top 3, soft Bayern background for the current user's row.
  • Buttons — primary (Bayern fill), secondary (hairline + text), ghost (text only with hover tint). All 44 px tall to satisfy touch-target minimums on mobile.
  • Inputs — borderless except for a single bottom hairline that thickens to a 2 px Bayern rule on focus. Minimum 16 px font.
  • Modal — centered card on desktop; bottom sheet on mobile. The one place the system uses real shadow.

Accessibility

The system targets WCAG AA across all body and UI text. The Bayern brand colour was chosen specifically so it passes against both light and dark canvases without needing a different "on dark" variant beyond the dark-theme token swap.

Keyboard navigation uses a 2 px Bayern focus ring (:focus-visible only — never on mouse-driven focus). Tap highlights on touch devices are suppressed in favour of the same ring. Touch targets are at least 44×44 throughout the chrome.

The whole system collapses motion to near-zero under prefers-reduced-motion: reduce, including the brand-tile lift and the theme-toggle fade.

Light & dark

Both themes are first-class. The light theme is the default and is the canonical "magazine spread" feel — bright canvas, deep ink, soft accents. The dark theme is an alpine twilight: a deep navy canvas (#08111A), brighter Bayern (#5BA3DB) for accessibility contrast, and a slightly warmer Alpenglow (#F0A572) so the sunrise-on-peaks metaphor still reads at low light. All accent soft-fills invert from pale tints to deep tints (#E7F1E9#1C2E22), keeping the same role-pairings intact across modes.

Theme switching is instant and animated only at the body level (200 ms colour cross-fade). All component tokens resolve through the same CSS variable system, so a theme change never reflows the layout.