mozo — Design System
Can be used as a Google Stitch DESIGN.md. AI agents read this to generate consistent mozo UI. Drop a copy into any mozo repo root for AI tooling that supports DESIGN.md.
Brand Identity
mozo is table-side ordering that makes restaurants faster. Not a POS replacement — a complement. The brand is warm, straightforward, and trustworthy. Like a good waiter: present when needed, invisible otherwise.
Tone: Clean hospitality — not luxury, not tech-bro, not playful-food-app. Who sees it: Restaurant owners (supplier app), diners (user app), curious restaurateurs (marketing site). The promise: “5 minutes to set up. Your guests love it. You make more money.”
Color System
Core Palette (OKLCH-adjacent, warm hospitality)
/* Backgrounds */
--bg-cream: #fbf8f3; /* primary page background — warm, not stark white */
--bg-sand: #f5f0e8; /* section alternate — subtle differentiation */
--bg-white: #ffffff; /* cards, elevated surfaces (rarely used) */
/* Text */
--ink: #1a1611; /* primary text — dark brown, never pure black */
--ink-muted: rgba(26, 22, 17, 0.6); /* secondary text */
--ink-subtle: rgba(26, 22, 17, 0.35); /* tertiary, borders */
/* Accent */
--amber: #d97706; /* primary accent — CTAs, highlights, mozo.BAR */
--amber-hover: #b96004; /* hover state */
--amber-subtle: rgba(217, 119, 6, 0.1); /* accent backgrounds */
/* Semantic */
--success: #059669; /* confirmations, active states */
--danger: #dc2626; /* errors, destructive actions */
--warning: #f59e0b; /* warnings, pending states */
Usage Rules
- NEVER use pure black (#000) or pure white (#fff) — always tint slightly
- No gradients. Solid colors only. No backdrop-blur effects.
- Amber is scarce. One CTA per viewport. Never amber text on amber background.
- Gray text always goes on a background with enough contrast — no gray-on-gray-on-gray nesting
- Dark mode: Not yet. Light theme only. When dark mode is added, invert the cream→dark charcoal, not pure black.
Typography
Font Stack
/* Primary: Inter (clean, versatile, great legibility) */
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
/* Monospace: for code, tables, data (rare in mozo UI but available) */
font-family: 'JetBrains Mono', 'Fira Code', monospace;
Scale
| Token | Size | Weight | Use |
|---|---|---|---|
text-xs | 0.75rem (12px) | 400/500 | Labels, captions, meta |
text-sm | 0.875rem (14px) | 400/500 | Secondary text, table cells |
text-base | 1rem (16px) | 400 | Body text minimum |
text-lg | 1.125rem (18px) | 400 | Lead paragraphs, marketing body |
text-xl | 1.25rem (20px) | 500 | Subheadings, card titles |
text-2xl | 1.5rem (24px) | 600 | Section headers (small) |
text-3xl | 1.875rem (30px) | 700 | Section headers |
text-4xl | 2.25rem (36px) | 700 | Page titles, hero subheads |
text-5xl | 3rem (48px) | 800 | Hero headlines |
text-6xl | 3.75rem (60px) | 800 | Hero headlines (large) |
Typography Rules
- Never use more than 3 sizes on one screen (hero can use 4)
- No all-caps for body text. All-caps only for eyebrow labels (
.text-sm.font-semibold.tracking-widest.uppercase) - No lorem ipsum in production — real content or nothing
- Line height:
leading-tightfor headings (1.25),leading-relaxedfor body (1.625) - Never use
text-centeron paragraphs longer than 2 lines — left-aligned is more readable - Font weight: 400 for body, 500-600 for emphasis, 700-800 for headings. Never use 300 or 900.
Spatial System
Spacing Scale (Tailwind v4 compatible)
0, px (1px), 0.5 (2px), 1 (4px), 1.5 (6px), 2 (8px), 2.5 (10px),
3 (12px), 3.5 (14px), 4 (16px), 5 (20px), 6 (24px), 7 (28px),
8 (32px), 9 (36px), 10 (40px), 11 (44px), 12 (48px), 14 (56px),
16 (64px), 20 (80px), 24 (96px), 28 (112px), 32 (128px)
Layout
/* Page container */
max-width: 72rem; /* max-w-6xl = 1152px */
padding-x: 1.25rem; /* px-5 */
padding-x-md: 2rem; /* md:px-8 */
/* Section vertical rhythm */
padding-y: 5rem; /* py-20 */
padding-y-md: 7rem; /* md:py-28 */
/* Grid gaps */
gap: 1.5rem; /* gap-6 — card grids */
gap-lg: 2rem; /* gap-8 — section spacing */
/* Content max-width for readability */
max-width: 42rem; /* max-w-2xl — for long-form text */
Spatial Rules
- Generous whitespace. mozo is spacious, not dense. If in doubt, add more space.
- No borders. Use whitespace and subtle background shifts (
bg-sand) to separate sections. Borders only for tables and form fields. - No shadows except on primary CTAs — and even then, subtle:
shadow-lg shadow-amber/20 - No cards nested in cards. If content needs grouping, use a subtle background shift, not a border/shadow card.
- Consistent section rhythm: Every section gets identical vertical padding. No exceptions.
Motion
Philosophy
Motion should feel like a well-trained waiter: efficient, barely noticeable, slightly warm.
Rules
- Duration: 150ms for micro-interactions, 200-300ms for transitions, 400ms max for entrances
- Easing:
ease-outfor entrances,ease-in-outfor state changes. Neverease-inalone, neverlinear. - No bounce or elastic easing — feels dated and playful, not right for hospitality
- No scroll-triggered animations. mozo is functional, not a portfolio site.
- No skeleton loaders unless the wait is >500ms — render immediately or show a simple spinner
- Hover states: subtle background shift or underline. Color changes only on interactive elements.
Animation Inventory
| Element | Animation | Duration | Easing |
|---|---|---|---|
| Button hover | background-color + shadow shift | 150ms | ease-out |
| Link hover | color shift + optional underline | 150ms | ease-out |
| Modal open | fade + scale(0.95→1) | 200ms | ease-out |
| Modal close | fade + scale(1→0.95) | 150ms | ease-in |
| Toast/appear | slide-up + fade | 300ms | ease-out |
| Toast/dismiss | fade-out | 200ms | ease-out |
| Tab switch | crossfade or instant | 150ms | ease-in-out |
| Page transition | instant (no animation) | 0ms | — |
What NOT to animate
- Page loads (just render the page)
- Paragraph text (staggered text reveals are for agency sites)
- Icons spinning endlessly (use for active loading only)
- Background colors on scroll
Component Inventory
Buttons
<!-- Primary CTA -->
<a class="inline-flex items-center gap-2 bg-amber text-white px-8 py-4 rounded-lg
font-semibold text-lg hover:bg-amber/90 transition shadow-lg shadow-amber/20">
Get Started →
</a>
<!-- Secondary -->
<a class="inline-flex items-center gap-2 border border-ink/10 text-ink px-6 py-3
rounded-lg font-medium hover:bg-ink/5 transition">
Learn more
</a>
<!-- Ghost / Text-only -->
<a class="text-amber font-medium hover:underline transition">
Sign in →
</a>
<!-- Destructive -->
<button class="bg-red-600 text-white px-6 py-2.5 rounded-lg font-medium
hover:bg-red-700 transition">
Delete
</button>
<!-- Disabled -->
<button class="bg-amber/40 text-white px-6 py-2.5 rounded-lg font-medium cursor-not-allowed" disabled>
Save
</button>
Cards
<!-- Standard card (no shadow, subtle border) -->
<div class="border border-ink/5 rounded-xl p-6 hover:border-ink/10 transition">
<h3 class="font-semibold text-ink mb-2">Title</h3>
<p class="text-ink/60 text-sm">Description</p>
</div>
<!-- Feature card with icon -->
<div class="text-center p-8">
<div class="text-4xl mb-4">🖨</div>
<h3 class="font-semibold text-ink mb-2">Feature</h3>
<p class="text-ink/60 text-sm">Description</p>
</div>
Forms
<!-- Text input -->
<div class="mb-4">
<label class="block text-sm font-medium text-ink mb-1.5">Email</label>
<input type="email" class="w-full px-4 py-2.5 border border-ink/10 rounded-lg
text-ink bg-white focus:border-amber focus:ring-1
focus:ring-amber/20 outline-none transition"
placeholder="you@restaurant.com">
</div>
<!-- Select -->
<select class="w-full px-4 py-2.5 border border-ink/10 rounded-lg
text-ink bg-white focus:border-amber focus:ring-1
focus:ring-amber/20 outline-none transition appearance-none">
<option>Choose...</option>
</select>
<!-- Checkbox -->
<label class="flex items-center gap-2 cursor-pointer">
<input type="checkbox" class="w-4 h-4 rounded border-ink/10 text-amber
focus:ring-amber/20">
<span class="text-sm text-ink/70">Remember me</span>
</label>
<!-- Error state -->
<input class="... border-red-500 focus:border-red-500 focus:ring-red-500/20">
<p class="text-red-600 text-sm mt-1">This field is required</p>
Tables
<!-- Data table -->
<div class="overflow-x-auto">
<table class="w-full text-left">
<thead>
<tr class="border-b border-ink/10">
<th class="py-3 pr-8 font-semibold text-ink text-sm">Name</th>
<th class="py-3 pr-8 font-semibold text-ink text-sm">Status</th>
<th class="py-3 font-semibold text-ink text-sm">Actions</th>
</tr>
</thead>
<tbody class="divide-y divide-ink/5">
<tr class="hover:bg-ink/[0.02] transition">
<td class="py-4 pr-8 text-ink">Table 7</td>
<td class="py-4 pr-8">
<span class="inline-flex items-center gap-1 text-emerald-700 text-sm">
<span class="w-1.5 h-1.5 bg-emerald-500 rounded-full"></span>
Active
</span>
</td>
<td class="py-4">
<a href="#" class="text-amber text-sm font-medium hover:underline">Edit</a>
</td>
</tr>
</tbody>
</table>
</div>
Modals
<!-- Backdrop -->
<div class="fixed inset-0 bg-black/40 z-50 flex items-center justify-center p-4">
<!-- Modal -->
<div class="bg-white rounded-xl shadow-xl max-w-md w-full p-6">
<h3 class="text-lg font-semibold text-ink mb-2">Confirm</h3>
<p class="text-ink/60 text-sm mb-6">Are you sure you want to delete this table?</p>
<div class="flex justify-end gap-3">
<button class="px-4 py-2 border border-ink/10 rounded-lg text-ink/70
text-sm font-medium hover:bg-ink/5 transition">
Cancel
</button>
<button class="px-4 py-2 bg-red-600 text-white rounded-lg text-sm
font-medium hover:bg-red-700 transition">
Delete
</button>
</div>
</div>
</div>
Status Badges
<!-- Active/Success -->
<span class="inline-flex items-center gap-1 px-2.5 py-1 bg-emerald-50 text-emerald-700
text-xs font-medium rounded-full">
<span class="w-1.5 h-1.5 bg-emerald-500 rounded-full"></span> Active
</span>
<!-- Pending/Warning -->
<span class="inline-flex items-center gap-1 px-2.5 py-1 bg-amber-50 text-amber-700
text-xs font-medium rounded-full">
<span class="w-1.5 h-1.5 bg-amber-500 rounded-full"></span> Pending
</span>
<!-- Error/Danger -->
<span class="inline-flex items-center gap-1 px-2.5 py-1 bg-red-50 text-red-700
text-xs font-medium rounded-full">
<span class="w-1.5 h-1.5 bg-red-500 rounded-full"></span> Error
</span>
<!-- Neutral -->
<span class="inline-flex items-center px-2.5 py-1 bg-ink/5 text-ink/60
text-xs font-medium rounded-full">Draft</span>
Anti-Patterns (DO NOT DO)
These are the most common AI-generated slop patterns. Avoid them all.
Color & Background
- ❌ Pure black (#000) or pure white (#fff) — always tint
- ❌ Gray text on colored backgrounds — invisible, inaccessible
- ❌ Purple-to-blue gradients — the most overused AI design cliché
- ❌ Backdrop-blur glassmorphism — wrong for hospitality
- ❌ Multiple accent colors — amber is the only accent. One accent = one brand.
Layout
- ❌ Cards nested inside cards — if you need grouping, use bg-shift or spacing
- ❌ Dark borders everywhere — use whitespace, not boxes
- ❌ Center-aligning paragraphs >2 lines — illegible
- ❌ Overlapping elements with negative margins — fragile, breaks on mobile
- ❌ Horizontal scroll on desktop — never. If it scrolls sideways, it’s broken.
Typography
- ❌ Inter for everything — Inter is our primary, but don’t make it the ONLY choice. (Actually for mozo, Inter alone is fine because we’re not a design-forward brand. But don’t use system-ui fallback when Inter is available.)
- ❌ All-caps paragraphs — all-caps only for eyebrow labels (< 5 words)
- ❌ Em dashes (—) — use regular dashes or commas. Em dashes in AI-generated text are a dead giveaway.
- ❌ Title Case Headings — use Sentence case for headings. “How it works” not “How It Works”.
- ❌ Bold text in body paragraphs — use for genuine emphasis only, never as decoration.
Content
- ❌ “Nestled within…” / “In today’s rapidly evolving…” — AI content tells
- ❌ “Great question!” / “I’d be happy to help!” — sycophantic openings
- ❌ “Let’s dive in” / “Here’s what you need to know” — signposting filler
- ❌ “In conclusion” / “The future looks bright” — generic conclusions
- ❌ Emoji in headings or CTAs — emoji in feature cards is fine. In headings, it looks desperate.
- ❌ “We’re excited to announce…” — just announce it.
Motion
- ❌ Bounce/easeOutBack easing — dated, feels like 2015
- ❌ Scroll-triggered reveals — performance tax for no functional gain
- ❌ Continuous animations (spinning icons, pulsing elements) — distracting
- ❌ Page transition animations — just render the page
- ❌ Hover scale transforms — subtle color/bg change only
Empty States
- ❌ “No data available” with nothing else — every empty state should tell the user what TO do
- ❌ Generic illustrations — a simple icon + text is better than a random undraw illustration
Page Templates
Marketing Page (mozo.bar)
1. HERO — eyebrow label + headline + subheadline + CTA + stats bar
2. HOW IT WORKS — 1-2-3-4 numbered steps
3. WHAT YOU NEED — 3 simple items with emoji icons
4. COMPARISON TABLE — mozo vs alternatives
5. BENEFITS — 3-4 feature cards
6. CTA FOOTER — same CTA as hero
Dashboard Page (supplier app)
1. HEADER — logo + supplier name + nav
2. STATUS BAR — quick stats (active tables, open orders, today's revenue)
3. MAIN CONTENT — table management grid or list
4. SIDE PANEL — context-sensitive details (open on click, not hover)
Form Page
1. HEADER — page title + back link
2. FORM — grouped fields with clear labels, inline validation
3. ACTIONS — save/cancel, save button is amber, cancel is ghost
Accessibility
- All interactive elements must be keyboard-focusable and show a visible focus ring
- Focus ring:
ring-2 ring-amber/50 ring-offset-2— amber, not browser default blue - Minimum touch target: 44×44px for all interactive elements on mobile
- Color contrast: Text on backgrounds must meet WCAG AA (4.5:1 for body, 3:1 for large text)
- Reduced motion: Respect
prefers-reduced-motion. Disable all animations when set. - Alt text: Every image needs
alt. Icons that are decorative getalt="".
Responsive Strategy
Breakpoints (Tailwind v4 defaults)
| Prefix | Min width | Use for |
|---|---|---|
| (none) | 0 | Mobile first — everything works here |
sm | 640px | Large phones |
md | 768px | Tablets |
lg | 1024px | Small laptops |
xl | 1280px | Desktops |
Rules
- Mobile-first always. Write the mobile layout, then add
md:overrides. - No hidden content on mobile — if it matters, show it. If it doesn’t, remove it.
- Stack on mobile, side-by-side on desktop — the standard grid pattern
- Tables on mobile: Either responsive scroll wrapper OR card layout. Never fixed-width tables.
- Navigation: Bottom tab bar on mobile (or hamburger), top bar on desktop.
Supplier App — Specific
Current State
- Ember 3.26, Emblem templates, CoffeeScript, Foundation 5
- Desktop-only design, raw
<table>login page - FA 4.7 icons via CDN
Immediate Targets
- Login page — rewrite with Foundation 5 grid (
.row,.small-12.medium-6.columns,.control-group) - Tables — add
table.responsivewrapper, test on mobile - Icons — FA 4.7 → 6 migration map
- Color tokens — unify with mozo palette via
_shared-tokens.scss
Long-term: Component Migration
When migrating from Foundation 5 to Tailwind, go component-by-component:
- Pick one route (e.g., login)
- Rewrite in Tailwind using this DESIGN.md
- Test, deploy, wait a week
- Pick next route
Never do a big-bang CSS migration.
Docs Site — Specific
docs.mozo.bar is a Hugo static site with a custom minimal theme. Design constraints:
- Primarily text content (guides, how-tos)
- Must be readable on mobile (restaurant owners reading setup guides)
- Should feel like part of mozo.bar family
The Hugo theme’s CSS should reference the same color tokens and typography scale.
Design Review Checklist
Before shipping any page, verify:
- No pure black or pure white anywhere
- No em dashes in text content
- No AI-tell phrases (“nestled”, “dive in”, “game-changer”)
- Amber used once per viewport (one CTA, not five)
- Maximum 3-4 font sizes per page
- Mobile layout works (not just responsive, actually tested)
- Touch targets ≥ 44px on mobile
- No horizontal scroll at any breakpoint
- No cards nested in cards
- No gradients or backdrop-blur
- Forms have visible labels and error states
- Empty states have clear next actions
- Focus rings visible on keyboard navigation
-
prefers-reduced-motionrespected
Last updated: 2026-06-01 Based on: mozo-page-design-recipe.md + impeccable anti-patterns + taste-skill principles + awesome-design-md format