Full design token file with colors, typography, spacing, shadows, breakpoints, animation, z-index, and component-level specs for: buttons, cards, inputs, badges, navbar, sidebar, tables, modals, toasts, avatars, menus, chips, ratings, and price tags. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1079 lines
43 KiB
HTML
1079 lines
43 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Grubflip Design System v1.0</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
<style>
|
|
/* ========================================
|
|
GRUBFLIP DESIGN SYSTEM v1.0
|
|
Created by Ava — 2026-03-25
|
|
======================================== */
|
|
|
|
/* --- CSS Custom Properties (Design Tokens) --- */
|
|
:root {
|
|
/* Primary — Warm Orange (appetite, energy, action) */
|
|
--gf-primary: #FF6B35;
|
|
--gf-primary-light: #FF8F66;
|
|
--gf-primary-dark: #D94E1F;
|
|
--gf-primary-bg: #FFF3ED;
|
|
|
|
/* Secondary — Deep Green (fresh food, trust, growth) */
|
|
--gf-secondary: #2D6A4F;
|
|
--gf-secondary-light: #40916C;
|
|
--gf-secondary-dark: #1B4332;
|
|
--gf-secondary-bg: #EDF5F0;
|
|
|
|
/* Accent — Golden Yellow (highlights, badges, stars) */
|
|
--gf-accent: #FFBA08;
|
|
--gf-accent-light: #FFD166;
|
|
--gf-accent-dark: #E0A100;
|
|
--gf-accent-bg: #FFF8E1;
|
|
|
|
/* Semantic */
|
|
--gf-success: #2ECC71;
|
|
--gf-success-bg: #EAFAF1;
|
|
--gf-warning: #F39C12;
|
|
--gf-warning-bg: #FEF5E7;
|
|
--gf-error: #E74C3C;
|
|
--gf-error-bg: #FDEDEC;
|
|
--gf-info: #3498DB;
|
|
--gf-info-bg: #EBF5FB;
|
|
|
|
/* Neutrals */
|
|
--gf-gray-50: #FAFAFA;
|
|
--gf-gray-100: #F5F5F5;
|
|
--gf-gray-200: #E5E5E5;
|
|
--gf-gray-300: #D4D4D4;
|
|
--gf-gray-400: #A3A3A3;
|
|
--gf-gray-500: #737373;
|
|
--gf-gray-600: #525252;
|
|
--gf-gray-700: #404040;
|
|
--gf-gray-800: #262626;
|
|
--gf-gray-900: #171717;
|
|
|
|
/* Background */
|
|
--gf-bg: #FFFFFF;
|
|
--gf-bg-subtle: #FAFAFA;
|
|
--gf-bg-muted: #F5F5F5;
|
|
|
|
/* Typography */
|
|
--gf-font-heading: 'Plus Jakarta Sans', sans-serif;
|
|
--gf-font-body: 'Inter', sans-serif;
|
|
|
|
/* Spacing base: 4px */
|
|
--gf-space-1: 0.25rem;
|
|
--gf-space-2: 0.5rem;
|
|
--gf-space-3: 0.75rem;
|
|
--gf-space-4: 1rem;
|
|
--gf-space-5: 1.25rem;
|
|
--gf-space-6: 1.5rem;
|
|
--gf-space-8: 2rem;
|
|
--gf-space-10: 2.5rem;
|
|
--gf-space-12: 3rem;
|
|
--gf-space-16: 4rem;
|
|
--gf-space-20: 5rem;
|
|
|
|
/* Border Radius */
|
|
--gf-radius-sm: 0.375rem;
|
|
--gf-radius-md: 0.5rem;
|
|
--gf-radius-lg: 0.75rem;
|
|
--gf-radius-xl: 1rem;
|
|
--gf-radius-2xl: 1.5rem;
|
|
--gf-radius-full: 9999px;
|
|
|
|
/* Shadows */
|
|
--gf-shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
|
|
--gf-shadow-md: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1);
|
|
--gf-shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1);
|
|
--gf-shadow-xl: 0 20px 25px -5px rgba(0,0,0,0.1), 0 8px 10px -6px rgba(0,0,0,0.1);
|
|
--gf-shadow-card: 0 2px 8px rgba(0,0,0,0.08);
|
|
}
|
|
|
|
/* --- Reset & Base --- */
|
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
html { font-size: 16px; -webkit-font-smoothing: antialiased; }
|
|
body {
|
|
font-family: var(--gf-font-body);
|
|
color: var(--gf-gray-800);
|
|
background: var(--gf-bg);
|
|
line-height: 1.6;
|
|
}
|
|
|
|
/* --- Layout --- */
|
|
.ds-container {
|
|
max-width: 1120px;
|
|
margin: 0 auto;
|
|
padding: var(--gf-space-8) var(--gf-space-6);
|
|
}
|
|
.ds-section {
|
|
margin-bottom: var(--gf-space-16);
|
|
}
|
|
.ds-section-title {
|
|
font-family: var(--gf-font-heading);
|
|
font-size: 1.5rem;
|
|
font-weight: 700;
|
|
color: var(--gf-gray-900);
|
|
margin-bottom: var(--gf-space-2);
|
|
padding-bottom: var(--gf-space-2);
|
|
border-bottom: 2px solid var(--gf-primary);
|
|
display: inline-block;
|
|
}
|
|
.ds-section-desc {
|
|
color: var(--gf-gray-500);
|
|
margin-bottom: var(--gf-space-8);
|
|
font-size: 0.938rem;
|
|
}
|
|
|
|
/* --- Header --- */
|
|
.ds-header {
|
|
background: linear-gradient(135deg, #FF6B35 0%, #D94E1F 50%, #2D6A4F 100%);
|
|
color: white;
|
|
padding: var(--gf-space-16) var(--gf-space-6);
|
|
text-align: center;
|
|
margin-bottom: var(--gf-space-12);
|
|
}
|
|
.ds-header h1 {
|
|
font-family: var(--gf-font-heading);
|
|
font-size: 3rem;
|
|
font-weight: 800;
|
|
letter-spacing: -0.02em;
|
|
margin-bottom: var(--gf-space-2);
|
|
}
|
|
.ds-header p {
|
|
font-size: 1.125rem;
|
|
opacity: 0.9;
|
|
}
|
|
.ds-logo-mark {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
/* --- Color Swatches --- */
|
|
.ds-color-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
|
gap: var(--gf-space-4);
|
|
}
|
|
.ds-color-card {
|
|
border-radius: var(--gf-radius-lg);
|
|
overflow: hidden;
|
|
box-shadow: var(--gf-shadow-card);
|
|
border: 1px solid var(--gf-gray-200);
|
|
}
|
|
.ds-color-swatch {
|
|
height: 100px;
|
|
display: flex;
|
|
align-items: flex-end;
|
|
padding: var(--gf-space-3);
|
|
}
|
|
.ds-color-swatch span {
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
padding: 2px 8px;
|
|
border-radius: var(--gf-radius-sm);
|
|
backdrop-filter: blur(4px);
|
|
}
|
|
.ds-color-swatch .light-text { color: white; background: rgba(0,0,0,0.3); }
|
|
.ds-color-swatch .dark-text { color: var(--gf-gray-800); background: rgba(255,255,255,0.7); }
|
|
.ds-color-meta {
|
|
padding: var(--gf-space-3) var(--gf-space-4);
|
|
}
|
|
.ds-color-meta strong {
|
|
display: block;
|
|
font-size: 0.875rem;
|
|
color: var(--gf-gray-800);
|
|
}
|
|
.ds-color-meta code {
|
|
font-size: 0.75rem;
|
|
color: var(--gf-gray-500);
|
|
}
|
|
.ds-color-variants {
|
|
display: flex;
|
|
gap: 0;
|
|
}
|
|
.ds-color-variants > div {
|
|
flex: 1;
|
|
height: 32px;
|
|
}
|
|
|
|
/* --- Neutral Strip --- */
|
|
.ds-neutral-strip {
|
|
display: flex;
|
|
border-radius: var(--gf-radius-lg);
|
|
overflow: hidden;
|
|
box-shadow: var(--gf-shadow-card);
|
|
border: 1px solid var(--gf-gray-200);
|
|
}
|
|
.ds-neutral-chip {
|
|
flex: 1;
|
|
height: 64px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 0.625rem;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
}
|
|
|
|
/* --- Typography --- */
|
|
.ds-type-sample {
|
|
margin-bottom: var(--gf-space-6);
|
|
padding-bottom: var(--gf-space-6);
|
|
border-bottom: 1px solid var(--gf-gray-100);
|
|
}
|
|
.ds-type-sample:last-child { border-bottom: none; }
|
|
.ds-type-label {
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
color: var(--gf-gray-400);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
margin-bottom: var(--gf-space-1);
|
|
}
|
|
.ds-type-meta {
|
|
font-size: 0.75rem;
|
|
color: var(--gf-gray-400);
|
|
margin-top: var(--gf-space-1);
|
|
}
|
|
|
|
/* --- Component Grid --- */
|
|
.ds-component-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
|
gap: var(--gf-space-6);
|
|
}
|
|
.ds-component-card {
|
|
border: 1px solid var(--gf-gray-200);
|
|
border-radius: var(--gf-radius-lg);
|
|
padding: var(--gf-space-6);
|
|
background: var(--gf-bg);
|
|
}
|
|
.ds-component-label {
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
color: var(--gf-gray-400);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
margin-bottom: var(--gf-space-4);
|
|
}
|
|
|
|
/* --- Buttons --- */
|
|
.gf-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 0.5rem;
|
|
font-family: var(--gf-font-body);
|
|
font-weight: 600;
|
|
font-size: 0.938rem;
|
|
padding: 0.625rem 1.25rem;
|
|
border-radius: var(--gf-radius-lg);
|
|
border: 2px solid transparent;
|
|
cursor: pointer;
|
|
transition: all 0.15s ease;
|
|
text-decoration: none;
|
|
line-height: 1.4;
|
|
}
|
|
.gf-btn-primary {
|
|
background: var(--gf-primary);
|
|
color: white;
|
|
}
|
|
.gf-btn-primary:hover { background: var(--gf-primary-dark); }
|
|
.gf-btn-secondary {
|
|
background: var(--gf-secondary);
|
|
color: white;
|
|
}
|
|
.gf-btn-secondary:hover { background: var(--gf-secondary-dark); }
|
|
.gf-btn-outline {
|
|
background: transparent;
|
|
color: var(--gf-primary);
|
|
border-color: var(--gf-primary);
|
|
}
|
|
.gf-btn-outline:hover { background: var(--gf-primary-bg); }
|
|
.gf-btn-ghost {
|
|
background: transparent;
|
|
color: var(--gf-gray-600);
|
|
border-color: transparent;
|
|
}
|
|
.gf-btn-ghost:hover { background: var(--gf-gray-100); color: var(--gf-gray-800); }
|
|
.gf-btn-sm { font-size: 0.813rem; padding: 0.375rem 0.875rem; border-radius: var(--gf-radius-md); }
|
|
.gf-btn-lg { font-size: 1.063rem; padding: 0.875rem 1.75rem; }
|
|
.gf-btn-icon { padding: 0.625rem; }
|
|
.gf-btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
|
|
/* --- Inputs --- */
|
|
.gf-input-group { margin-bottom: var(--gf-space-4); }
|
|
.gf-label {
|
|
display: block;
|
|
font-size: 0.875rem;
|
|
font-weight: 600;
|
|
color: var(--gf-gray-700);
|
|
margin-bottom: var(--gf-space-1);
|
|
}
|
|
.gf-input {
|
|
width: 100%;
|
|
font-family: var(--gf-font-body);
|
|
font-size: 0.938rem;
|
|
padding: 0.625rem 0.875rem;
|
|
border: 1.5px solid var(--gf-gray-300);
|
|
border-radius: var(--gf-radius-md);
|
|
background: var(--gf-bg);
|
|
color: var(--gf-gray-800);
|
|
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
|
outline: none;
|
|
}
|
|
.gf-input:focus {
|
|
border-color: var(--gf-primary);
|
|
box-shadow: 0 0 0 3px var(--gf-primary-bg);
|
|
}
|
|
.gf-input::placeholder { color: var(--gf-gray-400); }
|
|
.gf-input-error { border-color: var(--gf-error); }
|
|
.gf-input-error:focus { box-shadow: 0 0 0 3px var(--gf-error-bg); }
|
|
.gf-helper {
|
|
font-size: 0.75rem;
|
|
color: var(--gf-gray-500);
|
|
margin-top: var(--gf-space-1);
|
|
}
|
|
.gf-helper-error { color: var(--gf-error); }
|
|
textarea.gf-input { min-height: 100px; resize: vertical; }
|
|
|
|
/* --- Cards --- */
|
|
.gf-card {
|
|
background: var(--gf-bg);
|
|
border-radius: var(--gf-radius-xl);
|
|
box-shadow: var(--gf-shadow-card);
|
|
border: 1px solid var(--gf-gray-200);
|
|
overflow: hidden;
|
|
transition: box-shadow 0.2s ease, transform 0.2s ease;
|
|
}
|
|
.gf-card:hover {
|
|
box-shadow: var(--gf-shadow-md);
|
|
transform: translateY(-1px);
|
|
}
|
|
.gf-card-img {
|
|
width: 100%;
|
|
height: 180px;
|
|
object-fit: cover;
|
|
background: var(--gf-gray-100);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: var(--gf-gray-400);
|
|
font-size: 2rem;
|
|
}
|
|
.gf-card-body {
|
|
padding: var(--gf-space-5);
|
|
}
|
|
.gf-card-title {
|
|
font-family: var(--gf-font-heading);
|
|
font-weight: 700;
|
|
font-size: 1.125rem;
|
|
color: var(--gf-gray-900);
|
|
margin-bottom: var(--gf-space-1);
|
|
}
|
|
.gf-card-subtitle {
|
|
font-size: 0.813rem;
|
|
color: var(--gf-gray-500);
|
|
margin-bottom: var(--gf-space-3);
|
|
}
|
|
.gf-card-text {
|
|
font-size: 0.875rem;
|
|
color: var(--gf-gray-600);
|
|
line-height: 1.5;
|
|
}
|
|
.gf-card-footer {
|
|
padding: var(--gf-space-3) var(--gf-space-5);
|
|
border-top: 1px solid var(--gf-gray-100);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
/* --- Meal Card (Domain-Specific) --- */
|
|
.gf-meal-card { position: relative; }
|
|
.gf-meal-badge {
|
|
position: absolute;
|
|
top: var(--gf-space-3);
|
|
right: var(--gf-space-3);
|
|
font-size: 0.688rem;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.05em;
|
|
padding: 0.25rem 0.625rem;
|
|
border-radius: var(--gf-radius-full);
|
|
z-index: 1;
|
|
}
|
|
.gf-badge-available { background: var(--gf-success); color: white; }
|
|
.gf-badge-traded { background: var(--gf-gray-400); color: white; }
|
|
.gf-badge-pending { background: var(--gf-accent); color: var(--gf-gray-900); }
|
|
.gf-meal-meta {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--gf-space-2);
|
|
font-size: 0.813rem;
|
|
color: var(--gf-gray-500);
|
|
margin-bottom: var(--gf-space-3);
|
|
}
|
|
.gf-meal-meta svg { width: 16px; height: 16px; }
|
|
|
|
/* --- Tags --- */
|
|
.gf-tag {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
padding: 0.188rem 0.625rem;
|
|
border-radius: var(--gf-radius-full);
|
|
gap: 0.25rem;
|
|
}
|
|
.gf-tag-primary { background: var(--gf-primary-bg); color: var(--gf-primary-dark); }
|
|
.gf-tag-secondary { background: var(--gf-secondary-bg); color: var(--gf-secondary-dark); }
|
|
.gf-tag-accent { background: var(--gf-accent-bg); color: var(--gf-accent-dark); }
|
|
.gf-tag-neutral { background: var(--gf-gray-100); color: var(--gf-gray-600); }
|
|
|
|
/* --- Avatar --- */
|
|
.gf-avatar {
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: var(--gf-radius-full);
|
|
background: var(--gf-primary-bg);
|
|
color: var(--gf-primary);
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-weight: 700;
|
|
font-size: 0.875rem;
|
|
flex-shrink: 0;
|
|
}
|
|
.gf-avatar-sm { width: 32px; height: 32px; font-size: 0.75rem; }
|
|
.gf-avatar-lg { width: 56px; height: 56px; font-size: 1.25rem; }
|
|
|
|
/* --- Alerts / Toasts --- */
|
|
.gf-alert {
|
|
padding: var(--gf-space-3) var(--gf-space-4);
|
|
border-radius: var(--gf-radius-md);
|
|
font-size: 0.875rem;
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: var(--gf-space-3);
|
|
margin-bottom: var(--gf-space-4);
|
|
border-left: 4px solid;
|
|
}
|
|
.gf-alert-success { background: var(--gf-success-bg); border-color: var(--gf-success); color: #1B6B3A; }
|
|
.gf-alert-error { background: var(--gf-error-bg); border-color: var(--gf-error); color: #922B21; }
|
|
.gf-alert-warning { background: var(--gf-warning-bg); border-color: var(--gf-warning); color: #7D6608; }
|
|
.gf-alert-info { background: var(--gf-info-bg); border-color: var(--gf-info); color: #1A5276; }
|
|
|
|
/* --- Navigation --- */
|
|
.gf-nav {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: var(--gf-space-3) var(--gf-space-6);
|
|
background: var(--gf-bg);
|
|
border-bottom: 1px solid var(--gf-gray-200);
|
|
}
|
|
.gf-nav-brand {
|
|
font-family: var(--gf-font-heading);
|
|
font-weight: 800;
|
|
font-size: 1.375rem;
|
|
color: var(--gf-primary);
|
|
text-decoration: none;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
.gf-nav-links {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--gf-space-1);
|
|
list-style: none;
|
|
}
|
|
.gf-nav-link {
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
color: var(--gf-gray-600);
|
|
text-decoration: none;
|
|
padding: var(--gf-space-2) var(--gf-space-3);
|
|
border-radius: var(--gf-radius-md);
|
|
transition: all 0.15s ease;
|
|
}
|
|
.gf-nav-link:hover { color: var(--gf-gray-900); background: var(--gf-gray-100); }
|
|
.gf-nav-link-active { color: var(--gf-primary); background: var(--gf-primary-bg); }
|
|
|
|
/* --- Mobile Bottom Tab Bar --- */
|
|
.gf-tab-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-around;
|
|
background: var(--gf-bg);
|
|
border-top: 1px solid var(--gf-gray-200);
|
|
padding: var(--gf-space-2) 0 var(--gf-space-3);
|
|
max-width: 390px;
|
|
margin: 0 auto;
|
|
}
|
|
.gf-tab-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 2px;
|
|
font-size: 0.625rem;
|
|
font-weight: 600;
|
|
color: var(--gf-gray-400);
|
|
text-decoration: none;
|
|
padding: var(--gf-space-1) var(--gf-space-2);
|
|
}
|
|
.gf-tab-item svg { width: 24px; height: 24px; }
|
|
.gf-tab-item-active { color: var(--gf-primary); }
|
|
|
|
/* --- Spacing Demo --- */
|
|
.ds-spacing-bar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--gf-space-4);
|
|
margin-bottom: var(--gf-space-3);
|
|
}
|
|
.ds-spacing-bar .bar {
|
|
height: 24px;
|
|
background: var(--gf-primary);
|
|
border-radius: var(--gf-radius-sm);
|
|
opacity: 0.7;
|
|
}
|
|
.ds-spacing-bar code {
|
|
font-size: 0.75rem;
|
|
color: var(--gf-gray-500);
|
|
width: 120px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* --- Utility classes --- */
|
|
.flex { display: flex; }
|
|
.flex-wrap { flex-wrap: wrap; }
|
|
.gap-2 { gap: var(--gf-space-2); }
|
|
.gap-3 { gap: var(--gf-space-3); }
|
|
.gap-4 { gap: var(--gf-space-4); }
|
|
.mb-2 { margin-bottom: var(--gf-space-2); }
|
|
.mb-4 { margin-bottom: var(--gf-space-4); }
|
|
.mb-6 { margin-bottom: var(--gf-space-6); }
|
|
.text-center { text-align: center; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<!-- ======== HEADER ======== -->
|
|
<div class="ds-header">
|
|
<h1>
|
|
<span class="ds-logo-mark">
|
|
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
<rect width="40" height="40" rx="10" fill="rgba(255,255,255,0.2)"/>
|
|
<path d="M12 26 L20 14 L28 26" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
|
<path d="M14 22 L26 22" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
|
<circle cx="20" cy="12" r="2.5" fill="white"/>
|
|
</svg>
|
|
Grubflip
|
|
</span>
|
|
</h1>
|
|
<p>Design System v1.0 — Brand, Components & Guidelines</p>
|
|
<p style="font-size:0.813rem; opacity:0.7; margin-top:0.5rem;">Created by Ava · March 25, 2026</p>
|
|
</div>
|
|
|
|
<div class="ds-container">
|
|
|
|
<!-- ======== BRAND IDENTITY ======== -->
|
|
<section class="ds-section">
|
|
<h2 class="ds-section-title">Brand Identity</h2>
|
|
<p class="ds-section-desc">
|
|
Grubflip is meal trading for restaurant workers. The brand should feel <strong>warm</strong>, <strong>energetic</strong>, and <strong>peer-to-peer</strong>.
|
|
Think food truck meets modern fintech. Approachable and fun, but trustworthy enough to handle trades.
|
|
</p>
|
|
<div style="background: var(--gf-gray-50); border-radius: var(--gf-radius-xl); padding: var(--gf-space-8); text-align: center; margin-bottom: var(--gf-space-6);">
|
|
<div style="font-family: var(--gf-font-heading); font-weight: 800; font-size: 3.5rem; letter-spacing: -0.03em; color: var(--gf-primary); margin-bottom: var(--gf-space-2);">Grubflip</div>
|
|
<div style="font-family: var(--gf-font-body); font-weight: 500; font-size: 1rem; color: var(--gf-gray-500); letter-spacing: 0.15em; text-transform: uppercase;">Swap meals. Skip the line.</div>
|
|
</div>
|
|
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--gf-space-4);">
|
|
<div style="padding: var(--gf-space-4); border: 1px solid var(--gf-gray-200); border-radius: var(--gf-radius-lg);">
|
|
<strong style="font-size:0.813rem; color: var(--gf-gray-400); text-transform: uppercase; letter-spacing: 0.05em;">Voice</strong>
|
|
<p style="font-size:0.938rem; margin-top: 0.5rem;">Casual, friendly, a little playful. We're kitchen people, not corporate.</p>
|
|
</div>
|
|
<div style="padding: var(--gf-space-4); border: 1px solid var(--gf-gray-200); border-radius: var(--gf-radius-lg);">
|
|
<strong style="font-size:0.813rem; color: var(--gf-gray-400); text-transform: uppercase; letter-spacing: 0.05em;">Feel</strong>
|
|
<p style="font-size:0.938rem; margin-top: 0.5rem;">Warm but clean. More farmer's market than fast food. Fresh, trusted, community.</p>
|
|
</div>
|
|
<div style="padding: var(--gf-space-4); border: 1px solid var(--gf-gray-200); border-radius: var(--gf-radius-lg);">
|
|
<strong style="font-size:0.813rem; color: var(--gf-gray-400); text-transform: uppercase; letter-spacing: 0.05em;">Not</strong>
|
|
<p style="font-size:0.938rem; margin-top: 0.5rem;">Not stuffy. Not corporate. Not cluttered. Not another food delivery app aesthetic.</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ======== COLORS ======== -->
|
|
<section class="ds-section">
|
|
<h2 class="ds-section-title">Color Palette</h2>
|
|
<p class="ds-section-desc">Three-color system: warm orange for action/CTA, deep green for trust/balance, golden yellow for highlights and rewards.</p>
|
|
|
|
<h3 style="font-size:0.875rem; font-weight:700; color: var(--gf-gray-700); margin-bottom: var(--gf-space-4); text-transform: uppercase; letter-spacing: 0.05em;">Core Colors</h3>
|
|
<div class="ds-color-grid mb-6">
|
|
<!-- Primary -->
|
|
<div class="ds-color-card">
|
|
<div class="ds-color-swatch" style="background: var(--gf-primary);">
|
|
<span class="light-text">#FF6B35</span>
|
|
</div>
|
|
<div class="ds-color-variants">
|
|
<div style="background: var(--gf-primary-dark);" title="#D94E1F"></div>
|
|
<div style="background: var(--gf-primary);" title="#FF6B35"></div>
|
|
<div style="background: var(--gf-primary-light);" title="#FF8F66"></div>
|
|
<div style="background: var(--gf-primary-bg);" title="#FFF3ED"></div>
|
|
</div>
|
|
<div class="ds-color-meta">
|
|
<strong>Primary — Warm Orange</strong>
|
|
<code>--gf-primary: #FF6B35</code>
|
|
</div>
|
|
</div>
|
|
<!-- Secondary -->
|
|
<div class="ds-color-card">
|
|
<div class="ds-color-swatch" style="background: var(--gf-secondary);">
|
|
<span class="light-text">#2D6A4F</span>
|
|
</div>
|
|
<div class="ds-color-variants">
|
|
<div style="background: var(--gf-secondary-dark);" title="#1B4332"></div>
|
|
<div style="background: var(--gf-secondary);" title="#2D6A4F"></div>
|
|
<div style="background: var(--gf-secondary-light);" title="#40916C"></div>
|
|
<div style="background: var(--gf-secondary-bg);" title="#EDF5F0"></div>
|
|
</div>
|
|
<div class="ds-color-meta">
|
|
<strong>Secondary — Deep Green</strong>
|
|
<code>--gf-secondary: #2D6A4F</code>
|
|
</div>
|
|
</div>
|
|
<!-- Accent -->
|
|
<div class="ds-color-card">
|
|
<div class="ds-color-swatch" style="background: var(--gf-accent);">
|
|
<span class="dark-text">#FFBA08</span>
|
|
</div>
|
|
<div class="ds-color-variants">
|
|
<div style="background: var(--gf-accent-dark);" title="#E0A100"></div>
|
|
<div style="background: var(--gf-accent);" title="#FFBA08"></div>
|
|
<div style="background: var(--gf-accent-light);" title="#FFD166"></div>
|
|
<div style="background: var(--gf-accent-bg);" title="#FFF8E1"></div>
|
|
</div>
|
|
<div class="ds-color-meta">
|
|
<strong>Accent — Golden Yellow</strong>
|
|
<code>--gf-accent: #FFBA08</code>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 style="font-size:0.875rem; font-weight:700; color: var(--gf-gray-700); margin-bottom: var(--gf-space-4); text-transform: uppercase; letter-spacing: 0.05em;">Semantic Colors</h3>
|
|
<div class="ds-color-grid mb-6">
|
|
<div class="ds-color-card">
|
|
<div class="ds-color-swatch" style="background: var(--gf-success);"><span class="light-text">Success</span></div>
|
|
<div class="ds-color-meta"><strong>Success</strong><code>#2ECC71</code></div>
|
|
</div>
|
|
<div class="ds-color-card">
|
|
<div class="ds-color-swatch" style="background: var(--gf-warning);"><span class="light-text">Warning</span></div>
|
|
<div class="ds-color-meta"><strong>Warning</strong><code>#F39C12</code></div>
|
|
</div>
|
|
<div class="ds-color-card">
|
|
<div class="ds-color-swatch" style="background: var(--gf-error);"><span class="light-text">Error</span></div>
|
|
<div class="ds-color-meta"><strong>Error</strong><code>#E74C3C</code></div>
|
|
</div>
|
|
<div class="ds-color-card">
|
|
<div class="ds-color-swatch" style="background: var(--gf-info);"><span class="light-text">Info</span></div>
|
|
<div class="ds-color-meta"><strong>Info</strong><code>#3498DB</code></div>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 style="font-size:0.875rem; font-weight:700; color: var(--gf-gray-700); margin-bottom: var(--gf-space-4); text-transform: uppercase; letter-spacing: 0.05em;">Neutral Scale</h3>
|
|
<div class="ds-neutral-strip">
|
|
<div class="ds-neutral-chip" style="background: var(--gf-gray-50); color: var(--gf-gray-400);">50</div>
|
|
<div class="ds-neutral-chip" style="background: var(--gf-gray-100); color: var(--gf-gray-400);">100</div>
|
|
<div class="ds-neutral-chip" style="background: var(--gf-gray-200); color: var(--gf-gray-500);">200</div>
|
|
<div class="ds-neutral-chip" style="background: var(--gf-gray-300); color: var(--gf-gray-600);">300</div>
|
|
<div class="ds-neutral-chip" style="background: var(--gf-gray-400); color: white;">400</div>
|
|
<div class="ds-neutral-chip" style="background: var(--gf-gray-500); color: white;">500</div>
|
|
<div class="ds-neutral-chip" style="background: var(--gf-gray-600); color: white;">600</div>
|
|
<div class="ds-neutral-chip" style="background: var(--gf-gray-700); color: white;">700</div>
|
|
<div class="ds-neutral-chip" style="background: var(--gf-gray-800); color: white;">800</div>
|
|
<div class="ds-neutral-chip" style="background: var(--gf-gray-900); color: white;">900</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ======== TYPOGRAPHY ======== -->
|
|
<section class="ds-section">
|
|
<h2 class="ds-section-title">Typography</h2>
|
|
<p class="ds-section-desc">
|
|
Headings: <strong>Plus Jakarta Sans</strong> (geometric, warm, modern).
|
|
Body: <strong>Inter</strong> (clean, highly legible, great for UI).
|
|
Both free via Google Fonts.
|
|
</p>
|
|
|
|
<div class="ds-type-sample">
|
|
<div class="ds-type-label">Display / Hero — 3rem / 800</div>
|
|
<div style="font-family: var(--gf-font-heading); font-size: 3rem; font-weight: 800; letter-spacing: -0.03em; color: var(--gf-gray-900); line-height: 1.1;">
|
|
Swap meals with your crew
|
|
</div>
|
|
<div class="ds-type-meta">Plus Jakarta Sans · 48px · Extra Bold · -0.03em tracking</div>
|
|
</div>
|
|
|
|
<div class="ds-type-sample">
|
|
<div class="ds-type-label">H1 — 2.25rem / 700</div>
|
|
<div style="font-family: var(--gf-font-heading); font-size: 2.25rem; font-weight: 700; letter-spacing: -0.02em; color: var(--gf-gray-900); line-height: 1.2;">
|
|
Today's available meals
|
|
</div>
|
|
<div class="ds-type-meta">Plus Jakarta Sans · 36px · Bold</div>
|
|
</div>
|
|
|
|
<div class="ds-type-sample">
|
|
<div class="ds-type-label">H2 — 1.5rem / 700</div>
|
|
<div style="font-family: var(--gf-font-heading); font-size: 1.5rem; font-weight: 700; color: var(--gf-gray-900); line-height: 1.3;">
|
|
Your active trades
|
|
</div>
|
|
<div class="ds-type-meta">Plus Jakarta Sans · 24px · Bold</div>
|
|
</div>
|
|
|
|
<div class="ds-type-sample">
|
|
<div class="ds-type-label">H3 — 1.125rem / 600</div>
|
|
<div style="font-family: var(--gf-font-heading); font-size: 1.125rem; font-weight: 600; color: var(--gf-gray-900); line-height: 1.4;">
|
|
Grilled chicken bowl — posted 2h ago
|
|
</div>
|
|
<div class="ds-type-meta">Plus Jakarta Sans · 18px · Semibold</div>
|
|
</div>
|
|
|
|
<div class="ds-type-sample">
|
|
<div class="ds-type-label">Body — 1rem / 400</div>
|
|
<div style="font-family: var(--gf-font-body); font-size: 1rem; font-weight: 400; color: var(--gf-gray-700); line-height: 1.6;">
|
|
Post your staff meal, browse what others have, and flip trades with people at nearby restaurants. No money changes hands — just good food swapping between kitchen workers who get it.
|
|
</div>
|
|
<div class="ds-type-meta">Inter · 16px · Regular · 1.6 line-height</div>
|
|
</div>
|
|
|
|
<div class="ds-type-sample">
|
|
<div class="ds-type-label">Small / Caption — 0.813rem / 500</div>
|
|
<div style="font-family: var(--gf-font-body); font-size: 0.813rem; font-weight: 500; color: var(--gf-gray-500); line-height: 1.4;">
|
|
Posted by Marcus K. · 0.3 mi away · Expires in 4h
|
|
</div>
|
|
<div class="ds-type-meta">Inter · 13px · Medium</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ======== SPACING ======== -->
|
|
<section class="ds-section">
|
|
<h2 class="ds-section-title">Spacing Scale</h2>
|
|
<p class="ds-section-desc">4px base unit. Consistent spacing creates rhythm and polish across all screens.</p>
|
|
|
|
<div class="ds-spacing-bar"><code>--gf-space-1 (4px)</code><div class="bar" style="width: 4px;"></div></div>
|
|
<div class="ds-spacing-bar"><code>--gf-space-2 (8px)</code><div class="bar" style="width: 8px;"></div></div>
|
|
<div class="ds-spacing-bar"><code>--gf-space-3 (12px)</code><div class="bar" style="width: 12px;"></div></div>
|
|
<div class="ds-spacing-bar"><code>--gf-space-4 (16px)</code><div class="bar" style="width: 16px;"></div></div>
|
|
<div class="ds-spacing-bar"><code>--gf-space-6 (24px)</code><div class="bar" style="width: 24px;"></div></div>
|
|
<div class="ds-spacing-bar"><code>--gf-space-8 (32px)</code><div class="bar" style="width: 32px;"></div></div>
|
|
<div class="ds-spacing-bar"><code>--gf-space-10 (40px)</code><div class="bar" style="width: 40px;"></div></div>
|
|
<div class="ds-spacing-bar"><code>--gf-space-12 (48px)</code><div class="bar" style="width: 48px;"></div></div>
|
|
<div class="ds-spacing-bar"><code>--gf-space-16 (64px)</code><div class="bar" style="width: 64px;"></div></div>
|
|
<div class="ds-spacing-bar"><code>--gf-space-20 (80px)</code><div class="bar" style="width: 80px;"></div></div>
|
|
</section>
|
|
|
|
<!-- ======== BUTTONS ======== -->
|
|
<section class="ds-section">
|
|
<h2 class="ds-section-title">Buttons</h2>
|
|
<p class="ds-section-desc">Rounded corners (0.75rem), bold weight. Primary orange for main CTAs, green for confirmations, outline for secondary actions.</p>
|
|
|
|
<div class="ds-component-grid">
|
|
<div class="ds-component-card">
|
|
<div class="ds-component-label">Variants</div>
|
|
<div class="flex flex-wrap gap-3">
|
|
<button class="gf-btn gf-btn-primary">Post Meal</button>
|
|
<button class="gf-btn gf-btn-secondary">Confirm Trade</button>
|
|
<button class="gf-btn gf-btn-outline">View Details</button>
|
|
<button class="gf-btn gf-btn-ghost">Cancel</button>
|
|
</div>
|
|
</div>
|
|
<div class="ds-component-card">
|
|
<div class="ds-component-label">Sizes</div>
|
|
<div class="flex flex-wrap gap-3" style="align-items: center;">
|
|
<button class="gf-btn gf-btn-primary gf-btn-sm">Small</button>
|
|
<button class="gf-btn gf-btn-primary">Default</button>
|
|
<button class="gf-btn gf-btn-primary gf-btn-lg">Large CTA</button>
|
|
</div>
|
|
</div>
|
|
<div class="ds-component-card">
|
|
<div class="ds-component-label">States</div>
|
|
<div class="flex flex-wrap gap-3">
|
|
<button class="gf-btn gf-btn-primary">Normal</button>
|
|
<button class="gf-btn gf-btn-primary" disabled>Disabled</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ======== FORM INPUTS ======== -->
|
|
<section class="ds-section">
|
|
<h2 class="ds-section-title">Form Inputs</h2>
|
|
<p class="ds-section-desc">Clean, spacious inputs. Orange focus ring to match primary brand. Error state uses red with tinted background.</p>
|
|
|
|
<div class="ds-component-grid">
|
|
<div class="ds-component-card">
|
|
<div class="ds-component-label">Text Input</div>
|
|
<div class="gf-input-group">
|
|
<label class="gf-label">Meal name</label>
|
|
<input type="text" class="gf-input" placeholder="e.g. Grilled chicken bowl">
|
|
<div class="gf-helper">What did you make today?</div>
|
|
</div>
|
|
<div class="gf-input-group">
|
|
<label class="gf-label">Description</label>
|
|
<textarea class="gf-input" placeholder="Add details about your meal..."></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="ds-component-card">
|
|
<div class="ds-component-label">Error State</div>
|
|
<div class="gf-input-group">
|
|
<label class="gf-label">Meal name</label>
|
|
<input type="text" class="gf-input gf-input-error" value="">
|
|
<div class="gf-helper gf-helper-error">Meal name is required</div>
|
|
</div>
|
|
<div class="gf-input-group">
|
|
<label class="gf-label">Location</label>
|
|
<input type="text" class="gf-input" placeholder="Restaurant or area" value="Downtown Kitchen">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ======== CARDS ======== -->
|
|
<section class="ds-section">
|
|
<h2 class="ds-section-title">Cards</h2>
|
|
<p class="ds-section-desc">Cards are the primary content container. Meal cards are the hero component — they need to look appetizing and scannable.</p>
|
|
|
|
<div class="ds-component-grid">
|
|
<!-- Meal Card: Available -->
|
|
<div class="gf-card gf-meal-card">
|
|
<div class="gf-meal-badge gf-badge-available">Available</div>
|
|
<div class="gf-card-img" style="background: linear-gradient(135deg, #FFF3ED, #FFE0CC); font-size: 3rem;">
|
|
<span aria-hidden="true" style="filter: saturate(0.8);">🍙</span>
|
|
</div>
|
|
<div class="gf-card-body">
|
|
<div class="gf-card-title">Grilled Chicken Bowl</div>
|
|
<div class="gf-meal-meta">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
|
|
<span>Posted 2h ago</span>
|
|
<span>·</span>
|
|
<span>0.3 mi away</span>
|
|
</div>
|
|
<div class="flex gap-2 mb-4">
|
|
<span class="gf-tag gf-tag-secondary">Gluten-free</span>
|
|
<span class="gf-tag gf-tag-primary">High protein</span>
|
|
</div>
|
|
<div class="gf-card-text">Rice, grilled chicken, roasted veggies, chimichurri. Made fresh tonight — staff meal from the dinner service.</div>
|
|
</div>
|
|
<div class="gf-card-footer">
|
|
<div style="display: flex; align-items: center; gap: 0.5rem;">
|
|
<div class="gf-avatar gf-avatar-sm">MK</div>
|
|
<span style="font-size: 0.813rem; font-weight: 500; color: var(--gf-gray-600);">Marcus K.</span>
|
|
</div>
|
|
<button class="gf-btn gf-btn-primary gf-btn-sm">Offer Trade</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Meal Card: Pending -->
|
|
<div class="gf-card gf-meal-card">
|
|
<div class="gf-meal-badge gf-badge-pending">Pending</div>
|
|
<div class="gf-card-img" style="background: linear-gradient(135deg, #EDF5F0, #D1E8D5); font-size: 3rem;">
|
|
<span aria-hidden="true">🍣</span>
|
|
</div>
|
|
<div class="gf-card-body">
|
|
<div class="gf-card-title">Spicy Pork Tacos (x3)</div>
|
|
<div class="gf-meal-meta">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
|
|
<span>Posted 45m ago</span>
|
|
<span>·</span>
|
|
<span>0.1 mi away</span>
|
|
</div>
|
|
<div class="flex gap-2 mb-4">
|
|
<span class="gf-tag gf-tag-accent">Spicy</span>
|
|
<span class="gf-tag gf-tag-neutral">Pork</span>
|
|
</div>
|
|
<div class="gf-card-text">Three tacos with house-made salsa verde, pickled onions, and cotija. Corn tortillas from this morning.</div>
|
|
</div>
|
|
<div class="gf-card-footer">
|
|
<div style="display: flex; align-items: center; gap: 0.5rem;">
|
|
<div class="gf-avatar gf-avatar-sm" style="background: var(--gf-secondary-bg); color: var(--gf-secondary);">JR</div>
|
|
<span style="font-size: 0.813rem; font-weight: 500; color: var(--gf-gray-600);">Jamie R.</span>
|
|
</div>
|
|
<button class="gf-btn gf-btn-outline gf-btn-sm">Trade Pending...</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Generic Card -->
|
|
<div class="gf-card">
|
|
<div class="gf-card-body">
|
|
<div class="gf-card-title">Generic Content Card</div>
|
|
<div class="gf-card-subtitle">For non-meal content: profiles, settings, info</div>
|
|
<div class="gf-card-text">
|
|
Use this base card style for any boxed content that isn't a meal listing. Same radius, shadow, and hover treatment — just no image or badge.
|
|
</div>
|
|
</div>
|
|
<div class="gf-card-footer">
|
|
<button class="gf-btn gf-btn-ghost gf-btn-sm">Learn More</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ======== TAGS ======== -->
|
|
<section class="ds-section">
|
|
<h2 class="ds-section-title">Tags & Badges</h2>
|
|
<p class="ds-section-desc">Use tags for dietary info, cuisine type, and meal attributes. Pill-shaped, tinted backgrounds.</p>
|
|
<div class="flex flex-wrap gap-3">
|
|
<span class="gf-tag gf-tag-primary">High protein</span>
|
|
<span class="gf-tag gf-tag-secondary">Vegetarian</span>
|
|
<span class="gf-tag gf-tag-secondary">Gluten-free</span>
|
|
<span class="gf-tag gf-tag-accent">Spicy</span>
|
|
<span class="gf-tag gf-tag-neutral">Pork</span>
|
|
<span class="gf-tag gf-tag-neutral">Seafood</span>
|
|
<span class="gf-tag gf-tag-primary">Vegan</span>
|
|
<span class="gf-tag gf-tag-accent">Chef's Pick</span>
|
|
<span class="gf-tag gf-tag-neutral">Dairy-free</span>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ======== ALERTS ======== -->
|
|
<section class="ds-section">
|
|
<h2 class="ds-section-title">Alerts</h2>
|
|
<p class="ds-section-desc">Contextual feedback. Left border accent for quick scanning.</p>
|
|
|
|
<div class="gf-alert gf-alert-success">
|
|
<strong>Trade confirmed!</strong> Meet Marcus at Blue Line Kitchen in 30 minutes.
|
|
</div>
|
|
<div class="gf-alert gf-alert-info">
|
|
<strong>New match:</strong> Someone nearby wants to trade for your chicken bowl.
|
|
</div>
|
|
<div class="gf-alert gf-alert-warning">
|
|
<strong>Heads up:</strong> Your posted meal expires in 1 hour.
|
|
</div>
|
|
<div class="gf-alert gf-alert-error">
|
|
<strong>Trade cancelled.</strong> The other person withdrew their offer.
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ======== AVATARS ======== -->
|
|
<section class="ds-section">
|
|
<h2 class="ds-section-title">Avatars</h2>
|
|
<p class="ds-section-desc">Initials-based by default. Three sizes for different contexts.</p>
|
|
<div class="flex gap-4" style="align-items: center;">
|
|
<div class="gf-avatar gf-avatar-sm">A</div>
|
|
<div class="gf-avatar">MK</div>
|
|
<div class="gf-avatar gf-avatar-lg" style="background: var(--gf-secondary-bg); color: var(--gf-secondary);">JR</div>
|
|
<div class="gf-avatar gf-avatar-lg" style="background: var(--gf-accent-bg); color: var(--gf-accent-dark);">TS</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ======== NAVIGATION ======== -->
|
|
<section class="ds-section">
|
|
<h2 class="ds-section-title">Navigation</h2>
|
|
<p class="ds-section-desc">Desktop top bar + mobile bottom tab bar. Keep it minimal — Grubflip has only a few core screens.</p>
|
|
|
|
<!-- Desktop Nav -->
|
|
<div style="border: 1px solid var(--gf-gray-200); border-radius: var(--gf-radius-lg); overflow: hidden; margin-bottom: var(--gf-space-6);">
|
|
<div class="ds-component-label" style="padding: var(--gf-space-3) var(--gf-space-4); background: var(--gf-gray-50); border-bottom: 1px solid var(--gf-gray-200);">Desktop Nav Bar</div>
|
|
<nav class="gf-nav">
|
|
<a href="#" class="gf-nav-brand">Grubflip</a>
|
|
<ul class="gf-nav-links">
|
|
<li><a href="#" class="gf-nav-link gf-nav-link-active">Feed</a></li>
|
|
<li><a href="#" class="gf-nav-link">My Trades</a></li>
|
|
<li><a href="#" class="gf-nav-link">Post Meal</a></li>
|
|
<li><a href="#" class="gf-nav-link">Messages</a></li>
|
|
</ul>
|
|
<div class="gf-avatar gf-avatar-sm">AV</div>
|
|
</nav>
|
|
</div>
|
|
|
|
<!-- Mobile Tab Bar -->
|
|
<div style="border: 1px solid var(--gf-gray-200); border-radius: var(--gf-radius-lg); overflow: hidden;">
|
|
<div class="ds-component-label" style="padding: var(--gf-space-3) var(--gf-space-4); background: var(--gf-gray-50); border-bottom: 1px solid var(--gf-gray-200);">Mobile Tab Bar (390px)</div>
|
|
<div class="gf-tab-bar">
|
|
<a href="#" class="gf-tab-item gf-tab-item-active">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/></svg>
|
|
Feed
|
|
</a>
|
|
<a href="#" class="gf-tab-item">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M17 1l4 4-4 4"/><path d="M3 11V9a4 4 0 014-4h14"/><path d="M7 23l-4-4 4-4"/><path d="M21 13v2a4 4 0 01-4 4H3"/></svg>
|
|
Trades
|
|
</a>
|
|
<a href="#" class="gf-tab-item" style="color: var(--gf-primary);">
|
|
<svg viewBox="0 0 24 24" fill="currentColor" stroke="none"><rect x="2" y="2" width="20" height="20" rx="10"/><path d="M12 7v10M7 12h10" stroke="white" stroke-width="2.5" stroke-linecap="round"/></svg>
|
|
Post
|
|
</a>
|
|
<a href="#" class="gf-tab-item">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/></svg>
|
|
Chat
|
|
</a>
|
|
<a href="#" class="gf-tab-item">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
|
Profile
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ======== DESIGN GUIDELINES ======== -->
|
|
<section class="ds-section">
|
|
<h2 class="ds-section-title">Design Guidelines</h2>
|
|
<p class="ds-section-desc">Rules of the road for anyone building Grubflip UI.</p>
|
|
|
|
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: var(--gf-space-4);">
|
|
<div style="padding: var(--gf-space-5); background: var(--gf-success-bg); border-radius: var(--gf-radius-lg); border: 1px solid #B7E4C7;">
|
|
<strong style="color: #1B6B3A; font-size: 0.938rem;">DO</strong>
|
|
<ul style="margin-top: 0.5rem; font-size: 0.875rem; color: #1B6B3A; padding-left: 1.25rem;">
|
|
<li>Use generous whitespace between cards</li>
|
|
<li>Keep meal images or emoji large and appetizing</li>
|
|
<li>Use orange for primary CTAs only</li>
|
|
<li>Use green for confirmation/success states</li>
|
|
<li>Round corners (0.75rem+) for friendly feel</li>
|
|
<li>Mobile-first — design 390px screens first</li>
|
|
</ul>
|
|
</div>
|
|
<div style="padding: var(--gf-space-5); background: var(--gf-error-bg); border-radius: var(--gf-radius-lg); border: 1px solid #F5C6CB;">
|
|
<strong style="color: #922B21; font-size: 0.938rem;">DON'T</strong>
|
|
<ul style="margin-top: 0.5rem; font-size: 0.875rem; color: #922B21; padding-left: 1.25rem;">
|
|
<li>Use red/orange for non-interactive elements</li>
|
|
<li>Cram content — this isn't a data dashboard</li>
|
|
<li>Use more than 2 font weights per section</li>
|
|
<li>Mix Payfrit teal with Grubflip orange</li>
|
|
<li>Hard shadows — keep everything soft</li>
|
|
<li>Tiny text — minimum 13px for body copy</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ======== TOKEN REFERENCE ======== -->
|
|
<section class="ds-section">
|
|
<h2 class="ds-section-title">Token Reference</h2>
|
|
<p class="ds-section-desc">All CSS custom properties use the <code>--gf-</code> prefix. JSON tokens available at <code>brand-tokens.json</code> for native app integration.</p>
|
|
<div style="background: var(--gf-gray-900); color: #E5E5E5; padding: var(--gf-space-5); border-radius: var(--gf-radius-lg); font-family: 'JetBrains Mono', monospace; font-size: 0.813rem; line-height: 1.8; overflow-x: auto;">
|
|
<span style="color: #A3A3A3;">/* Import in your CSS */</span><br>
|
|
<span style="color: #FF8F66;">--gf-primary:</span> #FF6B35;<br>
|
|
<span style="color: #FF8F66;">--gf-secondary:</span> #2D6A4F;<br>
|
|
<span style="color: #FF8F66;">--gf-accent:</span> #FFBA08;<br>
|
|
<span style="color: #FF8F66;">--gf-font-heading:</span> 'Plus Jakarta Sans';<br>
|
|
<span style="color: #FF8F66;">--gf-font-body:</span> 'Inter';<br>
|
|
<br>
|
|
<span style="color: #A3A3A3;">/* Kotlin/Swift: use brand-tokens.json */</span><br>
|
|
<span style="color: #A3A3A3;">/* colors.primary.base → #FF6B35 */</span><br>
|
|
<span style="color: #A3A3A3;">/* colors.secondary.base → #2D6A4F */</span>
|
|
</div>
|
|
</section>
|
|
|
|
</div>
|
|
|
|
<!-- Footer -->
|
|
<div style="text-align: center; padding: var(--gf-space-8) var(--gf-space-6); color: var(--gf-gray-400); font-size: 0.813rem; border-top: 1px solid var(--gf-gray-100);">
|
|
Grubflip Design System v1.0 · Ava · March 2026<br>
|
|
Part of the Payfrit product family
|
|
</div>
|
|
|
|
</body>
|
|
</html>
|