- Store hero image as base64 data URI in text column (V023 migration) - Add file upload UI to RecipeForm with FileReader preview - Remove isChildFriendly from RecipeCreateRequest (no form field) - Fix 500 on save: effort values now lowercase, serves/cookTimeMin changed from primitive short to nullable Integer to survive omitted fields - Fix empty categories panel: removed stale tagType=category filter - Group category tags by type with German headings in recipe form - Split SuggestionResponse.SuggestionRecipe (no image) from SlotRecipe - Seed 11 HelloFresh recipes with ingredients, steps and tags (V101) - Add frontend e2e scaffold, specs and dev yml Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1821 lines
80 KiB
HTML
1821 lines
80 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Planner Layout Mockups — 5 Konzepte</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@300;400&family=DM+Sans:wght@400;500;600&family=DM+Mono&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root {
|
||
--color-page: #fafaf7;
|
||
--color-surface: #f5f4ee;
|
||
--color-subtle: #edecea;
|
||
--color-border: #d8d7d0;
|
||
--color-text: #1c1c18;
|
||
--color-text-muted: #6b6a63;
|
||
--green-tint: #e8f5ea;
|
||
--green-light: #aedcb0;
|
||
--green: #3d8c4a;
|
||
--green-dark: #2e6e39;
|
||
--green-deeper: #1e4a26;
|
||
--yellow-tint: #fdf6d8;
|
||
--yellow-light: #f9e08a;
|
||
--yellow: #f2c12e;
|
||
--yellow-dark: #c49610;
|
||
--yellow-text: #8a6800;
|
||
--blue-tint: #e6f1fb;
|
||
--blue: #2d7dd2;
|
||
--blue-dark: #185fa5;
|
||
--purple-tint: #eeedfe;
|
||
--purple: #534ab7;
|
||
--orange-tint: #fef0e6;
|
||
--orange: #e8862a;
|
||
--color-error: #dc4c3e;
|
||
--radius-xs: 2px;
|
||
--radius-sm: 4px;
|
||
--radius-md: 6px;
|
||
--radius-lg: 10px;
|
||
--radius-xl: 16px;
|
||
--shadow-card: 0 1px 3px rgba(28,28,24,.06),0 1px 2px rgba(28,28,24,.04);
|
||
--shadow-raised: 0 4px 12px rgba(28,28,24,.08),0 2px 4px rgba(28,28,24,.04);
|
||
--font-display: 'Fraunces', Georgia, serif;
|
||
--font-sans: 'DM Sans', system-ui, sans-serif;
|
||
--font-mono: 'DM Mono', monospace;
|
||
}
|
||
|
||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||
body {
|
||
font-family: var(--font-sans);
|
||
background: #e8e7e0;
|
||
color: var(--color-text);
|
||
padding: 40px 24px 80px;
|
||
}
|
||
|
||
/* ── Spec chrome ─────────────────────────────────────────────── */
|
||
.spec-page-title {
|
||
font-family: var(--font-sans);
|
||
font-size: 11px;
|
||
font-weight: 500;
|
||
letter-spacing: 0.1em;
|
||
text-transform: uppercase;
|
||
color: var(--color-text-muted);
|
||
margin-bottom: 8px;
|
||
}
|
||
.spec-section-title {
|
||
font-family: var(--font-display);
|
||
font-size: 32px;
|
||
font-weight: 300;
|
||
color: var(--color-text);
|
||
margin-bottom: 6px;
|
||
}
|
||
.spec-section-sub {
|
||
font-family: var(--font-sans);
|
||
font-size: 14px;
|
||
color: var(--color-text-muted);
|
||
margin-bottom: 40px;
|
||
max-width: 680px;
|
||
line-height: 1.6;
|
||
}
|
||
.mockup-card {
|
||
background: var(--color-page);
|
||
border-radius: var(--radius-xl);
|
||
border: 1px solid var(--color-border);
|
||
overflow: hidden;
|
||
margin-bottom: 48px;
|
||
box-shadow: var(--shadow-raised);
|
||
}
|
||
.mockup-label {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 12px;
|
||
padding: 20px 24px 16px;
|
||
border-bottom: 1px solid var(--color-border);
|
||
background: var(--color-surface);
|
||
}
|
||
.mockup-number {
|
||
font-family: var(--font-mono);
|
||
font-size: 11px;
|
||
color: var(--color-text-muted);
|
||
background: var(--color-subtle);
|
||
padding: 2px 7px;
|
||
border-radius: var(--radius-sm);
|
||
flex-shrink: 0;
|
||
}
|
||
.mockup-title {
|
||
font-family: var(--font-display);
|
||
font-size: 18px;
|
||
font-weight: 300;
|
||
color: var(--color-text);
|
||
}
|
||
.mockup-tagline {
|
||
font-family: var(--font-sans);
|
||
font-size: 13px;
|
||
color: var(--color-text-muted);
|
||
margin-left: auto;
|
||
}
|
||
.annotation {
|
||
font-family: var(--font-sans);
|
||
font-size: 11px;
|
||
color: var(--color-text-muted);
|
||
border-left: 2px solid var(--color-border);
|
||
padding: 10px 14px;
|
||
margin: 0 24px 24px;
|
||
line-height: 1.5;
|
||
}
|
||
.annotation strong { color: var(--color-text); font-weight: 500; }
|
||
|
||
/* ── Shared chrome reuse ─────────────────────────────────────── */
|
||
.chrome-topbar {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 12px 20px;
|
||
border-bottom: 1px solid var(--color-border);
|
||
background: var(--color-page);
|
||
}
|
||
.chrome-h1 {
|
||
font-family: var(--font-display);
|
||
font-size: 18px;
|
||
font-weight: 300;
|
||
color: var(--color-text);
|
||
}
|
||
.chrome-weekrange {
|
||
font-family: var(--font-sans);
|
||
font-size: 12px;
|
||
color: var(--color-text-muted);
|
||
margin-left: 4px;
|
||
}
|
||
.chrome-btn {
|
||
height: 32px;
|
||
padding: 0 10px;
|
||
border-radius: var(--radius-md);
|
||
border: 1px solid var(--color-border);
|
||
background: var(--color-page);
|
||
font-family: var(--font-sans);
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
letter-spacing: 0.04em;
|
||
color: var(--color-text);
|
||
cursor: pointer;
|
||
white-space: nowrap;
|
||
}
|
||
.chrome-btn-primary {
|
||
background: var(--green-dark);
|
||
color: white;
|
||
border-color: transparent;
|
||
}
|
||
.chrome-nav-arrow {
|
||
width: 32px;
|
||
height: 32px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
border-radius: var(--radius-md);
|
||
border: 1px solid var(--color-border);
|
||
font-size: 15px;
|
||
color: var(--color-text-muted);
|
||
}
|
||
.chrome-ml-auto { margin-left: auto; }
|
||
|
||
/* ── Score widget atoms ──────────────────────────────────────── */
|
||
.score-big {
|
||
font-family: var(--font-display);
|
||
font-size: 36px;
|
||
font-weight: 300;
|
||
color: var(--color-text);
|
||
line-height: 1;
|
||
}
|
||
.score-denom {
|
||
font-family: var(--font-sans);
|
||
font-size: 12px;
|
||
color: var(--color-text-muted);
|
||
}
|
||
.score-label {
|
||
font-family: var(--font-sans);
|
||
font-size: 11px;
|
||
font-weight: 500;
|
||
letter-spacing: 0.06em;
|
||
text-transform: uppercase;
|
||
color: var(--color-text-muted);
|
||
}
|
||
.progress-bar {
|
||
height: 4px;
|
||
border-radius: 9999px;
|
||
background: var(--yellow-light);
|
||
overflow: hidden;
|
||
margin-top: 6px;
|
||
}
|
||
.progress-fill {
|
||
height: 100%;
|
||
border-radius: 9999px;
|
||
background: var(--yellow);
|
||
}
|
||
.progress-fill-green { background: var(--green); }
|
||
.progress-bar-track { background: var(--color-border); }
|
||
|
||
.sub-score-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
margin-top: 8px;
|
||
}
|
||
.sub-score-label {
|
||
font-family: var(--font-sans);
|
||
font-size: 11px;
|
||
color: var(--color-text-muted);
|
||
width: 88px;
|
||
flex-shrink: 0;
|
||
}
|
||
.sub-score-bar {
|
||
flex: 1;
|
||
height: 3px;
|
||
border-radius: 9999px;
|
||
background: var(--color-border);
|
||
overflow: hidden;
|
||
}
|
||
.sub-score-fill { height: 100%; border-radius: 9999px; }
|
||
.sub-score-val {
|
||
font-family: var(--font-mono);
|
||
font-size: 10px;
|
||
color: var(--color-text-muted);
|
||
width: 20px;
|
||
text-align: right;
|
||
}
|
||
|
||
.effort-row {
|
||
display: flex;
|
||
gap: 3px;
|
||
margin-top: 10px;
|
||
height: 20px;
|
||
border-radius: var(--radius-sm);
|
||
overflow: hidden;
|
||
}
|
||
.effort-seg {
|
||
height: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-family: var(--font-sans);
|
||
font-size: 9px;
|
||
font-weight: 500;
|
||
letter-spacing: 0.02em;
|
||
color: white;
|
||
}
|
||
|
||
.warn-item {
|
||
display: flex;
|
||
gap: 6px;
|
||
font-family: var(--font-sans);
|
||
font-size: 11px;
|
||
color: var(--yellow-text);
|
||
margin-top: 6px;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
/* ── Calendar tile atoms ─────────────────────────────────────── */
|
||
.cal-tile {
|
||
border-radius: var(--radius-md);
|
||
border: 1px solid var(--color-border);
|
||
background: var(--color-surface);
|
||
padding: 8px;
|
||
cursor: pointer;
|
||
transition: box-shadow 0.12s;
|
||
}
|
||
.cal-tile:hover { box-shadow: var(--shadow-raised); }
|
||
.cal-tile-empty {
|
||
border-style: dashed;
|
||
background: transparent;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-direction: column;
|
||
color: var(--color-text-muted);
|
||
}
|
||
.cal-tile-selected {
|
||
border: 2px solid var(--green);
|
||
background: var(--green-tint);
|
||
}
|
||
.cal-tile-today {
|
||
border: 2px solid var(--yellow);
|
||
background: var(--yellow-tint);
|
||
}
|
||
.cal-day-name {
|
||
font-family: var(--font-sans);
|
||
font-size: 9px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.06em;
|
||
color: var(--color-text-muted);
|
||
text-align: center;
|
||
margin-bottom: 4px;
|
||
}
|
||
.cal-day-badge {
|
||
width: 22px;
|
||
height: 22px;
|
||
border-radius: 9999px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-family: var(--font-sans);
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
margin: 0 auto 6px;
|
||
color: var(--color-text);
|
||
}
|
||
.cal-day-badge-today { background: var(--yellow); color: white; }
|
||
.cal-day-badge-selected { background: var(--green-tint); color: var(--green-dark); }
|
||
|
||
.recipe-name-sm {
|
||
font-family: var(--font-display);
|
||
font-size: 12px;
|
||
font-weight: 300;
|
||
color: var(--color-text);
|
||
line-height: 1.3;
|
||
}
|
||
.recipe-meta-sm {
|
||
font-family: var(--font-sans);
|
||
font-size: 10px;
|
||
color: var(--color-text-muted);
|
||
margin-top: 3px;
|
||
}
|
||
.effort-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
padding: 1px 5px;
|
||
border-radius: var(--radius-xs);
|
||
font-family: var(--font-sans);
|
||
font-size: 9px;
|
||
font-weight: 500;
|
||
margin-top: 4px;
|
||
}
|
||
.effort-easy { background: var(--green-tint); color: var(--green-dark); }
|
||
.effort-medium { background: var(--yellow-tint); color: var(--yellow-text); }
|
||
.effort-hard { background: var(--orange-tint); color: var(--orange); }
|
||
|
||
.protein-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 3px;
|
||
padding: 1px 5px;
|
||
border-radius: var(--radius-xs);
|
||
font-family: var(--font-sans);
|
||
font-size: 9px;
|
||
font-weight: 500;
|
||
background: var(--purple-tint);
|
||
color: var(--purple);
|
||
margin-top: 3px;
|
||
}
|
||
|
||
/* ── Sidebar atom ────────────────────────────────────────────── */
|
||
.sidebar {
|
||
width: 200px;
|
||
flex-shrink: 0;
|
||
border-right: 1px solid var(--color-border);
|
||
background: var(--color-surface);
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding: 16px;
|
||
gap: 16px;
|
||
}
|
||
.sidebar-section-label {
|
||
font-family: var(--font-sans);
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
letter-spacing: 0.08em;
|
||
text-transform: uppercase;
|
||
color: var(--color-text-muted);
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
/* ── Right panel atom ────────────────────────────────────────── */
|
||
.right-panel {
|
||
width: 256px;
|
||
flex-shrink: 0;
|
||
border-left: 1px solid var(--color-border);
|
||
background: var(--color-page);
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding: 16px;
|
||
}
|
||
.panel-section {
|
||
margin-bottom: 16px;
|
||
}
|
||
.panel-label {
|
||
font-family: var(--font-sans);
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
letter-spacing: 0.08em;
|
||
text-transform: uppercase;
|
||
color: var(--color-text-muted);
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
/* ── Main content area ───────────────────────────────────────── */
|
||
.main-content {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
padding: 16px;
|
||
}
|
||
|
||
/* ── Layout wrapper ──────────────────────────────────────────── */
|
||
.desktop-frame {
|
||
display: flex;
|
||
flex-direction: column;
|
||
height: 480px;
|
||
background: var(--color-page);
|
||
}
|
||
.desktop-body {
|
||
display: flex;
|
||
flex: 1;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* ── Mobile frame ────────────────────────────────────────────── */
|
||
.mobile-frame {
|
||
width: 360px;
|
||
height: 640px;
|
||
border-radius: 24px;
|
||
border: 6px solid #2a2a26;
|
||
overflow: hidden;
|
||
background: var(--color-page);
|
||
display: flex;
|
||
flex-direction: column;
|
||
margin: 0 auto;
|
||
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
|
||
}
|
||
.mobile-status-bar {
|
||
height: 28px;
|
||
background: var(--color-page);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0 16px;
|
||
font-family: var(--font-sans);
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
color: var(--color-text);
|
||
}
|
||
.mobile-topbar {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 10px 14px;
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
.mobile-h1 {
|
||
font-family: var(--font-display);
|
||
font-size: 17px;
|
||
font-weight: 300;
|
||
}
|
||
|
||
/* ── Helper classes ──────────────────────────────────────────── */
|
||
.flex { display: flex; }
|
||
.flex-col { flex-direction: column; }
|
||
.flex-1 { flex: 1; }
|
||
.items-center { align-items: center; }
|
||
.items-start { align-items: flex-start; }
|
||
.justify-between { justify-content: space-between; }
|
||
.gap-2 { gap: 8px; }
|
||
.gap-3 { gap: 12px; }
|
||
.gap-4 { gap: 16px; }
|
||
.w-full { width: 100%; }
|
||
.mt-1 { margin-top: 4px; }
|
||
.mt-2 { margin-top: 8px; }
|
||
.mt-3 { margin-top: 12px; }
|
||
.mt-4 { margin-top: 16px; }
|
||
.mb-1 { margin-bottom: 4px; }
|
||
.mb-2 { margin-bottom: 8px; }
|
||
.mb-3 { margin-bottom: 12px; }
|
||
.grid-7 {
|
||
display: grid;
|
||
grid-template-columns: repeat(7, 1fr);
|
||
gap: 6px;
|
||
}
|
||
.divider {
|
||
height: 1px;
|
||
background: var(--color-border);
|
||
margin: 10px 0;
|
||
}
|
||
.text-muted {
|
||
font-family: var(--font-sans);
|
||
font-size: 12px;
|
||
color: var(--color-text-muted);
|
||
}
|
||
.link-sm {
|
||
font-family: var(--font-sans);
|
||
font-size: 11px;
|
||
font-weight: 500;
|
||
color: var(--yellow-text);
|
||
text-decoration: none;
|
||
cursor: pointer;
|
||
}
|
||
.link-sm:hover { text-decoration: underline; }
|
||
|
||
.stat-chip {
|
||
background: var(--color-surface);
|
||
border: 1px solid var(--color-border);
|
||
border-radius: var(--radius-md);
|
||
padding: 8px 10px;
|
||
flex: 1;
|
||
}
|
||
.stat-chip-val {
|
||
font-family: var(--font-display);
|
||
font-size: 20px;
|
||
font-weight: 300;
|
||
color: var(--color-text);
|
||
}
|
||
.stat-chip-label {
|
||
font-family: var(--font-sans);
|
||
font-size: 10px;
|
||
color: var(--color-text-muted);
|
||
margin-top: 1px;
|
||
}
|
||
|
||
.action-btn {
|
||
display: block;
|
||
width: 100%;
|
||
padding: 8px;
|
||
border-radius: var(--radius-md);
|
||
border: 1px solid var(--color-border);
|
||
background: var(--color-page);
|
||
font-family: var(--font-sans);
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
letter-spacing: 0.04em;
|
||
text-align: center;
|
||
color: var(--color-text);
|
||
cursor: pointer;
|
||
margin-top: 6px;
|
||
}
|
||
.action-btn-primary {
|
||
background: var(--green-dark);
|
||
color: white;
|
||
border-color: transparent;
|
||
}
|
||
|
||
.suggestion-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 7px 8px;
|
||
border-radius: var(--radius-md);
|
||
background: var(--color-surface);
|
||
border: 1px solid var(--color-border);
|
||
margin-top: 6px;
|
||
cursor: pointer;
|
||
}
|
||
.suggestion-row:hover { border-color: var(--green-light); }
|
||
.suggestion-name {
|
||
font-family: var(--font-sans);
|
||
font-size: 12px;
|
||
color: var(--color-text);
|
||
flex: 1;
|
||
}
|
||
.delta-badge {
|
||
font-family: var(--font-mono);
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
padding: 1px 5px;
|
||
border-radius: var(--radius-xs);
|
||
}
|
||
.delta-pos { background: var(--green-tint); color: var(--green-dark); }
|
||
.delta-neg { background: #fde8e8; color: var(--color-error); }
|
||
|
||
/* ── Spec footer ─────────────────────────────────────────────── */
|
||
.agent-section {
|
||
display: none;
|
||
}
|
||
|
||
/* ── Two-panel layout for mobile+desktop side-by-side ────────── */
|
||
.side-by-side {
|
||
display: flex;
|
||
gap: 24px;
|
||
padding: 24px;
|
||
align-items: flex-start;
|
||
flex-wrap: wrap;
|
||
}
|
||
.side-label {
|
||
font-family: var(--font-sans);
|
||
font-size: 10px;
|
||
font-weight: 500;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.08em;
|
||
color: var(--color-text-muted);
|
||
text-align: center;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
/* variety donut placeholder */
|
||
.score-ring {
|
||
width: 72px;
|
||
height: 72px;
|
||
border-radius: 50%;
|
||
background: conic-gradient(var(--yellow) 0% 78%, var(--yellow-light) 78% 100%);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
}
|
||
.score-ring::after {
|
||
content: '';
|
||
position: absolute;
|
||
width: 52px;
|
||
height: 52px;
|
||
border-radius: 50%;
|
||
background: var(--color-surface);
|
||
}
|
||
.score-ring-val {
|
||
position: relative;
|
||
z-index: 1;
|
||
font-family: var(--font-display);
|
||
font-size: 18px;
|
||
font-weight: 300;
|
||
color: var(--color-text);
|
||
}
|
||
|
||
.week-strip-mobile {
|
||
display: grid;
|
||
grid-template-columns: repeat(7, 1fr);
|
||
gap: 4px;
|
||
padding: 10px 14px;
|
||
}
|
||
.day-pip {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 3px;
|
||
cursor: pointer;
|
||
}
|
||
.day-pip-label {
|
||
font-family: var(--font-sans);
|
||
font-size: 9px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.04em;
|
||
color: var(--color-text-muted);
|
||
}
|
||
.day-pip-circle {
|
||
width: 30px;
|
||
height: 30px;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-family: var(--font-sans);
|
||
font-size: 11px;
|
||
font-weight: 500;
|
||
color: var(--color-text);
|
||
background: transparent;
|
||
position: relative;
|
||
}
|
||
.day-pip-dot {
|
||
width: 4px;
|
||
height: 4px;
|
||
border-radius: 50%;
|
||
background: var(--green);
|
||
}
|
||
.day-pip-circle-today { background: var(--yellow); color: white; }
|
||
.day-pip-circle-selected { background: var(--green-tint); color: var(--green-dark); }
|
||
|
||
.mobile-card {
|
||
margin: 10px 14px;
|
||
border-radius: var(--radius-lg);
|
||
border: 2px solid var(--color-border);
|
||
background: var(--color-surface);
|
||
padding: 14px;
|
||
}
|
||
.mobile-card-selected {
|
||
border-color: var(--green);
|
||
background: var(--green-tint);
|
||
}
|
||
|
||
.mobile-2col-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 8px;
|
||
padding: 10px 14px;
|
||
}
|
||
.mobile-grid-tile {
|
||
border-radius: var(--radius-md);
|
||
border: 1px solid var(--color-border);
|
||
background: var(--color-surface);
|
||
padding: 10px;
|
||
min-height: 72px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
cursor: pointer;
|
||
}
|
||
.mobile-grid-tile-empty {
|
||
border-style: dashed;
|
||
background: transparent;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--color-text-muted);
|
||
}
|
||
.mobile-grid-tile-today {
|
||
border: 2px solid var(--yellow);
|
||
background: var(--yellow-tint);
|
||
}
|
||
.mobile-grid-tile-selected {
|
||
border: 2px solid var(--green);
|
||
background: var(--green-tint);
|
||
}
|
||
.mobile-grid-day {
|
||
font-family: var(--font-sans);
|
||
font-size: 9px;
|
||
font-weight: 500;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.06em;
|
||
color: var(--color-text-muted);
|
||
}
|
||
.mobile-grid-name {
|
||
font-family: var(--font-display);
|
||
font-size: 12px;
|
||
font-weight: 300;
|
||
color: var(--color-text);
|
||
line-height: 1.3;
|
||
}
|
||
.mobile-grid-meta {
|
||
font-family: var(--font-sans);
|
||
font-size: 10px;
|
||
color: var(--color-text-muted);
|
||
}
|
||
.score-inline-badge {
|
||
display: inline-flex;
|
||
align-items: baseline;
|
||
gap: 3px;
|
||
background: var(--yellow-tint);
|
||
border: 1px solid var(--yellow-light);
|
||
border-radius: var(--radius-md);
|
||
padding: 3px 8px;
|
||
}
|
||
.score-inline-val {
|
||
font-family: var(--font-display);
|
||
font-size: 14px;
|
||
font-weight: 300;
|
||
color: var(--color-text);
|
||
}
|
||
.score-inline-denom {
|
||
font-family: var(--font-sans);
|
||
font-size: 10px;
|
||
color: var(--color-text-muted);
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- ────────────────────────────────────────────────────────────── -->
|
||
<!-- HUMAN-READABLE SECTION -->
|
||
<!-- ────────────────────────────────────────────────────────────── -->
|
||
|
||
<p class="spec-page-title">Mealplan · Wochenplaner</p>
|
||
<h1 class="spec-section-title">Planner Layout — 5 Konzepte</h1>
|
||
<p class="spec-section-sub">
|
||
Problem: Desktop zeigt ~80 % leeren Platz. Die linke Sidebar hat den Variety-Score nur am unteren Rand.
|
||
Rechtes Panel beginnt mit „Kein Tag ausgewählt". Die Kacheln sind zu flach für die Datendichte die wir hätten.
|
||
Alle 5 Konzepte nutzen ausschließlich vorhandene API-Daten.
|
||
</p>
|
||
|
||
|
||
<!-- ═══════════════════════════════════════════════════════════════ -->
|
||
<!-- MOCKUP 1: Score Dashboard Sidebar -->
|
||
<!-- ═══════════════════════════════════════════════════════════════ -->
|
||
<div class="mockup-card">
|
||
<div class="mockup-label">
|
||
<span class="mockup-number">01</span>
|
||
<span class="mockup-title">Score Dashboard Sidebar</span>
|
||
<span class="mockup-tagline">Einfachster Win — Sidebar von oben befüllen</span>
|
||
</div>
|
||
|
||
<div style="padding:24px;">
|
||
<div class="desktop-frame">
|
||
<!-- Topbar -->
|
||
<div class="chrome-topbar">
|
||
<span class="chrome-h1">Wochenplaner</span>
|
||
<span class="chrome-weekrange">7.–13. Apr</span>
|
||
<div class="chrome-nav-arrow">‹</div>
|
||
<div class="chrome-nav-arrow">›</div>
|
||
<button class="chrome-btn">Heute</button>
|
||
<button class="chrome-btn chrome-btn-primary chrome-ml-auto">+ Gericht hinzufügen</button>
|
||
</div>
|
||
|
||
<div class="desktop-body">
|
||
<!-- LEFT SIDEBAR — now full of content -->
|
||
<div class="sidebar">
|
||
<!-- Score at TOP -->
|
||
<div style="background:var(--yellow-tint);border:1px solid var(--yellow-light);border-radius:var(--radius-lg);padding:12px;">
|
||
<div class="sidebar-section-label">Abwechslungs-Score</div>
|
||
<div style="display:flex;align-items:baseline;gap:4px;">
|
||
<span class="score-big" style="font-size:32px;">7.8</span>
|
||
<span class="score-denom">/10</span>
|
||
</div>
|
||
<div class="progress-bar" style="margin-top:6px;">
|
||
<div class="progress-fill" style="width:78%;"></div>
|
||
</div>
|
||
<a class="link-sm" style="display:block;margin-top:8px;">Variety überprüfen →</a>
|
||
</div>
|
||
|
||
<!-- Sub-scores -->
|
||
<div>
|
||
<div class="sidebar-section-label">Teilwerte</div>
|
||
<div class="sub-score-row">
|
||
<span class="sub-score-label">Proteinvielfalt</span>
|
||
<div class="sub-score-bar"><div class="sub-score-fill" style="width:80%;background:var(--green);"></div></div>
|
||
<span class="sub-score-val">8.0</span>
|
||
</div>
|
||
<div class="sub-score-row">
|
||
<span class="sub-score-label">Zutaten</span>
|
||
<div class="sub-score-bar"><div class="sub-score-fill" style="width:72%;background:var(--yellow);"></div></div>
|
||
<span class="sub-score-val">7.2</span>
|
||
</div>
|
||
<div class="sub-score-row">
|
||
<span class="sub-score-label">Aufwand</span>
|
||
<div class="sub-score-bar"><div class="sub-score-fill" style="width:82%;background:var(--green);"></div></div>
|
||
<span class="sub-score-val">8.2</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Effort distribution -->
|
||
<div>
|
||
<div class="sidebar-section-label">Aufwandverteilung</div>
|
||
<div style="display:flex;gap:3px;border-radius:var(--radius-sm);overflow:hidden;height:18px;">
|
||
<div style="flex:3;background:var(--green);display:flex;align-items:center;justify-content:center;font-family:var(--font-sans);font-size:9px;color:white;font-weight:500;">3 einfach</div>
|
||
<div style="flex:2;background:var(--yellow);display:flex;align-items:center;justify-content:center;font-family:var(--font-sans);font-size:9px;color:white;font-weight:500;">2 mittel</div>
|
||
<div style="flex:1;background:var(--orange);display:flex;align-items:center;justify-content:center;font-family:var(--font-sans);font-size:9px;color:white;font-weight:500;">1</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Warnings -->
|
||
<div>
|
||
<div class="sidebar-section-label">Überschneidungen</div>
|
||
<div class="warn-item">⚠ Hähnchen an 3 Tagen</div>
|
||
<div class="warn-item">⚠ Tomaten an 2 Tagen</div>
|
||
</div>
|
||
|
||
<!-- Progress: geplante Tage -->
|
||
<div>
|
||
<div class="sidebar-section-label" style="margin-bottom:4px;">Geplant</div>
|
||
<div style="display:flex;align-items:baseline;gap:4px;">
|
||
<span style="font-family:var(--font-display);font-size:22px;font-weight:300;color:var(--color-text);">5</span>
|
||
<span style="font-family:var(--font-sans);font-size:11px;color:var(--color-text-muted);">von 7 Tagen</span>
|
||
</div>
|
||
<div style="display:flex;gap:3px;margin-top:6px;">
|
||
<div style="flex:1;height:4px;border-radius:9999px;background:var(--green);"></div>
|
||
<div style="flex:1;height:4px;border-radius:9999px;background:var(--green);"></div>
|
||
<div style="flex:1;height:4px;border-radius:9999px;background:var(--green);"></div>
|
||
<div style="flex:1;height:4px;border-radius:9999px;background:var(--green);"></div>
|
||
<div style="flex:1;height:4px;border-radius:9999px;background:var(--green);"></div>
|
||
<div style="flex:1;height:4px;border-radius:9999px;background:var(--color-border);"></div>
|
||
<div style="flex:1;height:4px;border-radius:9999px;background:var(--color-border);"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MAIN CALENDAR — taller tiles -->
|
||
<main class="main-content">
|
||
<div class="grid-7">
|
||
<!-- Mo -->
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Mo</div>
|
||
<div class="cal-day-badge">7</div>
|
||
<div class="cal-tile" style="flex:1;min-height:160px;">
|
||
<p class="recipe-name-sm">Hähnchen-Curry</p>
|
||
<p class="recipe-meta-sm">35 Min</p>
|
||
<span class="effort-badge effort-medium">mittel</span>
|
||
<span class="protein-badge">Hähnchen</span>
|
||
</div>
|
||
</div>
|
||
<!-- Di -->
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Di</div>
|
||
<div class="cal-day-badge cal-day-badge-today" style="background:var(--yellow);color:white;">8</div>
|
||
<div class="cal-tile cal-tile-today" style="flex:1;min-height:160px;border-radius:var(--radius-md);border:2px solid var(--yellow);background:var(--yellow-tint);">
|
||
<p class="recipe-name-sm">Pasta Bolognese</p>
|
||
<p class="recipe-meta-sm">45 Min</p>
|
||
<span class="effort-badge effort-medium">mittel</span>
|
||
<span class="protein-badge">Rind</span>
|
||
</div>
|
||
</div>
|
||
<!-- Mi -->
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Mi</div>
|
||
<div class="cal-day-badge cal-day-badge-selected" style="background:var(--green-tint);color:var(--green-dark);">9</div>
|
||
<div class="cal-tile cal-tile-selected" style="flex:1;min-height:160px;border-radius:var(--radius-md);border:2px solid var(--green);background:var(--green-tint);">
|
||
<p class="recipe-name-sm">Gemüse-Stir-fry</p>
|
||
<p class="recipe-meta-sm">20 Min</p>
|
||
<span class="effort-badge effort-easy">einfach</span>
|
||
<span class="protein-badge">Tofu</span>
|
||
</div>
|
||
</div>
|
||
<!-- Do -->
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Do</div>
|
||
<div class="cal-day-badge">10</div>
|
||
<div class="cal-tile" style="flex:1;min-height:160px;">
|
||
<p class="recipe-name-sm">Lachsfilet mit Kartoffeln</p>
|
||
<p class="recipe-meta-sm">30 Min</p>
|
||
<span class="effort-badge effort-easy">einfach</span>
|
||
<span class="protein-badge">Fisch</span>
|
||
</div>
|
||
</div>
|
||
<!-- Fr -->
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Fr</div>
|
||
<div class="cal-day-badge">11</div>
|
||
<div class="cal-tile" style="flex:1;min-height:160px;">
|
||
<p class="recipe-name-sm">Pizza Margherita</p>
|
||
<p class="recipe-meta-sm">50 Min</p>
|
||
<span class="effort-badge effort-hard">aufwändig</span>
|
||
<span class="protein-badge">vegetarisch</span>
|
||
</div>
|
||
</div>
|
||
<!-- Sa -->
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Sa</div>
|
||
<div class="cal-day-badge">12</div>
|
||
<div class="cal-tile cal-tile-empty" style="flex:1;min-height:160px;border-radius:var(--radius-md);">
|
||
<span style="font-size:16px;color:var(--color-text-muted);">+</span>
|
||
<span style="font-family:var(--font-sans);font-size:10px;color:var(--color-text-muted);">wählen</span>
|
||
</div>
|
||
</div>
|
||
<!-- So -->
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">So</div>
|
||
<div class="cal-day-badge">13</div>
|
||
<div class="cal-tile cal-tile-empty" style="flex:1;min-height:160px;border-radius:var(--radius-md);">
|
||
<span style="font-size:16px;color:var(--color-text-muted);">+</span>
|
||
<span style="font-family:var(--font-sans);font-size:10px;color:var(--color-text-muted);">wählen</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- RIGHT PANEL -->
|
||
<div class="right-panel">
|
||
<div class="panel-section">
|
||
<div class="panel-label">Mittwoch, 9. Apr</div>
|
||
<p style="font-family:var(--font-display);font-size:16px;font-weight:300;color:var(--color-text);line-height:1.4;">Gemüse-Stir-fry</p>
|
||
<p style="font-family:var(--font-sans);font-size:12px;color:var(--color-text-muted);margin-top:4px;">20 Min · einfach</p>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;gap:6px;">
|
||
<button class="action-btn action-btn-primary">Koch-Modus</button>
|
||
<button class="action-btn">Rezept ansehen</button>
|
||
<button class="action-btn">Gericht tauschen</button>
|
||
<button class="action-btn" style="color:var(--color-error);border-color:var(--color-error);">Entfernen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="annotation">
|
||
<strong>Was ändert sich:</strong> Variety Score wird an den Anfang der Sidebar verschoben. Darunter folgen Teilwerte (3 Mini-Balken),
|
||
Aufwandverteilung (Farbbalken), Top-Warnungen, und ein 5/7-Fortschrittsindikator.
|
||
Kacheln werden auf 160 px min-height erhöht und zeigen Effort-Badge + Protein-Tag.
|
||
<br><br>
|
||
<strong>Vorteile:</strong> Minimaler Aufwand, keine Layout-Änderung, alle Daten bereits vorhanden (varietyScore API liefert sub-scores + overlaps).
|
||
Die Sidebar ist jetzt von oben bis unten gefüllt. Kacheln vermitteln mehr Kontext auf einen Blick.
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- ═══════════════════════════════════════════════════════════════ -->
|
||
<!-- MOCKUP 2: Week Stats Header + Full-Width Calendar -->
|
||
<!-- ═══════════════════════════════════════════════════════════════ -->
|
||
<div class="mockup-card">
|
||
<div class="mockup-label">
|
||
<span class="mockup-number">02</span>
|
||
<span class="mockup-title">Stats-Leiste + Fullscreen-Kalender</span>
|
||
<span class="mockup-tagline">2-Spalten-Layout, Kennzahlen als Kopfzeile</span>
|
||
</div>
|
||
|
||
<div style="padding:24px;">
|
||
<div class="desktop-frame" style="height:500px;">
|
||
<!-- Topbar -->
|
||
<div class="chrome-topbar">
|
||
<span class="chrome-h1">Wochenplaner</span>
|
||
<span class="chrome-weekrange">7.–13. Apr</span>
|
||
<div class="chrome-nav-arrow">‹</div>
|
||
<div class="chrome-nav-arrow">›</div>
|
||
<button class="chrome-btn">Heute</button>
|
||
<button class="chrome-btn chrome-btn-primary chrome-ml-auto">+ Gericht hinzufügen</button>
|
||
</div>
|
||
|
||
<!-- Stats row under topbar -->
|
||
<div style="display:flex;gap:8px;padding:10px 16px;border-bottom:1px solid var(--color-border);background:var(--color-surface);">
|
||
<div class="stat-chip">
|
||
<div class="stat-chip-val">7.8</div>
|
||
<div class="stat-chip-label">Abwechslungs-Score</div>
|
||
</div>
|
||
<div class="stat-chip">
|
||
<div class="stat-chip-val">5<span style="font-family:var(--font-sans);font-size:12px;color:var(--color-text-muted);">/7</span></div>
|
||
<div class="stat-chip-label">Tage geplant</div>
|
||
</div>
|
||
<div class="stat-chip">
|
||
<div class="stat-chip-val">34 <span style="font-family:var(--font-sans);font-size:12px;color:var(--color-text-muted);">Min</span></div>
|
||
<div class="stat-chip-label">Ø Kochzeit</div>
|
||
</div>
|
||
<div class="stat-chip" style="flex:2;">
|
||
<div class="stat-chip-label" style="margin-bottom:4px;">Aufwand</div>
|
||
<div style="display:flex;gap:2px;border-radius:var(--radius-sm);overflow:hidden;height:16px;">
|
||
<div style="flex:3;background:var(--green);display:flex;align-items:center;justify-content:center;font-family:var(--font-sans);font-size:8px;color:white;font-weight:500;">3×</div>
|
||
<div style="flex:2;background:var(--yellow);display:flex;align-items:center;justify-content:center;font-family:var(--font-sans);font-size:8px;color:white;font-weight:500;">2×</div>
|
||
<div style="flex:1;background:var(--orange);"></div>
|
||
</div>
|
||
</div>
|
||
<div style="flex:3;" class="stat-chip">
|
||
<div class="stat-chip-label" style="margin-bottom:4px;">Protein-Verteilung</div>
|
||
<div style="display:flex;gap:3px;flex-wrap:wrap;">
|
||
<span class="protein-badge">Hähnchen ×2</span>
|
||
<span class="protein-badge">Rind ×1</span>
|
||
<span class="protein-badge">Fisch ×1</span>
|
||
<span class="protein-badge">Tofu ×1</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="desktop-body">
|
||
<!-- MAIN: Full-width calendar with taller tiles -->
|
||
<main style="flex:1;overflow-y:auto;padding:16px;">
|
||
<div class="grid-7" style="height:calc(100% - 8px);">
|
||
<!-- Mon -->
|
||
<div style="display:flex;flex-direction:column;gap:6px;">
|
||
<div class="cal-day-name">Montag</div>
|
||
<div class="cal-day-badge">7</div>
|
||
<div class="cal-tile" style="flex:1;">
|
||
<p class="recipe-name-sm">Hähnchen-Curry</p>
|
||
<p class="recipe-meta-sm">35 Min</p>
|
||
<div style="margin-top:6px;display:flex;flex-direction:column;gap:3px;">
|
||
<span class="effort-badge effort-medium">mittel</span>
|
||
<span class="protein-badge">Hähnchen</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Tue today -->
|
||
<div style="display:flex;flex-direction:column;gap:6px;">
|
||
<div class="cal-day-name" style="color:var(--yellow-text);">Dienstag</div>
|
||
<div class="cal-day-badge" style="background:var(--yellow);color:white;">8</div>
|
||
<div class="cal-tile" style="flex:1;border:2px solid var(--yellow);background:var(--yellow-tint);">
|
||
<p class="recipe-name-sm">Pasta Bolognese</p>
|
||
<p class="recipe-meta-sm">45 Min</p>
|
||
<div style="margin-top:6px;display:flex;flex-direction:column;gap:3px;">
|
||
<span class="effort-badge effort-medium">mittel</span>
|
||
<span class="protein-badge">Rind</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Wed selected -->
|
||
<div style="display:flex;flex-direction:column;gap:6px;">
|
||
<div class="cal-day-name" style="color:var(--green-dark);">Mittwoch</div>
|
||
<div class="cal-day-badge" style="background:var(--green-tint);color:var(--green-dark);">9</div>
|
||
<div class="cal-tile" style="flex:1;border:2px solid var(--green);background:var(--green-tint);">
|
||
<p class="recipe-name-sm">Gemüse-Stir-fry</p>
|
||
<p class="recipe-meta-sm">20 Min</p>
|
||
<div style="margin-top:6px;display:flex;flex-direction:column;gap:3px;">
|
||
<span class="effort-badge effort-easy">einfach</span>
|
||
<span class="protein-badge">Tofu</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Thu -->
|
||
<div style="display:flex;flex-direction:column;gap:6px;">
|
||
<div class="cal-day-name">Donnerstag</div>
|
||
<div class="cal-day-badge">10</div>
|
||
<div class="cal-tile" style="flex:1;">
|
||
<p class="recipe-name-sm">Lachs mit Kartoffeln</p>
|
||
<p class="recipe-meta-sm">30 Min</p>
|
||
<div style="margin-top:6px;display:flex;flex-direction:column;gap:3px;">
|
||
<span class="effort-badge effort-easy">einfach</span>
|
||
<span class="protein-badge">Fisch</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Fri -->
|
||
<div style="display:flex;flex-direction:column;gap:6px;">
|
||
<div class="cal-day-name">Freitag</div>
|
||
<div class="cal-day-badge">11</div>
|
||
<div class="cal-tile" style="flex:1;">
|
||
<p class="recipe-name-sm">Pizza Margherita</p>
|
||
<p class="recipe-meta-sm">50 Min</p>
|
||
<div style="margin-top:6px;display:flex;flex-direction:column;gap:3px;">
|
||
<span class="effort-badge effort-hard">aufwändig</span>
|
||
<span class="protein-badge">vegetarisch</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Sat empty -->
|
||
<div style="display:flex;flex-direction:column;gap:6px;">
|
||
<div class="cal-day-name">Samstag</div>
|
||
<div class="cal-day-badge">12</div>
|
||
<div class="cal-tile cal-tile-empty" style="flex:1;">
|
||
<span style="font-size:20px;">+</span>
|
||
<span style="font-family:var(--font-sans);font-size:10px;margin-top:2px;">Gericht wählen</span>
|
||
</div>
|
||
</div>
|
||
<!-- Sun empty -->
|
||
<div style="display:flex;flex-direction:column;gap:6px;">
|
||
<div class="cal-day-name">Sonntag</div>
|
||
<div class="cal-day-badge">13</div>
|
||
<div class="cal-tile cal-tile-empty" style="flex:1;">
|
||
<span style="font-size:20px;">+</span>
|
||
<span style="font-family:var(--font-sans);font-size:10px;margin-top:2px;">Gericht wählen</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- RIGHT PANEL: day detail -->
|
||
<div class="right-panel">
|
||
<div class="panel-section">
|
||
<div class="panel-label">Mittwoch, 9. Apr</div>
|
||
<p style="font-family:var(--font-display);font-size:16px;font-weight:300;line-height:1.4;">Gemüse-Stir-fry</p>
|
||
<p style="font-family:var(--font-sans);font-size:12px;color:var(--color-text-muted);margin-top:4px;">20 Min · einfach</p>
|
||
</div>
|
||
<div class="divider"></div>
|
||
<div class="panel-section">
|
||
<div class="panel-label">Score-Vorschau</div>
|
||
<div style="display:flex;align-items:baseline;gap:4px;">
|
||
<span style="font-family:var(--font-display);font-size:24px;font-weight:300;">7.8</span>
|
||
<span class="text-muted">/10</span>
|
||
<span style="font-family:var(--font-sans);font-size:11px;color:var(--green-dark);margin-left:4px;">▲ +0.4</span>
|
||
</div>
|
||
<div class="progress-bar"><div class="progress-fill" style="width:78%;"></div></div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;gap:6px;">
|
||
<button class="action-btn action-btn-primary">Koch-Modus</button>
|
||
<button class="action-btn">Rezept ansehen</button>
|
||
<button class="action-btn">Gericht tauschen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="annotation">
|
||
<strong>Was ändert sich:</strong> Die linke Sidebar entfällt — stattdessen gibt es eine horizontale Stats-Leiste direkt unter der Topbar.
|
||
Sie zeigt Score, geplante Tage, Ø Kochzeit, Aufwand-Farbbalken und Protein-Tags kompakt nebeneinander.
|
||
Der Kalender wächst auf die volle verbleibende Breite. Rechtes Panel zeigt beim ausgewählten Tag jetzt auch den aktuellen Score.
|
||
<br><br>
|
||
<strong>Vorteile:</strong> Maximaler Platz für den Kalender. Stats auf einen Blick ohne Scrolling. Variety-Score immer sichtbar.
|
||
Schwäche: Keine persistente Sidebar für Warnungen.
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- ═══════════════════════════════════════════════════════════════ -->
|
||
<!-- MOCKUP 3: Idle Panel = Wochenübersicht -->
|
||
<!-- ═══════════════════════════════════════════════════════════════ -->
|
||
<div class="mockup-card">
|
||
<div class="mockup-label">
|
||
<span class="mockup-number">03</span>
|
||
<span class="mockup-title">Rechtes Panel als Wochenübersicht</span>
|
||
<span class="mockup-tagline">„Kein Tag ausgewählt" durch echte Daten ersetzen</span>
|
||
</div>
|
||
|
||
<div style="padding:24px;">
|
||
<div class="desktop-frame" style="height:500px;">
|
||
<div class="chrome-topbar">
|
||
<span class="chrome-h1">Wochenplaner</span>
|
||
<span class="chrome-weekrange">7.–13. Apr</span>
|
||
<div class="chrome-nav-arrow">‹</div>
|
||
<div class="chrome-nav-arrow">›</div>
|
||
<button class="chrome-btn">Heute</button>
|
||
<button class="chrome-btn chrome-btn-primary chrome-ml-auto">+ Gericht hinzufügen</button>
|
||
</div>
|
||
|
||
<div class="desktop-body">
|
||
<!-- Sidebar: Score oben -->
|
||
<div class="sidebar" style="width:192px;">
|
||
<div style="background:var(--yellow-tint);border:1px solid var(--yellow-light);border-radius:var(--radius-lg);padding:12px;">
|
||
<div class="sidebar-section-label">Score</div>
|
||
<div style="display:flex;align-items:baseline;gap:4px;">
|
||
<span class="score-big" style="font-size:30px;">7.8</span>
|
||
<span class="score-denom">/10</span>
|
||
</div>
|
||
<div class="progress-bar" style="margin-top:6px;"><div class="progress-fill" style="width:78%;"></div></div>
|
||
<div class="sub-score-row" style="margin-top:8px;">
|
||
<span class="sub-score-label">Protein</span>
|
||
<div class="sub-score-bar"><div class="sub-score-fill" style="width:80%;background:var(--green);"></div></div>
|
||
<span class="sub-score-val">8.0</span>
|
||
</div>
|
||
<div class="sub-score-row">
|
||
<span class="sub-score-label">Zutaten</span>
|
||
<div class="sub-score-bar"><div class="sub-score-fill" style="width:72%;background:var(--yellow);"></div></div>
|
||
<span class="sub-score-val">7.2</span>
|
||
</div>
|
||
<div class="sub-score-row">
|
||
<span class="sub-score-label">Aufwand</span>
|
||
<div class="sub-score-bar"><div class="sub-score-fill" style="width:82%;background:var(--green);"></div></div>
|
||
<span class="sub-score-val">8.2</span>
|
||
</div>
|
||
<a class="link-sm" style="display:block;margin-top:8px;">Details →</a>
|
||
</div>
|
||
<div>
|
||
<div class="sidebar-section-label">Warnungen</div>
|
||
<div class="warn-item">⚠ Hähnchen ×3</div>
|
||
<div class="warn-item">⚠ Tomaten ×2</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MAIN: Calendar -->
|
||
<main class="main-content">
|
||
<div class="grid-7">
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Mo</div>
|
||
<div class="cal-day-badge">7</div>
|
||
<div class="cal-tile" style="min-height:140px;">
|
||
<p class="recipe-name-sm">Hähnchen-Curry</p>
|
||
<p class="recipe-meta-sm">35 Min</p>
|
||
<span class="effort-badge effort-medium">mittel</span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Di</div>
|
||
<div class="cal-day-badge" style="background:var(--yellow);color:white;">8</div>
|
||
<div class="cal-tile" style="min-height:140px;border:2px solid var(--yellow);background:var(--yellow-tint);">
|
||
<p class="recipe-name-sm">Pasta Bolognese</p>
|
||
<p class="recipe-meta-sm">45 Min</p>
|
||
<span class="effort-badge effort-medium">mittel</span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Mi</div>
|
||
<div class="cal-day-badge">9</div>
|
||
<div class="cal-tile" style="min-height:140px;">
|
||
<p class="recipe-name-sm">Gemüse-Stir-fry</p>
|
||
<p class="recipe-meta-sm">20 Min</p>
|
||
<span class="effort-badge effort-easy">einfach</span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Do</div>
|
||
<div class="cal-day-badge">10</div>
|
||
<div class="cal-tile" style="min-height:140px;">
|
||
<p class="recipe-name-sm">Lachs mit Kartoffeln</p>
|
||
<p class="recipe-meta-sm">30 Min</p>
|
||
<span class="effort-badge effort-easy">einfach</span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Fr</div>
|
||
<div class="cal-day-badge">11</div>
|
||
<div class="cal-tile" style="min-height:140px;">
|
||
<p class="recipe-name-sm">Pizza Margherita</p>
|
||
<p class="recipe-meta-sm">50 Min</p>
|
||
<span class="effort-badge effort-hard">aufwändig</span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Sa</div>
|
||
<div class="cal-day-badge">12</div>
|
||
<div class="cal-tile cal-tile-empty" style="min-height:140px;">+</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">So</div>
|
||
<div class="cal-day-badge">13</div>
|
||
<div class="cal-tile cal-tile-empty" style="min-height:140px;">+</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- RIGHT PANEL: IDLE state shows week summary -->
|
||
<div class="right-panel">
|
||
<div style="font-family:var(--font-sans);font-size:10px;font-weight:500;letter-spacing:0.08em;text-transform:uppercase;color:var(--color-text-muted);margin-bottom:12px;">Diese Woche</div>
|
||
|
||
<!-- Geplante Tage -->
|
||
<div style="display:flex;gap:4px;margin-bottom:12px;">
|
||
<div style="flex:1;background:var(--green-tint);border:1px solid var(--green-light);border-radius:var(--radius-md);padding:8px;text-align:center;">
|
||
<div style="font-family:var(--font-display);font-size:22px;font-weight:300;">5</div>
|
||
<div style="font-family:var(--font-sans);font-size:9px;color:var(--color-text-muted);">geplant</div>
|
||
</div>
|
||
<div style="flex:1;background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-md);padding:8px;text-align:center;">
|
||
<div style="font-family:var(--font-display);font-size:22px;font-weight:300;">2</div>
|
||
<div style="font-family:var(--font-sans);font-size:9px;color:var(--color-text-muted);">offen</div>
|
||
</div>
|
||
<div style="flex:1;background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-md);padding:8px;text-align:center;">
|
||
<div style="font-family:var(--font-display);font-size:22px;font-weight:300;">34</div>
|
||
<div style="font-family:var(--font-sans);font-size:9px;color:var(--color-text-muted);">Ø Min</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="divider"></div>
|
||
|
||
<!-- Restliche Woche -->
|
||
<div style="font-family:var(--font-sans);font-size:10px;font-weight:500;letter-spacing:0.08em;text-transform:uppercase;color:var(--color-text-muted);margin-bottom:8px;">Ungeplante Tage</div>
|
||
<div style="display:flex;flex-direction:column;gap:4px;">
|
||
<div class="suggestion-row" style="flex-direction:column;align-items:flex-start;gap:4px;">
|
||
<span style="font-family:var(--font-sans);font-size:11px;font-weight:500;color:var(--color-text);">Samstag, 12. Apr</span>
|
||
<span style="font-family:var(--font-sans);font-size:10px;color:var(--color-text-muted);">Noch kein Gericht — Klicken zum Planen</span>
|
||
</div>
|
||
<div class="suggestion-row" style="flex-direction:column;align-items:flex-start;gap:4px;">
|
||
<span style="font-family:var(--font-sans);font-size:11px;font-weight:500;color:var(--color-text);">Sonntag, 13. Apr</span>
|
||
<span style="font-family:var(--font-sans);font-size:10px;color:var(--color-text-muted);">Noch kein Gericht — Klicken zum Planen</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="divider"></div>
|
||
|
||
<!-- Heute Abend -->
|
||
<div style="font-family:var(--font-sans);font-size:10px;font-weight:500;letter-spacing:0.08em;text-transform:uppercase;color:var(--color-text-muted);margin-bottom:8px;">Heute Abend</div>
|
||
<div style="background:var(--yellow-tint);border:1px solid var(--yellow-light);border-radius:var(--radius-md);padding:10px;">
|
||
<p style="font-family:var(--font-display);font-size:14px;font-weight:300;">Pasta Bolognese</p>
|
||
<p style="font-family:var(--font-sans);font-size:11px;color:var(--color-text-muted);margin-top:2px;">45 Min · mittel</p>
|
||
<button class="action-btn action-btn-primary" style="margin-top:8px;padding:6px;">Koch-Modus</button>
|
||
</div>
|
||
|
||
<div style="margin-top:auto;padding-top:16px;">
|
||
<a class="link-sm" style="color:var(--color-text-muted);">Klicke einen Tag um Details zu sehen</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="annotation">
|
||
<strong>Was ändert sich:</strong> Nur das rechte Panel im Idle-Zustand. Statt „Kein Tag ausgewählt" zeigt es eine echte Wochenübersicht:
|
||
Geplant/Offen/Ø Kochzeit, ungeplante Tage als Einladung zum Klicken, und „Heute Abend" als schnellen Koch-Modus-Einstieg.
|
||
<br><br>
|
||
<strong>Vorteile:</strong> Kein leerer Zustand mehr. Nutzer sehen sofort den Stand ihrer Woche. „Heute Abend" löst den häufigsten
|
||
Use-Case (abends schnell kochen starten) direkt. Minimale Änderungen am restlichen Layout.
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- ═══════════════════════════════════════════════════════════════ -->
|
||
<!-- MOCKUP 4: Score-Ring + Variety-Panel rechts -->
|
||
<!-- ═══════════════════════════════════════════════════════════════ -->
|
||
<div class="mockup-card">
|
||
<div class="mockup-label">
|
||
<span class="mockup-number">04</span>
|
||
<span class="mockup-title">Variety rechts, Kalender breiter</span>
|
||
<span class="mockup-tagline">Variety-Analyse ins rechte Panel, kein linkes Sidebar mehr</span>
|
||
</div>
|
||
|
||
<div style="padding:24px;">
|
||
<div class="desktop-frame" style="height:520px;">
|
||
<div class="chrome-topbar">
|
||
<span class="chrome-h1">Wochenplaner</span>
|
||
<span class="chrome-weekrange">7.–13. Apr 2026</span>
|
||
<div class="chrome-nav-arrow">‹</div>
|
||
<div class="chrome-nav-arrow">›</div>
|
||
<button class="chrome-btn">Heute</button>
|
||
<button class="chrome-btn chrome-btn-primary chrome-ml-auto">+ Gericht hinzufügen</button>
|
||
</div>
|
||
|
||
<div class="desktop-body">
|
||
<!-- MAIN: wider calendar, no left sidebar -->
|
||
<main style="flex:1;overflow-y:auto;padding:16px;">
|
||
<div class="grid-7" style="grid-template-columns:repeat(7,1fr);gap:8px;">
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Mo, 7.</div>
|
||
<div class="cal-tile" style="min-height:180px;margin-top:4px;">
|
||
<p class="recipe-name-sm">Hähnchen-Curry</p>
|
||
<p class="recipe-meta-sm">35 Min</p>
|
||
<span class="effort-badge effort-medium" style="margin-top:6px;">mittel</span>
|
||
<span class="protein-badge" style="display:block;margin-top:3px;">Hähnchen</span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name" style="color:var(--yellow-text);">Di, 8. ★</div>
|
||
<div class="cal-tile" style="min-height:180px;margin-top:4px;border:2px solid var(--yellow);background:var(--yellow-tint);">
|
||
<p class="recipe-name-sm">Pasta Bolognese</p>
|
||
<p class="recipe-meta-sm">45 Min</p>
|
||
<span class="effort-badge effort-medium" style="margin-top:6px;">mittel</span>
|
||
<span class="protein-badge" style="display:block;margin-top:3px;">Rind</span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name" style="color:var(--green-dark);">Mi, 9.</div>
|
||
<div class="cal-tile" style="min-height:180px;margin-top:4px;border:2px solid var(--green);background:var(--green-tint);">
|
||
<p class="recipe-name-sm">Gemüse-Stir-fry</p>
|
||
<p class="recipe-meta-sm">20 Min</p>
|
||
<span class="effort-badge effort-easy" style="margin-top:6px;">einfach</span>
|
||
<span class="protein-badge" style="display:block;margin-top:3px;">Tofu</span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Do, 10.</div>
|
||
<div class="cal-tile" style="min-height:180px;margin-top:4px;">
|
||
<p class="recipe-name-sm">Lachs mit Kartoffeln</p>
|
||
<p class="recipe-meta-sm">30 Min</p>
|
||
<span class="effort-badge effort-easy" style="margin-top:6px;">einfach</span>
|
||
<span class="protein-badge" style="display:block;margin-top:3px;">Fisch</span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Fr, 11.</div>
|
||
<div class="cal-tile" style="min-height:180px;margin-top:4px;">
|
||
<p class="recipe-name-sm">Pizza Margherita</p>
|
||
<p class="recipe-meta-sm">50 Min</p>
|
||
<span class="effort-badge effort-hard" style="margin-top:6px;">aufwändig</span>
|
||
<span class="protein-badge" style="display:block;margin-top:3px;">vegetarisch</span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">Sa, 12.</div>
|
||
<div class="cal-tile cal-tile-empty" style="min-height:180px;margin-top:4px;">
|
||
<span style="font-size:22px;">+</span>
|
||
<span style="font-family:var(--font-sans);font-size:10px;margin-top:4px;">Gericht wählen</span>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;">
|
||
<div class="cal-day-name">So, 13.</div>
|
||
<div class="cal-tile cal-tile-empty" style="min-height:180px;margin-top:4px;">
|
||
<span style="font-size:22px;">+</span>
|
||
<span style="font-family:var(--font-sans);font-size:10px;margin-top:4px;">Gericht wählen</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<!-- RIGHT PANEL: always shows variety analysis + today quick action -->
|
||
<div class="right-panel" style="width:280px;">
|
||
<!-- Score ring + value -->
|
||
<div style="display:flex;align-items:center;gap:14px;margin-bottom:12px;">
|
||
<div class="score-ring">
|
||
<span class="score-ring-val">7.8</span>
|
||
</div>
|
||
<div>
|
||
<div class="sidebar-section-label" style="margin-bottom:2px;">Abwechslungs-Score</div>
|
||
<div class="sub-score-row" style="margin-top:4px;">
|
||
<span class="sub-score-label">Protein</span>
|
||
<div class="sub-score-bar"><div class="sub-score-fill" style="width:80%;background:var(--green);"></div></div>
|
||
<span class="sub-score-val">8.0</span>
|
||
</div>
|
||
<div class="sub-score-row">
|
||
<span class="sub-score-label">Zutaten</span>
|
||
<div class="sub-score-bar"><div class="sub-score-fill" style="width:72%;background:var(--yellow);"></div></div>
|
||
<span class="sub-score-val">7.2</span>
|
||
</div>
|
||
<div class="sub-score-row">
|
||
<span class="sub-score-label">Aufwand</span>
|
||
<div class="sub-score-bar"><div class="sub-score-fill" style="width:82%;background:var(--green);"></div></div>
|
||
<span class="sub-score-val">8.2</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="divider"></div>
|
||
|
||
<!-- Aufwand-Verteilung -->
|
||
<div style="margin-bottom:12px;">
|
||
<div class="panel-label">Aufwand diese Woche</div>
|
||
<div style="display:flex;gap:3px;border-radius:var(--radius-sm);overflow:hidden;height:20px;margin-top:4px;">
|
||
<div style="flex:3;background:var(--green);display:flex;align-items:center;justify-content:center;font-family:var(--font-sans);font-size:9px;color:white;font-weight:500;">3 einfach</div>
|
||
<div style="flex:2;background:var(--yellow);display:flex;align-items:center;justify-content:center;font-family:var(--font-sans);font-size:9px;color:white;font-weight:500;">2 mittel</div>
|
||
<div style="flex:1;background:var(--orange);display:flex;align-items:center;justify-content:center;font-family:var(--font-sans);font-size:9px;color:white;font-weight:500;">1</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Warnungen -->
|
||
<div style="margin-bottom:12px;">
|
||
<div class="panel-label">Überschneidungen</div>
|
||
<div class="warn-item">⚠ Hähnchen an Mo, Mi, Do</div>
|
||
<div class="warn-item">⚠ Tomaten an Di, Do</div>
|
||
<a class="link-sm" style="display:block;margin-top:6px;">Variety-Analyse →</a>
|
||
</div>
|
||
|
||
<div class="divider"></div>
|
||
|
||
<!-- Heute Abend CTA -->
|
||
<div>
|
||
<div class="panel-label">Heute Abend</div>
|
||
<div style="background:var(--yellow-tint);border:1px solid var(--yellow-light);border-radius:var(--radius-md);padding:10px;">
|
||
<p style="font-family:var(--font-display);font-size:14px;font-weight:300;">Pasta Bolognese</p>
|
||
<p style="font-family:var(--font-sans);font-size:11px;color:var(--color-text-muted);margin-top:2px;">Dienstag · 45 Min · mittel</p>
|
||
<button class="action-btn action-btn-primary" style="margin-top:8px;padding:6px;">Koch-Modus starten</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="annotation">
|
||
<strong>Was ändert sich:</strong> Linke Sidebar komplett entfernt → Kalender gewinnt ~200 px Breite.
|
||
Das rechte Panel wird zum permanenten Variety-Dashboard: Score-Ring, Teilwerte, Aufwand-Balken, Warnungen.
|
||
Ganz unten: „Heute Abend" als direkter Koch-Modus-Einstieg. Beim Klick auf einen Tag ersetzt das Day-Detail-Panel diesen Inhalt.
|
||
<br><br>
|
||
<strong>Vorteile:</strong> Variety-Score ist immer im Blick, nicht nur am unteren Sidebar-Rand.
|
||
Breiterer Kalender = mehr Platz für Rezeptnamen. Klarer Haupt-CTA (Koch-Modus) ohne Tab-Wechsel.
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- ═══════════════════════════════════════════════════════════════ -->
|
||
<!-- MOCKUP 5: Mobile — 2-Spalten Tages-Gitter -->
|
||
<!-- ═══════════════════════════════════════════════════════════════ -->
|
||
<div class="mockup-card">
|
||
<div class="mockup-label">
|
||
<span class="mockup-number">05</span>
|
||
<span class="mockup-title">Mobile — Wochengitter statt Tagesstreifen</span>
|
||
<span class="mockup-tagline">Alle 7 Tage auf einmal sichtbar, Score im Header</span>
|
||
</div>
|
||
|
||
<div style="padding:24px;">
|
||
<div style="display:flex;gap:40px;flex-wrap:wrap;align-items:flex-start;justify-content:center;">
|
||
|
||
<!-- Current state comparison -->
|
||
<div>
|
||
<div class="side-label">Aktueller Zustand</div>
|
||
<div class="mobile-frame">
|
||
<div class="mobile-status-bar"><span>9:41</span><span>●●●</span></div>
|
||
<div class="mobile-topbar">
|
||
<span class="mobile-h1">Diese Woche</span>
|
||
<div style="display:flex;gap:6px;align-items:center;">
|
||
<span style="font-size:16px;color:var(--color-text-muted);">‹</span>
|
||
<span style="font-size:16px;color:var(--color-text-muted);">›</span>
|
||
<button style="background:var(--green-dark);color:white;border:none;border-radius:var(--radius-md);padding:5px 10px;font-family:var(--font-sans);font-size:11px;font-weight:500;">+ Gericht</button>
|
||
</div>
|
||
</div>
|
||
<!-- Yellow score banner -->
|
||
<div style="margin:10px 14px 0;background:var(--yellow-tint);border:1px solid var(--yellow-light);border-radius:var(--radius-md);padding:10px;">
|
||
<div style="display:flex;align-items:baseline;gap:4px;">
|
||
<span style="font-family:var(--font-display);font-size:24px;font-weight:300;">7.8</span>
|
||
<span style="font-family:var(--font-sans);font-size:11px;color:var(--color-text-muted);">/10 Abwechslungs-Score</span>
|
||
</div>
|
||
<div class="progress-bar"><div class="progress-fill" style="width:78%;"></div></div>
|
||
<div style="font-family:var(--font-sans);font-size:10px;color:var(--yellow-text);margin-top:6px;">⚠ Hähnchen in 3 Mahlzeiten</div>
|
||
</div>
|
||
<!-- Week strip -->
|
||
<div class="week-strip-mobile">
|
||
<div class="day-pip"><span class="day-pip-label">Mo</span><div class="day-pip-circle"><div class="day-pip-dot"></div></div></div>
|
||
<div class="day-pip"><span class="day-pip-label">Di</span><div class="day-pip-circle day-pip-circle-today">8</div></div>
|
||
<div class="day-pip"><span class="day-pip-label">Mi</span><div class="day-pip-circle day-pip-circle-selected">9</div></div>
|
||
<div class="day-pip"><span class="day-pip-label">Do</span><div class="day-pip-circle"><div class="day-pip-dot"></div></div></div>
|
||
<div class="day-pip"><span class="day-pip-label">Fr</span><div class="day-pip-circle"><div class="day-pip-dot"></div></div></div>
|
||
<div class="day-pip"><span class="day-pip-label">Sa</span><div class="day-pip-circle" style="color:var(--color-text-muted);">12</div></div>
|
||
<div class="day-pip"><span class="day-pip-label">So</span><div class="day-pip-circle" style="color:var(--color-text-muted);">13</div></div>
|
||
</div>
|
||
<!-- Selected day card -->
|
||
<div style="font-family:var(--font-sans);font-size:10px;font-weight:500;text-transform:uppercase;letter-spacing:0.06em;color:var(--color-text-muted);padding:0 14px;margin-bottom:6px;">Mittwoch, 9. April</div>
|
||
<div class="mobile-card mobile-card-selected">
|
||
<p style="font-family:var(--font-display);font-size:18px;font-weight:300;">Gemüse-Stir-fry</p>
|
||
<p style="font-family:var(--font-sans);font-size:12px;color:var(--color-text-muted);margin-top:4px;">20 Min · einfach</p>
|
||
<div style="display:flex;gap:6px;margin-top:10px;">
|
||
<button style="flex:1;background:var(--green-dark);color:white;border:none;border-radius:var(--radius-md);padding:8px;font-family:var(--font-sans);font-size:11px;font-weight:500;">Jetzt kochen</button>
|
||
<button style="background:transparent;border:1px solid var(--color-border);border-radius:var(--radius-md);padding:8px;font-family:var(--font-sans);font-size:11px;color:var(--color-text);">Tauschen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- New mockup -->
|
||
<div>
|
||
<div class="side-label">Neuer Vorschlag — 2-Spalten-Gitter</div>
|
||
<div class="mobile-frame">
|
||
<div class="mobile-status-bar"><span>9:41</span><span>●●●</span></div>
|
||
<!-- Compact header with inline score badge -->
|
||
<div class="mobile-topbar" style="padding:8px 14px;">
|
||
<span class="mobile-h1">Diese Woche</span>
|
||
<div style="display:flex;gap:6px;align-items:center;">
|
||
<div class="score-inline-badge">
|
||
<span class="score-inline-val">7.8</span>
|
||
<span class="score-inline-denom">/10</span>
|
||
</div>
|
||
<span style="font-size:16px;color:var(--color-text-muted);">‹</span>
|
||
<span style="font-size:16px;color:var(--color-text-muted);">›</span>
|
||
</div>
|
||
</div>
|
||
<!-- 2-col grid: all 7 days visible -->
|
||
<div style="overflow-y:auto;flex:1;">
|
||
<div class="mobile-2col-grid">
|
||
<!-- Mo -->
|
||
<div class="mobile-grid-tile">
|
||
<div class="mobile-grid-day">Montag · 7.</div>
|
||
<div class="mobile-grid-name">Hähnchen-Curry</div>
|
||
<div class="mobile-grid-meta">35 Min · mittel</div>
|
||
</div>
|
||
<!-- Di today -->
|
||
<div class="mobile-grid-tile mobile-grid-tile-today">
|
||
<div class="mobile-grid-day" style="color:var(--yellow-text);">Dienstag · 8. ★</div>
|
||
<div class="mobile-grid-name">Pasta Bolognese</div>
|
||
<div class="mobile-grid-meta">45 Min · mittel</div>
|
||
</div>
|
||
<!-- Mi selected -->
|
||
<div class="mobile-grid-tile mobile-grid-tile-selected" style="grid-column:1/-1;">
|
||
<div style="display:flex;justify-content:space-between;align-items:flex-start;">
|
||
<div>
|
||
<div class="mobile-grid-day" style="color:var(--green-dark);">Mittwoch · 9. — Ausgewählt</div>
|
||
<div class="mobile-grid-name" style="font-size:16px;margin-top:4px;">Gemüse-Stir-fry</div>
|
||
<div class="mobile-grid-meta" style="margin-top:3px;">20 Min · einfach</div>
|
||
</div>
|
||
<div style="display:flex;flex-direction:column;gap:5px;flex-shrink:0;margin-left:10px;">
|
||
<button style="background:var(--green-dark);color:white;border:none;border-radius:var(--radius-md);padding:6px 10px;font-family:var(--font-sans);font-size:10px;font-weight:500;white-space:nowrap;">Kochen</button>
|
||
<button style="background:transparent;border:1px solid var(--color-border);border-radius:var(--radius-md);padding:6px 10px;font-family:var(--font-sans);font-size:10px;white-space:nowrap;">Tauschen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- Do -->
|
||
<div class="mobile-grid-tile">
|
||
<div class="mobile-grid-day">Donnerstag · 10.</div>
|
||
<div class="mobile-grid-name">Lachs mit Kartoffeln</div>
|
||
<div class="mobile-grid-meta">30 Min · einfach</div>
|
||
</div>
|
||
<!-- Fr -->
|
||
<div class="mobile-grid-tile">
|
||
<div class="mobile-grid-day">Freitag · 11.</div>
|
||
<div class="mobile-grid-name">Pizza Margherita</div>
|
||
<div class="mobile-grid-meta">50 Min · aufwändig</div>
|
||
</div>
|
||
<!-- Sa empty -->
|
||
<div class="mobile-grid-tile mobile-grid-tile-empty">
|
||
<div class="mobile-grid-day" style="color:var(--color-text-muted);">Samstag · 12.</div>
|
||
<div style="font-size:18px;color:var(--color-border);margin-top:4px;">+</div>
|
||
<div class="mobile-grid-meta">wählen</div>
|
||
</div>
|
||
<!-- So empty -->
|
||
<div class="mobile-grid-tile mobile-grid-tile-empty">
|
||
<div class="mobile-grid-day" style="color:var(--color-text-muted);">Sonntag · 13.</div>
|
||
<div style="font-size:18px;color:var(--color-border);margin-top:4px;">+</div>
|
||
<div class="mobile-grid-meta">wählen</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<div class="annotation">
|
||
<strong>Was ändert sich (Mobile):</strong> Die gelbe Score-Banner wird aus dem Scroll-Bereich herausgelöst und als kompaktes Badge
|
||
in die Topbar integriert (spart ~80 px). Der horizontale Tagesstreifen + separate „Restliche Woche" Liste werden ersetzt durch ein
|
||
2-Spalten-Gitter, das alle 7 Tage auf einmal zeigt. Der ausgewählte Tag expandiert zur vollen Breite mit integrierten Aktionen (kein separater großer Card mehr).
|
||
<br><br>
|
||
<strong>Vorteile:</strong> Auf einem Blick sieht man die ganze Woche. Kein Scrollen nötig um alle Tage zu sehen.
|
||
Score-Badge bleibt jederzeit sichtbar ohne Platz zu fressen. Expandierter Tag ersetzt das separate Tagesdetail-Pattern.
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- ────────────────────────────────────────────────────────────── -->
|
||
<!-- MACHINE-READABLE SECTION -->
|
||
<!-- ────────────────────────────────────────────────────────────── -->
|
||
<div class="agent-section" id="agent-section">
|
||
<!--
|
||
MACHINE-READABLE SPEC: Planner Layout Mockups
|
||
Generated: 2026-04-09
|
||
Author: Atlas (UI persona)
|
||
Scope: /planner desktop + mobile
|
||
|
||
═══════════════════════════════════════════════════════════════════
|
||
MOCKUP 01 — Score Dashboard Sidebar
|
||
═══════════════════════════════════════════════════════════════════
|
||
Layout: 3-column (sidebar | main | right-panel) — unchanged
|
||
Sidebar width: 200px (currently 224px, can shrink)
|
||
Changes:
|
||
- Sidebar: mt-auto removed from VarietyScoreCard wrapper
|
||
- Sidebar: score card now first child (no div wrapper needed)
|
||
- Sidebar: Add <ScoreBreakdownList> component below score card
|
||
(already exists: /frontend/src/lib/planner/ScoreBreakdownList.svelte)
|
||
- Sidebar: Add effort distribution mini bar
|
||
(data: slots.map(s => s.recipe?.effort) → count einfach/mittel/aufwändig)
|
||
- Sidebar: Add top-2 ingredient overlap warnings
|
||
(data: varietyScore.ingredientOverlaps.slice(0,2))
|
||
- Sidebar: Add "X von 7 Tagen geplant" progress row
|
||
(data: slots.filter(s => s.recipe).length)
|
||
Calendar tiles: min-height 140px → 180px
|
||
- Show: recipe.name, cookTimeMin, effort badge, protein tag (first protein tag from recipe.tags)
|
||
- effort-badge: einfach=green-tint/green-dark, mittel=yellow-tint/yellow-text, aufwändig=orange-tint/orange
|
||
- protein-badge: purple-tint/purple always
|
||
|
||
Data sources (all available):
|
||
- varietyScore.score ✓
|
||
- varietyScore.ingredientOverlaps ✓
|
||
- VarietyPreviewResponse.proteinDiversity / ingredientOverlap / effortBalance (sub-scores) ✓
|
||
- slots[].recipe.effort ✓
|
||
- slots.filter(s => s.recipe).length ✓
|
||
- slots[].recipe.tags (for protein tag) ✓
|
||
|
||
═══════════════════════════════════════════════════════════════════
|
||
MOCKUP 02 — Stats-Leiste + Full-Width Calendar
|
||
═══════════════════════════════════════════════════════════════════
|
||
Layout: 2-column (main | right-panel) — remove left sidebar
|
||
Stats bar: height 48px, flex row, gap-2, px-4
|
||
Position: between topbar and desktop-body
|
||
Chips (flex:1 each, except last flex:2 and flex:3):
|
||
1. score/10 → varietyScore.score
|
||
2. X/7 geplant → slots.filter(s=>s.recipe).length
|
||
3. Ø Min → Math.round(slots.filter(s=>s.recipe?.cookTimeMin).reduce(…) / count)
|
||
4. Aufwand bar (flex:2) → einfach/mittel/aufwändig counts
|
||
5. Protein tags (flex:3) → unique protein tags with counts
|
||
Calendar tile full-day label: "Montag" not "Mo" — use formatDayLabel
|
||
Right panel: keep existing day-detail state, add score delta display:
|
||
currentScore + delta when day is selected
|
||
|
||
═══════════════════════════════════════════════════════════════════
|
||
MOCKUP 03 — Idle Panel = Wochenübersicht
|
||
═══════════════════════════════════════════════════════════════════
|
||
Layout: 3-column — unchanged
|
||
Changes: only right panel idle state
|
||
Replace: <p>Kein Tag ausgewählt</p>
|
||
With: week summary component containing:
|
||
1. Stat chips: geplant count, offen count, avg cook time
|
||
2. "Ungeplante Tage" list → days.filter(d => !slotMap[d]?.recipe)
|
||
Each item: date label + "Klicken zum Planen" → onclick sets panelState recipe-picker
|
||
3. "Heute Abend" card → slotMap[today] if recipe exists
|
||
Show: recipe name, meta, Koch-Modus button
|
||
No new API calls needed — all derived from existing slots + today
|
||
|
||
═══════════════════════════════════════════════════════════════════
|
||
MOCKUP 04 — Variety Panel rechts, kein linkes Sidebar
|
||
═══════════════════════════════════════════════════════════════════
|
||
Layout: 2-column (main | right-panel), left sidebar removed
|
||
Right panel: 2 states:
|
||
STATE A (no day selected) — permanent variety dashboard:
|
||
- Score ring (CSS conic-gradient, hole via ::after)
|
||
- Sub-scores (3 bars)
|
||
- Effort distribution bar
|
||
- Top ingredient overlap warnings + link to /planner/variety
|
||
- "Heute Abend" CTA at bottom
|
||
STATE B (day selected) — existing day-detail content + score delta
|
||
Right panel width: 280px (was 280px — unchanged)
|
||
Main calendar: gains 200px width (sidebar removed)
|
||
Calendar day label: "Mo, 7." format — formatDayAbbr + dateNum
|
||
|
||
Score ring CSS:
|
||
background: conic-gradient(var(--yellow) 0% {score*10}%, var(--yellow-light) {score*10}% 100%)
|
||
After: 52px circle var(--color-surface) centered = donut hole
|
||
|
||
═══════════════════════════════════════════════════════════════════
|
||
MOCKUP 05 — Mobile 2-Column Grid
|
||
═══════════════════════════════════════════════════════════════════
|
||
Breakpoint: mobile only (< 1024px)
|
||
Changes:
|
||
|
||
A. Header: score badge replaces full VarietyScoreCard banner
|
||
Component: inline badge in header right area
|
||
Value: varietyScore.score.toFixed(1) + "/10"
|
||
Style: yellow-tint bg, yellow-light border, radius-md
|
||
Full banner removed → saves ~80px vertical space
|
||
|
||
B. Week navigation: score badge sits between score and nav arrows
|
||
Layout: flex row: [title] [score-badge] [‹] [›] [+ Gericht]
|
||
|
||
C. Replace WeekStrip + DayMealCard + "Restliche Woche" section
|
||
With: 2-column CSS grid of day tiles
|
||
Grid: grid-cols-2, gap-2, px-3.5, overflow-y-auto
|
||
|
||
D. Tile states:
|
||
- default: border color-border, bg color-surface
|
||
- today: border-2 yellow, bg yellow-tint
|
||
- selected: grid-column span 2 (full width), expanded with actions
|
||
- empty: dashed border, placeholder +
|
||
|
||
E. Selected tile (expanded):
|
||
- grid-column: 1 / -1 (spans both columns)
|
||
- flex row: [name + meta] [actions column: Kochen btn + Tauschen btn]
|
||
- onclick same as handleSelectDay: selectedDay = day
|
||
|
||
F. Interaction:
|
||
- Tap tile → selectedDay = day (same state)
|
||
- No bottom sheet needed for basic day selection
|
||
- + empty tile → opens pickerOpen bottom sheet (unchanged)
|
||
- Existing tile → opens actionSheetOpen (unchanged, but triggered from tile click)
|
||
|
||
G. Ingredient overlap warnings:
|
||
- Removed from sticky banner (too much space)
|
||
- Accessible via "Variety überprüfen" link (score badge is tappable → /planner/variety)
|
||
|
||
TOKEN REFERENCE:
|
||
--yellow-tint: #fdf6d8 (today bg)
|
||
--yellow-light: #f9e08a (today border)
|
||
--green-tint: #e8f5ea (selected bg)
|
||
--green: #3d8c4a (selected border)
|
||
--color-surface: #f5f4ee (default tile bg)
|
||
--color-border: #d8d7d0 (default tile border)
|
||
--color-page: #fafaf7
|
||
--radius-md: 6px (tile radius)
|
||
--radius-lg: 10px (expanded tile)
|
||
|
||
═══════════════════════════════════════════════════════════════════
|
||
ACCESSIBILITY NOTES (all mockups)
|
||
═══════════════════════════════════════════════════════════════════
|
||
- Score ring: add role="img" aria-label="Abwechslungs-Score: 7.8 von 10"
|
||
- Sub-score bars: role="progressbar" aria-valuenow aria-valuemin=0 aria-valuemax=10
|
||
- Effort bar segments: aria-label="3 einfach, 2 mittel, 1 aufwändig"
|
||
- Mobile tile grid: each tile button gets aria-label="{dayLabel}: {recipeName or 'Kein Gericht'}"
|
||
- Expanded tile: focus management — when tile expands, move focus to action button
|
||
- Score badge in mobile header: role="status" (updates when score changes)
|
||
- Contrast check:
|
||
yellow-text (#8a6800) on yellow-tint (#fdf6d8): ~6.8:1 ✓ AAA
|
||
green-dark (#2e6e39) on green-tint (#e8f5ea): ~5.1:1 ✓ AA
|
||
orange (#e8862a) on orange-tint (#fef0e6): ~3.4:1 ✓ large text only
|
||
→ use orange-dark (#b46820) for small text on orange-tint: ~5.2:1 ✓ AA
|
||
|
||
═══════════════════════════════════════════════════════════════════
|
||
RECOMMENDED PRIORITY
|
||
═══════════════════════════════════════════════════════════════════
|
||
1. Mockup 01 — highest ROI, lowest risk. Sidebar already exists.
|
||
2. Mockup 03 — zero layout change, only right panel idle state.
|
||
Together 01+03 fix both reported problems with minimal scope.
|
||
3. Mockup 05 — mobile improvement, self-contained.
|
||
4. Mockup 04 — bigger refactor but best visual result.
|
||
5. Mockup 02 — breaks 3-panel convention, discuss first.
|
||
-->
|
||
</div>
|
||
|
||
</body>
|
||
</html>
|