You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Last updated: 2026-03-14
Status: Active (incremental — updates as #407/#408 complete)
Owner issue:#410Parent epic:#397 — Brand Identity Foundation
This document is the single source of truth for the project's visual identity. It enables any contributor or designer to produce on-brand assets without guessing. All color values are sourced from docs/assets/design-tokens.json and frontend/src/styles/globals.css.
Empower consumers in Poland (and expanding to Europe) to make healthier food choices by providing transparent, science-driven quality scores for grocery products — grounded in real EU label data, never invented.
Brand Personality
Trait
Expression
Trustworthy
Every data point traced to a source. Confidence bands show data quality. No hidden logic.
Scientific
EFSA-based additive classification. Nutri-Score follows EU regulation. Peer-reviewable formula.
Clean
Minimal UI, generous whitespace, no clutter. Data-dense but visually breathable.
Data-driven
Numbers first. Score breakdowns, not opinion. Quantified ingredient concerns, not vague warnings.
Health-focused
Green = low risk, red = high risk. Every visual decision reinforces health-conscious choices.
European
Poland-first, EU regulatory alignment, RODO/GDPR compliant, multi-language ready.
"Product not found. Try scanning the barcode again."
Onboarding
Encouraging, simple
"Pick your country to see local products."
Data confidence
Transparent, honest
"Confidence: Estimated — some nutrition data may be incomplete."
Health warnings
Clinical, objective
"High in saturated fat (12g per 100g). Daily reference: 20g."
Writing rules:
Never use superlatives ("best", "worst", "healthiest") — use comparative language ("lower score", "fewer additives").
Never moralize ("you should avoid") — present data and let users decide.
Prefer metric units (g, kcal, mg). No imperial units.
Product names are legal label text — never modify, abbreviate, or translate them.
2. Logo Usage
Status: Active — logomark (#407) and lockups (#408) finalized.
Logo Variants
Variant
File
Use Case
Icon-only (full color)
logomark.svg
App icons, favicons (32px+), badges
Icon-only (dark mode)
logomark-dark.svg
App icons on dark backgrounds
Icon-only (mono)
logomark-mono.svg
Single-color contexts, watermarks, print
Horizontal lockup
lockup-horizontal.svg
Navigation bar, email headers, banners
Horizontal lockup (dark)
lockup-horizontal-dark.svg
Nav bar on dark backgrounds
Stacked lockup
lockup-stacked.svg
Marketing materials, splash screens
Stacked lockup (dark)
lockup-stacked-dark.svg
Splash screens on dark backgrounds
Wordmark
wordmark.svg
Text-only contexts (placeholder name)
Wordmark (dark)
wordmark-dark.svg
Text-only on dark backgrounds
Wordmark note: The wordmark is a deliberate placeholder. When the project name changes, regenerate wordmark.svg and wordmark-dark.svg. The lockup architecture makes this swap trivial — only the <text> element changes.
Clear Space Rules
Minimum clear space around logomark: icon height × 0.5 on all sides.
Minimum clear space in horizontal lockup: icon height × 0.5 between icon and wordmark.
Minimum clear space in stacked lockup: icon height × 0.3 between icon and wordmark.
Minimum padding around entire lockup: icon height × 0.25 on all sides.
Minimum Size Rules
Context
Minimum Size
Action
Digital icon-only
16×16px
Use monochrome variant (logomark-mono.svg)
Digital icon-only
32×32px+
Use full-color variant
Horizontal lockup
120px width
Below this, switch to icon-only
Stacked lockup
80px width
Below this, switch to icon-only
Print icon-only
10mm
Use monochrome variant
Do's and Don'ts
Do
Don't
Use the correct variant for the theme (light/dark)
Stretch or distort the logo
Maintain minimum clear space
Change logo colors outside approved palette
Use the monochrome variant on photos
Add drop shadows or outlines to the logo
Center-align when used as a standalone mark
Place logo smaller than minimum size
Use lockup SVGs as-is (they embed the logomark)
Recompose icon + text manually
Switch to icon-only below lockup minimum width
Crop or partially obscure the logomark
3. Color System
All colors are defined as CSS custom properties in frontend/src/styles/globals.css and documented in docs/assets/design-tokens.json. Never use hardcoded hex values in components — always reference the token.
3.1 Brand Identity Colors
Role
Token
Light
Dark
WCAG on bg
Usage
Primary
--color-brand-primary
#0d7377
#2dd4bf
5.6:1 (AA)
Logos, headers, primary CTA backgrounds
Primary Dark
--color-brand-primary-dark
#095456
#0d7377
8.5:1 (AAA)
Hover states on primary, gradient endpoints
Secondary
--color-brand-secondary
#f8fafc
#1e293b
Background
Page backgrounds, card fills
Accent (Gold)
--color-brand-accent
#d4a844
#fbbf24
2.2:1 / 12.3:1
Decorative only on light; text-safe on dark
Warning: Brand accent (gold) does NOT meet WCAG AA for text on white. Use it only for decorative elements, badge borders, or on dark backgrounds where it achieves 12.3:1.
3.2 Action Colors (UI)
Role
Token
Light
Dark
Usage
Action
--color-brand
#15803d
#4ade80
Buttons, links, toggles
Action Hover
--color-brand-hover
#166534
#22c55e
Hover/focus states
Action Subtle
--color-brand-subtle
#dcfce7
#14532d
Selected states, soft highlights
3.3 Health Score Bands
These colors are the most critical visual element in the application. They must remain consistent across themes — same hues, only brightness adjusted.
Band
Score
Token
Light
Dark
Text Token
Text Light
Text Dark
Green
1–20
--color-score-green
#22c55e
#4ade80
--color-score-green-text
#15803d
#4ade80
Yellow
21–40
--color-score-yellow
#eab308
#facc15
--color-score-yellow-text
#854d0e
#facc15
Orange
41–60
--color-score-orange
#f97316
#fb923c
--color-score-orange-text
#c2410c
#fb923c
Red
61–80
--color-score-red
#ef4444
#f87171
--color-score-red-text
#b91c1c
#f87171
Dark Red
81–100
--color-score-darkred
#991b1b
#dc2626
--color-score-darkred-text
#991b1b
#dc2626
Invariant: Score band colors use the same hues in both themes. Users learn the color associations; never change them between themes.
3.4 Nutri-Score (EU Standard)
These colors are defined by EU regulation and must not be modified.
Grade
Token
Light
Dark
A
--color-nutri-A
#038141
#34d399
B
--color-nutri-B
#85bb2f
#a3e635
C
--color-nutri-C
#fecb02
#fde047
D
--color-nutri-D
#ee8100
#fb923c
E
--color-nutri-E
#e63e11
#f87171
3.5 NOVA Processing Groups
Group
Label
Token
Light
Dark
1
Unprocessed
--color-nova-1
#22c55e
#4ade80
2
Processed culinary
--color-nova-2
#84cc16
#a3e635
3
Processed
--color-nova-3
#f59e0b
#fbbf24
4
Ultra-processed
--color-nova-4
#ef4444
#f87171
3.6 Confidence Bands
Band
Token
Light
Dark
High
--color-confidence-high
#22c55e
#4ade80
Medium
--color-confidence-medium
#f59e0b
#fbbf24
Low
--color-confidence-low
#ef4444
#f87171
3.7 Allergen Severity
Level
Token
Light
Dark
Present
--color-allergen-present
#ef4444
#f87171
Traces
--color-allergen-traces
#f59e0b
#fbbf24
Free
--color-allergen-free
#22c55e
#4ade80
3.8 Semantic Feedback
Role
Token
Light
Dark
Success
--color-success
#22c55e
#4ade80
Warning
--color-warning
#f59e0b
#fbbf24
Error
--color-error
#ef4444
#f87171
Info
--color-info
#3b82f6
#60a5fa
3.9 Nutrition Traffic Light (FSA/EFSA)
Level
Token
Light
Dark
Low
--color-nutrient-low
#22c55e
#4ade80
Medium
--color-nutrient-medium
#f59e0b
#fbbf24
High
--color-nutrient-high
#ef4444
#f87171
3.10 Surfaces, Borders & Neutrals
Token
Light
Dark
Usage
--color-surface
#ffffff
#111827
Page/card background
--color-surface-subtle
#f9fafb
#1f2937
Alternating rows, body bg
--color-surface-muted
#f3f4f6
#374151
Disabled states, skeleton base
--color-surface-overlay
rgba(0,0,0,0.5)
rgba(0,0,0,0.7)
Modal backdrop
--color-border
#e5e7eb
#374151
Card borders, dividers
--color-border-strong
#d1d5db
#4b5563
Input borders, emphasis lines
--color-neutral-50
#f8fafc
#0f172a
Lightest neutral
--color-neutral-200
#e2e8f0
#334155
Dividers
--color-neutral-400
#94a3b8
#94a3b8
Placeholder text
--color-neutral-600
#475569
#cbd5e1
Secondary content
--color-neutral-900
#0f172a
#f8fafc
Darkest neutral / headings
Color Usage Rules
Never hardcode hex values in components. Always use CSS custom properties or Tailwind utility classes.
Brand primary (#0d7377) is for identity — logos, headers, diagrams. Action (#15803d) is for interactive elements — buttons, links.
Score colors must never be repurposed for non-scoring contexts. Green always means low-risk; red always means high-risk.
Nutri-Score colors are immutable — they follow EU regulation.
Test all color pairings for WCAG AA (4.5:1 normal text, 3:1 large text/UI) before use.
4. Typography
Font Stack
The application uses the system font stack for performance — no web font downloads required:
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,"Segoe UI", Roboto,"Helvetica Neue", Arial,"Noto Sans",
sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";
For monospaced contexts (EAN codes, score values, data tables):
Never use: Score band colors for decorative purposes in illustrations — reserve them for data.
7. Photography Direction
Product Photography
Property
Guideline
Background
Plain white or light gray (#f8fafc) — no textured or patterned backgrounds
Lighting
Even, diffused lighting — no harsh shadows or specular highlights
Angle
Front-facing, label visible — the product as a consumer would see it on a shelf
Branding
Store branding/price tags must be removed or cropped
Resolution
Minimum 400×400px for product cards, 800×800px for detail pages
Format
WebP preferred (with JPEG fallback), max 200KB per product image
Consistency
All products in a category should have matching framing and scale
User-Submitted Photos (via product_submissions)
Accepted: Clear front-of-pack photo showing product name, brand, and barcode.
Rejected: Blurry, rotated, or partial images. Multiple products in one photo.
Processing: Images are resized to max 1200px longest edge before storage.
Photography in Marketing
Lifestyle photography (food on plates, grocery shopping) may be used for marketing but never in the core data application.
Always pair lifestyle photos with the actual product data — never present photography without corresponding nutrition information.
8. Component Patterns
All component classes are defined in frontend/src/styles/globals.css under @layer components. Components use CSS custom properties through Tailwind utility classes — never hardcoded values.
All text and UI elements follow WCAG 2.1 Level AA:
Element Type
Minimum Ratio
Standard
Normal text (< 18px)
4.5:1
WCAG AA
Large text (≥ 18px bold or ≥ 24px)
3:1
WCAG AA
UI components (borders, icons)
3:1
WCAG AA
Decorative elements
No requirement
—
Verified Contrast Ratios
Color Pair
Ratio
Pass
Brand primary #0d7377 on white #ffffff
5.6:1
AA
Brand primary dark #095456 on white
8.5:1
AAA
Text primary #111827 on surface #ffffff
17.1:1
AAA
Text secondary #4b5563 on surface
7.08:1
AAA
Text muted #6b7280 on surface
4.63:1
AA
Score green text #15803d on white
5.1:1
AA
Score yellow text #854d0e on white
5.9:1
AA
Score orange text #c2410c on white
5.2:1
AA
Score red text #b91c1c on white
5.9:1
AA
Score darkred text #991b1b on white
8.3:1
AAA
Brand accent #d4a844 on white
2.2:1
FAIL
Dark mode primary #2dd4bf on dark #111827
8.6:1
AAA
Dark mode accent #fbbf24 on dark #111827
12.3:1
AAA
Brand accent (#d4a844) fails WCAG AA on white backgrounds. Use only for decorative purposes (badge borders, gold accents) on light backgrounds. Safe for text on dark backgrounds.
Focus Indicators
All interactive elements receive a visible focus indicator via :focus-visible:
Focus outline color matches brand action color (context-aware).
Offset prevents the outline from overlapping element content.
Hidden when :focus but not :focus-visible (mouse clicks don't trigger outlines).
Touch Targets
Requirement
Size
Implementation
Minimum touch target
44×44px
.touch-target class
Expanded hit area (small elements)
44×44px
.touch-target-expanded (pseudo-element)
Button double-tap prevention
—
touch-action: manipulation
Screen Reader Considerations
Decorative icons paired with visible text use aria-hidden="true".
Standalone icons (no visible text) require aria-label="Description".
Score values include aria-label with the risk band label (e.g., aria-label="Score 45, Elevated risk").
Color-blind safe: Score bands are never conveyed by color alone — they always include a text label or numeric value.
Dynamic content uses aria-live="polite" for non-urgent updates (score recalculation) and aria-live="assertive" for errors.
Reduced Motion (reiterated)
All motion tokens collapse to 0ms when prefers-reduced-motion: reduce is active. Skeleton shimmer falls back to a static muted background. See §10 — Motion & Animation.
12. Dark Mode
Theme Implementation
Dark mode is applied via the data-theme="dark" attribute on the root element:
<htmldata-theme="dark">
Fallback: If no data-theme is set, @media (prefers-color-scheme: dark) activates dark mode automatically — until the user makes an explicit choice.
Full Light → Dark Mapping Table
Token
Light
Dark
Surfaces
--color-surface
#ffffff
#111827
--color-surface-subtle
#f9fafb
#1f2937
--color-surface-muted
#f3f4f6
#374151
--color-surface-overlay
rgba(0,0,0,0.5)
rgba(0,0,0,0.7)
Text
--color-text-primary
#111827
#f9fafb
--color-text-secondary
#4b5563
#d1d5db
--color-text-muted
#6b7280
#9ca3af
--color-text-inverse
#ffffff
#111827
Border
--color-border
#e5e7eb
#374151
--color-border-strong
#d1d5db
#4b5563
Brand Action
--color-brand
#15803d
#4ade80
--color-brand-hover
#166534
#22c55e
--color-brand-subtle
#dcfce7
#14532d
Brand Identity
--color-brand-primary
#0d7377
#2dd4bf
--color-brand-primary-dark
#095456
#0d7377
--color-brand-secondary
#f8fafc
#1e293b
--color-brand-accent
#d4a844
#fbbf24
Neutral Scale
--color-neutral-50
#f8fafc
#0f172a
--color-neutral-200
#e2e8f0
#334155
--color-neutral-400
#94a3b8
#94a3b8
--color-neutral-600
#475569
#cbd5e1
--color-neutral-900
#0f172a
#f8fafc
Score Bands
--color-score-green
#22c55e
#4ade80
--color-score-yellow
#eab308
#facc15
--color-score-orange
#f97316
#fb923c
--color-score-red
#ef4444
#f87171
--color-score-darkred
#991b1b
#dc2626
Score Text
--color-score-green-text
#15803d
#4ade80
--color-score-yellow-text
#854d0e
#facc15
--color-score-orange-text
#c2410c
#fb923c
--color-score-red-text
#b91c1c
#f87171
--color-score-darkred-text
#991b1b
#dc2626
Nutri-Score
--color-nutri-A
#038141
#34d399
--color-nutri-B
#85bb2f
#a3e635
--color-nutri-C
#fecb02
#fde047
--color-nutri-D
#ee8100
#fb923c
--color-nutri-E
#e63e11
#f87171
NOVA
--color-nova-1
#22c55e
#4ade80
--color-nova-2
#84cc16
#a3e635
--color-nova-3
#f59e0b
#fbbf24
--color-nova-4
#ef4444
#f87171
Nutrition Traffic Light
--color-nutrient-low
#22c55e
#4ade80
--color-nutrient-medium
#f59e0b
#fbbf24
--color-nutrient-high
#ef4444
#f87171
Confidence
--color-confidence-high
#22c55e
#4ade80
--color-confidence-medium
#f59e0b
#fbbf24
--color-confidence-low
#ef4444
#f87171
Allergen
--color-allergen-present
#ef4444
#f87171
--color-allergen-traces
#f59e0b
#fbbf24
--color-allergen-free
#22c55e
#4ade80
Semantic
--color-success
#22c55e
#4ade80
--color-warning
#f59e0b
#fbbf24
--color-error
#ef4444
#f87171
--color-info
#3b82f6
#60a5fa
Shadows
--shadow-sm
rgba(0,0,0,0.05)
rgba(0,0,0,0.3)
--shadow-md
rgba(0,0,0,0.1)
rgba(0,0,0,0.4)
--shadow-lg
rgba(0,0,0,0.1)
rgba(0,0,0,0.4)
Design Principles for Dark Mode
Don't invert — remap. Dark mode is not a simple inversion. Background goes dark, text goes light, but colored data indicators (scores, Nutri-Score) retain their hue identity.
Increase shadow opacity. Shadows need higher opacity on dark backgrounds to maintain visual hierarchy.
Neutral scale inverts.neutral-50 (lightest in light mode) becomes the darkest value in dark mode and vice versa.
Score band hues are preserved — only the lightness adjusts to maintain readability. Users must recognize "green = good" regardless of theme.
Logo variant selection: Use the dark-mode logo variant (when available from #407/#408) on dark backgrounds. Never place the light logo on dark backgrounds.
Theme transition: 150ms ease on background-color and color, disabled during initial page load to prevent flash.
13. Co-branding
Partner Logos
This project acknowledges the following partners and data sources: