Files
mealprep/specs/frontend/variety-page-rework.html
Marcel Raddatz fa4a4c9ef7 docs(specs): add J9 variety score config user journey and variety page rework spec
- Adds J9 (Configure variety score) to userjourneys.html — new journey for
  tuning the algorithm per household dietary context (e.g. disabling protein
  penalties for vegetarian households); introduces screen E4 (Variety settings)
- Adds specs/frontend/variety-page-rework.html with 3 design variations for
  the /planner/variety page rework: recipe-name pills, action rows (recommended),
  and week-grid with side panel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 15:51:26 +02:00

842 lines
63 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Variety Page Rework · 3 Variationen</title>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,300;9..144,400;9..144,500&family=DM+Sans:wght@300;400;500;600&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet"/>
<!--
spec:agent
document: /planner/variety — Variety Page Rework, 3 Variationen
version: 1.0
journey: J4 Swap (adjacent)
route: /planner/variety
screen: C2
variations: V1 Recipe Pills | V2 Action Rows | V3 Week Grid
last-updated: 2026-04-09
PROBLEMS ADDRESSED:
1. Warnings show day abbreviations ("MON, WED") — replace with recipe names
2. No swap action reachable from warnings — add inline swap CTA per recipe
3. Protein score is meat-centric for vegetarian households (backend concern, noted below)
FRONTEND-ONLY CHANGE (no backend schema changes required for items 1+2):
weekPlan.slots has { dayOfWeek: "MON", recipe: { id, name } }
tagRepeats.days[] contains day keys matching dayOfWeek
→ build slotsByDay map frontend-side, look up recipeName + slotId per day
→ swap CTA links to /planner?week={weekStart}&swap={slotId}
PROTEIN SCORE — VEGETARIAN HOUSEHOLDS (backend concern, TBD):
Current: proteinDiversity = 10 - proteinRepeats * 2
Problem: vegetarian protein sources (Tofu, Linsen, Ei) may repeat more than
omnivore households; penalty of -2 per repeat is calibrated for meat variety.
Backend discussed: tag filtering or weight adjustment needed.
Frontend impact: if backend changes tagRepeats to exclude non-meat or adjusts score,
the frontend ScoreBreakdownList label "Protein-Vielfalt" may need renaming.
Until resolved: the rework does NOT change protein score display — only warnings.
-->
<style>
:root {
--color-page: #FAFAF7;
--color-surface: #F5F4EE;
--color-subtle: #EDECEA;
--color-border: #D8D7D0;
--color-text-muted: #6B6A63;
--color-text: #1C1C18;
--green-tint: #E8F5EA;
--green-light: #AEDCB0;
--green: #3D8C4A;
--green-dark: #2E6E39;
--yellow-tint: #FDF6D8;
--yellow-light: #F9E08A;
--yellow: #E8B400;
--yellow-text: #8A6800;
--color-error: #DC4C3E;
--blue-tint: #E6F1FB;
--blue: #185FA5;
--font-display: 'Fraunces', Georgia, serif;
--font-sans: 'DM Sans', system-ui, sans-serif;
--font-mono: 'DM Mono', monospace;
--radius-sm: 4px; --radius-md: 6px; --radius-lg: 10px; --radius-xl: 16px; --radius-full: 9999px;
--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,.10), 0 2px 4px rgba(28,28,24,.05);
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: var(--font-sans); background: var(--color-page); color: var(--color-text); font-size: 14px; line-height: 1.6; }
.doc { max-width: 1040px; margin: 0 auto; padding: 48px 40px 96px; }
.doc-header { padding-bottom: 28px; border-bottom: 1px solid var(--color-border); margin-bottom: 32px; display: flex; justify-content: space-between; align-items: flex-end; }
.doc-header h1 { font-family: var(--font-display); font-size: 26px; font-weight: 500; letter-spacing: -0.02em; }
.doc-header p { font-size: 13px; color: var(--color-text-muted); margin-top: 4px; }
.doc-meta { font-family: var(--font-mono); font-size: 11px; color: var(--color-text-muted); text-align: right; line-height: 1.9; }
.intro { font-size: 14px; line-height: 1.75; max-width: 680px; margin-bottom: 16px; }
.section-label { font-size: 10px; font-weight: 500; letter-spacing: 0.12em; text-transform: uppercase; color: var(--color-text-muted); padding-bottom: 10px; border-bottom: 1px solid var(--color-border); margin-bottom: 32px; margin-top: 56px; }
/* Notice box */
.notice { background: var(--yellow-tint); border: 1px solid var(--yellow-light); border-radius: var(--radius-lg); padding: 14px 18px; margin-bottom: 40px; }
.notice h3 { font-size: 12px; font-weight: 600; color: var(--yellow-text); margin-bottom: 4px; }
.notice p { font-size: 12px; color: var(--yellow-text); line-height: 1.6; }
.notice code { font-family: var(--font-mono); background: rgba(0,0,0,.07); padding: 1px 4px; border-radius: 3px; }
/* Variation sections */
.variation { margin-bottom: 72px; }
.var-header { display: flex; align-items: flex-start; gap: 20px; margin-bottom: 24px; }
.var-num { font-family: var(--font-display); font-size: 44px; font-weight: 300; color: var(--yellow-light); line-height: 1; flex-shrink: 0; width: 56px; letter-spacing: -0.03em; }
.var-meta { flex: 1; padding-top: 4px; }
.var-title { font-size: 18px; font-weight: 500; letter-spacing: -0.01em; margin-bottom: 4px; }
.var-desc { font-size: 13px; color: var(--color-text-muted); line-height: 1.6; max-width: 540px; }
.var-tag { font-size: 10px; font-weight: 500; letter-spacing: 0.07em; text-transform: uppercase; padding: 3px 8px; border-radius: var(--radius-sm); background: var(--color-subtle); color: var(--color-text-muted); margin-top: 6px; display: inline-block; }
.var-tag.rec { background: var(--green-tint); color: var(--green-dark); }
.var-tag.amb { background: var(--blue-tint); color: var(--blue); }
/* Preview containers */
.preview-pair { display: flex; gap: 24px; align-items: flex-start; margin-bottom: 20px; }
.preview-d-wrap { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.preview-m-wrap { flex-shrink: 0; display: flex; flex-direction: column; gap: 6px; }
.preview-label { font-size: 9px; font-weight: 500; letter-spacing: 0.09em; text-transform: uppercase; color: var(--color-text-muted); }
.preview-d-clip { height: 340px; overflow: hidden; border: 1px solid var(--color-border); border-radius: var(--radius-lg); background: var(--color-page); }
.preview-d-scale { transform: scale(0.5); transform-origin: top left; width: 200%; }
.preview-m-clip { width: 196px; height: 340px; overflow: hidden; border: 1.5px solid var(--color-border); border-radius: 24px; background: var(--color-page); }
.preview-m-scale { transform: scale(0.5); transform-origin: top left; width: 200%; }
/* Notes */
.notes { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: 14px 18px; }
.notes-label { font-size: 9px; font-weight: 500; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-text-muted); margin-bottom: 8px; }
.notes ul { list-style: none; display: flex; flex-direction: column; gap: 4px; }
.notes li { font-size: 12px; color: var(--color-text-muted); line-height: 1.5; display: flex; align-items: flex-start; gap: 8px; }
.notes li::before { content: '→'; color: var(--green); font-weight: 500; flex-shrink: 0; }
/* ── AppShell chrome ── */
.shell { display: flex; background: var(--color-page); font-family: var(--font-sans); overflow: hidden; }
.sidebar { width: 224px; min-width: 224px; background: white; border-right: 1px solid var(--color-border); display: flex; flex-direction: column; }
.sidebar-brand { padding: 14px 18px; border-bottom: 1px solid var(--color-border); }
.sidebar-brand-row { display: flex; align-items: center; gap: 8px; }
.sidebar-logo { width: 22px; height: 22px; background: var(--green); border-radius: var(--radius-sm); }
.sidebar-app { font-family: var(--font-display); font-size: 15px; font-weight: 500; }
.sidebar-household { font-size: 10px; color: var(--color-text-muted); margin-top: 1px; }
.sidebar-nav { flex: 1; padding: 4px 8px; }
.sidebar-group-label { font-size: 8px; font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-text-muted); padding: 16px 12px 4px; }
.sidebar-item { display: flex; align-items: center; gap: 8px; padding: 7px 12px; border-radius: var(--radius-md); font-size: 13px; color: var(--color-text); text-decoration: none; }
.sidebar-item.active { background: var(--green-tint); color: var(--green-dark); font-weight: 500; }
.sidebar-icon { width: 20px; text-align: center; font-size: 16px; }
/* Page chrome */
.topbar { display: flex; align-items: center; gap: 12px; border-bottom: 1px solid var(--color-border); background: var(--color-page); padding: 14px 24px; }
.topbar-back { font-size: 13px; color: var(--color-text-muted); text-decoration: none; }
.topbar-sep { font-size: 13px; color: var(--color-text-muted); }
.topbar-title { font-family: var(--font-display); font-size: 20px; font-weight: 300; }
.main { flex: 1; padding: 24px; overflow: hidden; }
/* Score hero (shared across variations) */
.score-hero { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; margin-bottom: 20px; }
.score-num { font-family: var(--font-display); font-size: 64px; font-weight: 300; line-height: 1; letter-spacing: -0.03em; }
.score-denom { font-family: var(--font-display); font-size: 24px; font-weight: 300; color: var(--color-text-muted); }
.score-label { font-size: 13px; font-weight: 500; color: var(--yellow-text); }
.score-bar { height: 6px; background: var(--color-subtle); border-radius: var(--radius-full); overflow: hidden; width: 160px; }
.score-fill { height: 100%; border-radius: var(--radius-full); }
.score-fill.good { background: var(--green-dark); }
.score-fill.warn { background: var(--yellow); }
/* Sub-scores */
.sub-scores { border: 1px solid var(--color-border); border-radius: var(--radius-lg); overflow: hidden; background: white; margin-bottom: 20px; }
.sub-row { display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; border-bottom: 1px solid var(--color-border); }
.sub-row:last-child { border-bottom: none; }
.sub-label { font-size: 13px; }
.sub-val { font-size: 13px; font-weight: 500; color: var(--yellow-text); }
.sub-val.ok { color: var(--green-dark); }
/* Section heading */
.section-hd { font-size: 10px; font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-text-muted); margin-bottom: 10px; }
/* ────────────────────────────────────────────
V1: Recipe Pill Warning Cards
──────────────────────────────────────────── */
.warn-card { background: var(--yellow-tint); border: 1px solid var(--yellow-light); border-radius: var(--radius-lg); padding: 14px 16px; margin-bottom: 10px; }
.warn-title { font-size: 13px; font-weight: 500; color: var(--yellow-text); margin-bottom: 8px; }
.pill-row { display: flex; flex-wrap: wrap; gap: 6px; }
.recipe-pill { display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px 5px 12px; border-radius: var(--radius-full); background: white; border: 1px solid var(--yellow-light); font-size: 12px; font-weight: 500; color: var(--color-text); }
.recipe-pill-day { font-size: 10px; color: var(--color-text-muted); font-weight: 400; }
.pill-swap-btn { width: 22px; height: 22px; border-radius: var(--radius-full); background: var(--color-subtle); border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--color-text-muted); flex-shrink: 0; }
.pill-swap-btn:hover { background: var(--green-tint); color: var(--green-dark); }
/* ────────────────────────────────────────────
V2: Action Rows
──────────────────────────────────────────── */
/* Compact score header for V2 */
.score-compact { display: flex; align-items: center; gap: 14px; padding: 14px 20px; background: white; border: 1px solid var(--color-border); border-radius: var(--radius-lg); margin-bottom: 20px; }
.score-compact-num { font-family: var(--font-display); font-size: 36px; font-weight: 300; line-height: 1; }
.score-compact-denom { font-family: var(--font-display); font-size: 16px; font-weight: 300; color: var(--color-text-muted); }
.score-compact-right { flex: 1; }
.score-compact-label { font-size: 12px; font-weight: 500; color: var(--yellow-text); margin-bottom: 4px; }
.score-compact-bar { height: 5px; background: var(--color-subtle); border-radius: var(--radius-full); overflow: hidden; }
.score-compact-fill { height: 100%; border-radius: var(--radius-full); background: var(--yellow); }
.action-row { display: flex; align-items: flex-start; gap: 14px; padding: 14px 16px; background: white; border: 1px solid var(--color-border); border-radius: var(--radius-lg); margin-bottom: 8px; }
.action-icon { width: 32px; height: 32px; border-radius: var(--radius-md); background: var(--yellow-tint); display: flex; align-items: center; justify-content: center; font-size: 14px; flex-shrink: 0; margin-top: 1px; }
.action-body { flex: 1; }
.action-title { font-size: 13px; font-weight: 500; margin-bottom: 6px; }
.action-recipe-row { display: flex; align-items: center; justify-content: space-between; padding: 6px 10px; background: var(--color-subtle); border-radius: var(--radius-md); margin-bottom: 4px; }
.action-recipe-name { font-size: 12px; font-weight: 500; }
.action-recipe-day { font-size: 10px; color: var(--color-text-muted); margin-left: 4px; }
.btn-swap { padding: 4px 10px; background: white; border: 1px solid var(--color-border); border-radius: var(--radius-md); font-size: 11px; font-weight: 500; color: var(--color-text-muted); cursor: pointer; white-space: nowrap; }
.btn-swap:hover { border-color: var(--green-light); color: var(--green-dark); }
/* ────────────────────────────────────────────
V3: Week Grid + Side Panel
──────────────────────────────────────────── */
.v3-layout { display: flex; gap: 0; height: 680px; }
.v3-main { flex: 1; padding: 24px; overflow-y: auto; }
.v3-panel { width: 280px; min-width: 280px; border-left: 1px solid var(--color-border); background: white; padding: 20px; overflow-y: auto; display: flex; flex-direction: column; }
.week-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; margin-bottom: 20px; }
.day-col { display: flex; flex-direction: column; gap: 4px; }
.day-header { font-size: 10px; font-weight: 500; color: var(--color-text-muted); text-align: center; padding-bottom: 4px; }
.recipe-slot { border-radius: var(--radius-md); border: 1px solid var(--color-border); background: white; padding: 6px 5px; min-height: 52px; font-size: 10px; font-weight: 500; text-align: center; display: flex; align-items: center; justify-content: center; cursor: pointer; line-height: 1.3; }
.recipe-slot.warn { border-color: var(--yellow); background: var(--yellow-tint); color: var(--yellow-text); box-shadow: 0 0 0 2px rgba(232,180,0,.25); }
.recipe-slot.warn:hover { box-shadow: 0 0 0 2px var(--yellow); }
.recipe-slot.selected { border-color: var(--green-dark); box-shadow: 0 0 0 2px var(--green-light); }
.recipe-slot.empty { background: var(--color-subtle); color: var(--color-text-muted); font-weight: 400; font-size: 9px; }
.warn-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--yellow); display: inline-block; margin-left: 3px; vertical-align: middle; }
.panel-score { display: flex; align-items: baseline; gap: 4px; margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid var(--color-border); }
.panel-score-num { font-family: var(--font-display); font-size: 48px; font-weight: 300; line-height: 1; }
.panel-score-denom { font-family: var(--font-display); font-size: 18px; font-weight: 300; color: var(--color-text-muted); }
.panel-warn-title { font-size: 13px; font-weight: 500; margin-bottom: 4px; }
.panel-warn-desc { font-size: 12px; color: var(--color-text-muted); margin-bottom: 14px; line-height: 1.5; }
.panel-recipe-entry { display: flex; align-items: center; justify-content: space-between; padding: 8px 10px; background: var(--color-subtle); border-radius: var(--radius-md); margin-bottom: 6px; }
.panel-recipe-name { font-size: 12px; font-weight: 500; }
.panel-recipe-day { font-size: 10px; color: var(--color-text-muted); }
.btn-swap-primary { display: flex; align-items: center; justify-content: center; gap: 6px; padding: 9px 16px; background: var(--green-dark); color: white; border-radius: var(--radius-md); font-size: 12px; font-weight: 500; border: none; cursor: pointer; width: 100%; margin-top: 12px; }
.btn-swap-primary:hover { background: var(--green); }
.panel-hint { font-size: 11px; color: var(--color-text-muted); margin-top: 8px; }
.panel-empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 8px; }
.panel-empty-icon { font-size: 24px; opacity: .4; }
.panel-empty-text { font-size: 12px; color: var(--color-text-muted); }
/* ── Mobile ── */
.m-shell { display: flex; flex-direction: column; background: var(--color-page); }
.m-topbar { display: flex; align-items: center; gap: 10px; border-bottom: 1px solid var(--color-border); background: var(--color-page); padding: 12px 16px; position: sticky; top: 0; z-index: 10; }
.m-back { font-size: 20px; color: var(--color-text-muted); }
.m-title { font-family: var(--font-display); font-size: 16px; font-weight: 300; }
.m-content { flex: 1; padding: 16px; overflow-y: auto; }
.m-score-hero { display: flex; align-items: baseline; gap: 4px; margin-bottom: 16px; }
.m-score-num { font-family: var(--font-display); font-size: 52px; font-weight: 300; line-height: 1; }
.m-score-denom { font-family: var(--font-display); font-size: 20px; font-weight: 300; color: var(--color-text-muted); }
.m-score-bar { height: 5px; background: var(--color-subtle); border-radius: var(--radius-full); overflow: hidden; margin-bottom: 4px; }
.m-score-fill { height: 100%; border-radius: var(--radius-full); background: var(--yellow); }
.m-score-label { font-size: 12px; font-weight: 500; color: var(--yellow-text); margin-bottom: 16px; }
.m-section-hd { font-size: 9px; font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-text-muted); margin-bottom: 8px; }
.m-warn-card { background: var(--yellow-tint); border: 1px solid var(--yellow-light); border-radius: var(--radius-lg); padding: 12px 14px; margin-bottom: 8px; }
.m-warn-title { font-size: 12px; font-weight: 500; color: var(--yellow-text); margin-bottom: 6px; }
.m-pill-row { display: flex; flex-wrap: wrap; gap: 6px; }
.m-pill { display: inline-flex; align-items: center; gap: 5px; padding: 4px 8px 4px 10px; background: white; border: 1px solid var(--yellow-light); border-radius: var(--radius-full); font-size: 11px; font-weight: 500; }
.m-pill-swap { width: 18px; height: 18px; border-radius: 50%; background: var(--color-subtle); display: flex; align-items: center; justify-content: center; font-size: 10px; flex-shrink: 0; }
.m-tabbar { display: flex; border-top: 1px solid var(--color-border); background: white; }
.m-tab { flex: 1; display: flex; flex-direction: column; align-items: center; padding: 8px 4px 4px; font-size: 10px; color: var(--color-text-muted); gap: 2px; }
.m-tab.active { color: var(--green-dark); }
.m-tab-icon { font-size: 20px; }
/* Agent section */
.agent-section { background: var(--color-text); color: #E8E8E2; padding: 40px 48px; margin-top: 64px; }
.agent-section h2 { font-size: 10px; font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase; color: #6B6A63; margin-bottom: 4px; }
.agent-section > p { font-size: 13px; color: #9A9990; margin-bottom: 28px; line-height: 1.6; max-width: 640px; }
.spec-comment { font-family: var(--font-mono); font-size: 11px; color: #3A3A36; margin-bottom: 32px; line-height: 1.9; white-space: pre-wrap; }
.agent-table { width: 100%; border-collapse: collapse; font-family: var(--font-mono); font-size: 11px; margin-bottom: 40px; }
.agent-table thead tr { border-bottom: 1px solid #2A2A26; }
.agent-table th { text-align: left; padding: 8px 14px; font-size: 9px; font-weight: 500; letter-spacing: 0.09em; text-transform: uppercase; color: #5A5A55; font-family: var(--font-sans); }
.agent-table td { padding: 9px 14px; border-bottom: 1px solid #1E1E1A; vertical-align: top; line-height: 1.5; }
.agent-table tr:last-child td { border-bottom: none; }
.agent-table td:first-child { color: #7A7A72; white-space: nowrap; }
.agent-table td:nth-child(2) { color: #E8E8E2; font-weight: 500; }
.agent-table td:nth-child(3) { color: #5A5A55; }
.group-row td { padding-top: 20px; font-family: var(--font-sans); font-size: 9px; font-weight: 500; letter-spacing: 0.09em; text-transform: uppercase; color: #3A3A36; border-bottom: none; }
</style>
</head>
<body>
<div class="doc">
<div class="doc-header">
<div>
<h1>Variety Page — Rework</h1>
<p>3 Design-Variationen · Route: <code>/planner/variety</code></p>
</div>
<div class="doc-meta">
screen: C2<br/>
journey: J4<br/>
version: 1.0<br/>
date: 2026-04-09
</div>
</div>
<p class="intro">
Zwei Kernprobleme werden adressiert: (1) Warnungen zeigen aktuell Wochentag-Kürzel ("MON, WED")
statt Rezeptnamen — rein frontend-seitig lösbar über <code>weekPlan.slots</code>-Mapping.
(2) Es gibt keine Swap-Aktion direkt aus den Warnungen heraus. Das Protein-Score-Problem
für vegetarische Haushalte ist ein Backend-Thema und separat zu behandeln.
</p>
<div class="notice">
<h3>Protein-Score: Vegetarische Haushalte — Backend TBD</h3>
<p>
Die aktuelle Formel <code>proteinDiversity = 10 repeats × 2</code> bestraft vegetarische
Proteinquellen (Tofu, Linsen, Ei) stärker als in omnivoren Haushalten üblich.
Frontend-seitig ändert sich das Label "Protein-Vielfalt" ggf. zu "Quellen-Vielfalt" sobald
das Backend die Score-Gewichtung anpasst. Bis dahin: keine Änderung an <code>ScoreBreakdownList</code>.
</p>
</div>
<!-- ═══════════════════════════════════════════════════════ -->
<div class="section-label">V1 — Rezept-Pills in Warnkarten</div>
<div class="variation">
<div class="var-header">
<div class="var-num">1</div>
<div class="var-meta">
<div class="var-title">Rezept-Pills in Warnkarten</div>
<div class="var-desc">Minimale Änderung an der bestehenden Seitenstruktur. Warnkarten zeigen statt "MON, WED" konkrete Rezept-Pills mit Tauschen-Button. Seitenaufbau und Score-Hero bleiben identisch.</div>
<span class="var-tag">Vertraut · Geringer Aufwand</span>
</div>
</div>
<div class="preview-pair">
<div class="preview-d-wrap">
<div class="preview-label">Desktop</div>
<div class="preview-d-clip">
<div class="preview-d-scale">
<div class="shell" style="min-height:680px;">
<div class="sidebar">
<div class="sidebar-brand"><div class="sidebar-brand-row"><div class="sidebar-logo"></div><span class="sidebar-app">Mealplan</span></div><div class="sidebar-household">Familie Raddatz</div></div>
<div class="sidebar-nav">
<div class="sidebar-group-label">Plan</div>
<a class="sidebar-item active" href="#"><span class="sidebar-icon">📅</span>Planer</a>
<a class="sidebar-item" href="#"><span class="sidebar-icon">🍽</span>Rezepte</a>
<a class="sidebar-item" href="#"><span class="sidebar-icon">🛒</span>Einkauf</a>
</div>
</div>
<div style="flex:1;display:flex;flex-direction:column;overflow:hidden;">
<div class="topbar">
<a class="topbar-back" href="#">Planer</a>
<span class="topbar-sep">/</span>
<span class="topbar-title">Abwechslungs-Analyse</span>
</div>
<div class="main" style="display:flex;gap:32px;align-items:flex-start;overflow-y:auto;">
<!-- Left -->
<div style="flex:1;">
<div class="score-hero">
<div><span class="score-num" style="color:var(--yellow-text);">6.5</span><span class="score-denom">/10</span></div>
<div class="score-bar" style="width:200px;"><div class="score-fill warn" style="width:65%;"></div></div>
<div class="score-label">Verbesserbar</div>
</div>
<div class="section-hd">Bewertung im Detail</div>
<div class="sub-scores">
<div class="sub-row"><span class="sub-label">Quellen-Vielfalt</span><span class="sub-val">6/10</span></div>
<div class="sub-row"><span class="sub-label">Zutaten-Überlappung</span><span class="sub-val ok">8/10</span></div>
<div class="sub-row"><span class="sub-label">Aufwandsbalance</span><span class="sub-val ok">9/10</span></div>
</div>
<!-- Warnings with recipe pills -->
<div class="section-hd" style="margin-top:20px;">Hinweise</div>
<div class="warn-card">
<div class="warn-title">Tofu mehrfach diese Woche</div>
<div class="pill-row">
<span class="recipe-pill"><span class="recipe-pill-day">Mo</span>Tofu-Curry<button class="pill-swap-btn"></button></span>
<span class="recipe-pill"><span class="recipe-pill-day">Mi</span>Tofu-Bowl<button class="pill-swap-btn"></button></span>
</div>
</div>
<div class="warn-card">
<div class="warn-title">Linsen in mehreren Gerichten</div>
<div class="pill-row">
<span class="recipe-pill"><span class="recipe-pill-day">Di</span>Linsen-Suppe<button class="pill-swap-btn"></button></span>
<span class="recipe-pill"><span class="recipe-pill-day">Fr</span>Linsen-Dal<button class="pill-swap-btn"></button></span>
</div>
</div>
</div>
<!-- Right -->
<div style="width:280px;flex-shrink:0;">
<div class="section-hd">Quellen-Verteilung</div>
<div style="display:grid;grid-template-columns:repeat(7,1fr);gap:5px;margin-bottom:16px;">
<div style="display:flex;flex-direction:column;align-items:center;gap:3px;"><span style="font-size:9px;color:var(--color-text-muted);">Mo</span><div style="width:100%;height:40px;background:var(--yellow-tint);border:2px solid var(--yellow);border-radius:3px;display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:600;color:var(--yellow-text);">TOF</div></div>
<div style="display:flex;flex-direction:column;align-items:center;gap:3px;"><span style="font-size:9px;color:var(--color-text-muted);">Di</span><div style="width:100%;height:40px;background:var(--green-tint);border-radius:3px;display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:600;color:var(--green-dark);">LIN</div></div>
<div style="display:flex;flex-direction:column;align-items:center;gap:3px;"><span style="font-size:9px;color:var(--color-text-muted);">Mi</span><div style="width:100%;height:40px;background:var(--yellow-tint);border:2px solid var(--yellow);border-radius:3px;display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:600;color:var(--yellow-text);">TOF</div></div>
<div style="display:flex;flex-direction:column;align-items:center;gap:3px;"><span style="font-size:9px;color:var(--color-text-muted);">Do</span><div style="width:100%;height:40px;background:var(--green-tint);border-radius:3px;display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:600;color:var(--green-dark);">GEM</div></div>
<div style="display:flex;flex-direction:column;align-items:center;gap:3px;"><span style="font-size:9px;color:var(--color-text-muted);">Fr</span><div style="width:100%;height:40px;background:var(--yellow-tint);border:2px solid var(--yellow);border-radius:3px;display:flex;align-items:center;justify-content:center;font-size:9px;font-weight:600;color:var(--yellow-text);">LIN</div></div>
<div style="display:flex;flex-direction:column;align-items:center;gap:3px;"><span style="font-size:9px;color:var(--color-text-muted);">Sa</span><div style="width:100%;height:40px;background:var(--color-subtle);border-radius:3px;display:flex;align-items:center;justify-content:center;font-size:9px;color:var(--color-text-muted);"></div></div>
<div style="display:flex;flex-direction:column;align-items:center;gap:3px;"><span style="font-size:9px;color:var(--color-text-muted);">So</span><div style="width:100%;height:40px;background:var(--color-subtle);border-radius:3px;display:flex;align-items:center;justify-content:center;font-size:9px;color:var(--color-text-muted);"></div></div>
</div>
<div class="section-hd">Aufwandsverteilung</div>
<div style="display:flex;height:16px;border-radius:var(--radius-full);overflow:hidden;gap:2px;">
<div style="flex:3;background:var(--green-dark);"></div>
<div style="flex:2;background:var(--yellow);"></div>
</div>
<div style="display:flex;justify-content:space-between;margin-top:6px;font-size:10px;color:var(--color-text-muted);">
<span>Einfach ×3</span><span>Mittel ×2</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="preview-m-wrap">
<div class="preview-label">Mobile</div>
<div class="preview-m-clip">
<div class="preview-m-scale">
<div class="m-shell" style="min-height:680px;">
<div class="m-topbar"><span class="m-back"></span><span class="m-title">Abwechslungs-Analyse</span></div>
<div class="m-content">
<div class="m-score-hero"><span class="m-score-num" style="color:var(--yellow-text);">6.5</span><span class="m-score-denom">/10</span></div>
<div class="m-score-bar"><div class="m-score-fill" style="width:65%;"></div></div>
<div class="m-score-label">Verbesserbar</div>
<div class="m-section-hd">Hinweise</div>
<div class="m-warn-card">
<div class="m-warn-title">Tofu mehrfach diese Woche</div>
<div class="m-pill-row">
<span class="m-pill"><span style="font-size:9px;color:var(--color-text-muted);">Mo</span>Tofu-Curry<span class="m-pill-swap"></span></span>
<span class="m-pill"><span style="font-size:9px;color:var(--color-text-muted);">Mi</span>Tofu-Bowl<span class="m-pill-swap"></span></span>
</div>
</div>
<div class="m-warn-card">
<div class="m-warn-title">Linsen in mehreren Gerichten</div>
<div class="m-pill-row">
<span class="m-pill"><span style="font-size:9px;color:var(--color-text-muted);">Di</span>Linsen-Suppe<span class="m-pill-swap"></span></span>
<span class="m-pill"><span style="font-size:9px;color:var(--color-text-muted);">Fr</span>Linsen-Dal<span class="m-pill-swap"></span></span>
</div>
</div>
</div>
<div class="m-tabbar">
<div class="m-tab active"><div class="m-tab-icon">📅</div>Planer</div>
<div class="m-tab"><div class="m-tab-icon">🍽</div>Rezepte</div>
<div class="m-tab"><div class="m-tab-icon">🛒</div>Einkauf</div>
<div class="m-tab"><div class="m-tab-icon">⚙️</div>Einstellungen</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="notes">
<div class="notes-label">Notizen</div>
<ul>
<li>Kein Backend-Change nötig. Frontend mappt <code>tagRepeat.days[]</code><code>weekPlan.slots.find(s => s.dayOfWeek === day)</code><code>recipe.name</code></li>
<li>Pill-Swap-Button (↔): navigiert zu <code>/planner?week={weekStart}&amp;swap={slotId}</code> — öffnet RecipePicker für den betreffenden Slot</li>
<li>Pill-Label links: Wochentag-Kürzel (Mo, Di, …) aus <code>dayOfWeek</code>-Mapping</li>
<li>Wenn ein Slot leer ist (Rezept wurde bereits entfernt): Pill zeigt nur den Wochentag, kein Swap-Button</li>
<li>Geringe Änderung: nur <code>VarietyWarningCards.svelte</code> + <code>variety.ts</code> anpassen; Rest der Seite bleibt</li>
</ul>
</div>
</div>
<!-- ═══════════════════════════════════════════════════════ -->
<div class="section-label">V2 — Aktions-Zeilen (Action-first)</div>
<div class="variation">
<div class="var-header">
<div class="var-num">2</div>
<div class="var-meta">
<div class="var-title">Aktions-Zeilen</div>
<div class="var-desc">Warnungen stehen oben, Score-Hero wird kompakt. Pro Warnung gibt es eine vollständige Rezept-Zeile mit Wochentag und dediziertem "Tauschen"-Button. Fokus auf sofortige Handlung statt auf Metrik-Verständnis.</div>
<span class="var-tag rec">Empfohlen · Aktionsfokus</span>
</div>
</div>
<div class="preview-pair">
<div class="preview-d-wrap">
<div class="preview-label">Desktop</div>
<div class="preview-d-clip">
<div class="preview-d-scale">
<div class="shell" style="min-height:680px;">
<div class="sidebar">
<div class="sidebar-brand"><div class="sidebar-brand-row"><div class="sidebar-logo"></div><span class="sidebar-app">Mealplan</span></div><div class="sidebar-household">Familie Raddatz</div></div>
<div class="sidebar-nav">
<div class="sidebar-group-label">Plan</div>
<a class="sidebar-item active" href="#"><span class="sidebar-icon">📅</span>Planer</a>
<a class="sidebar-item" href="#"><span class="sidebar-icon">🍽</span>Rezepte</a>
<a class="sidebar-item" href="#"><span class="sidebar-icon">🛒</span>Einkauf</a>
</div>
</div>
<div style="flex:1;display:flex;flex-direction:column;overflow:hidden;">
<div class="topbar">
<a class="topbar-back" href="#">Planer</a>
<span class="topbar-sep">/</span>
<span class="topbar-title">Abwechslungs-Analyse</span>
</div>
<div class="main" style="overflow-y:auto;">
<!-- Compact score -->
<div class="score-compact">
<div><span class="score-compact-num" style="color:var(--yellow-text);">6.5</span><span class="score-compact-denom">/10</span></div>
<div class="score-compact-right">
<div class="score-compact-label">Verbesserbar — 2 Hinweise</div>
<div class="score-compact-bar"><div class="score-compact-fill" style="width:65%;"></div></div>
</div>
</div>
<div style="display:flex;gap:24px;align-items:flex-start;">
<div style="flex:1;">
<div class="section-hd">Empfehlenswerte Tausche</div>
<!-- Action row 1 -->
<div class="action-row">
<div class="action-icon">🔄</div>
<div class="action-body">
<div class="action-title">Tofu mehrfach diese Woche</div>
<div class="action-recipe-row">
<span><span class="action-recipe-name">Tofu-Curry</span><span class="action-recipe-day">· Montag</span></span>
<button class="btn-swap">Tauschen →</button>
</div>
<div class="action-recipe-row">
<span><span class="action-recipe-name">Tofu-Bowl</span><span class="action-recipe-day">· Mittwoch</span></span>
<button class="btn-swap">Tauschen →</button>
</div>
</div>
</div>
<!-- Action row 2 -->
<div class="action-row">
<div class="action-icon">🔄</div>
<div class="action-body">
<div class="action-title">Linsen in mehreren Gerichten</div>
<div class="action-recipe-row">
<span><span class="action-recipe-name">Linsen-Suppe</span><span class="action-recipe-day">· Dienstag</span></span>
<button class="btn-swap">Tauschen →</button>
</div>
<div class="action-recipe-row">
<span><span class="action-recipe-name">Linsen-Dal</span><span class="action-recipe-day">· Freitag</span></span>
<button class="btn-swap">Tauschen →</button>
</div>
</div>
</div>
<!-- Collapsible detail scores -->
<details style="margin-top:16px;">
<summary style="font-size:10px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--color-text-muted);cursor:pointer;list-style:none;padding:8px 0;">Bewertung im Detail ▾</summary>
<div class="sub-scores" style="margin-top:10px;">
<div class="sub-row"><span class="sub-label">Quellen-Vielfalt</span><span class="sub-val">6/10</span></div>
<div class="sub-row"><span class="sub-label">Zutaten-Überlappung</span><span class="sub-val ok">8/10</span></div>
<div class="sub-row"><span class="sub-label">Aufwandsbalance</span><span class="sub-val ok">9/10</span></div>
</div>
</details>
</div>
<div style="width:240px;flex-shrink:0;">
<div class="section-hd">Quellen-Verteilung</div>
<div style="display:grid;grid-template-columns:repeat(7,1fr);gap:4px;margin-bottom:12px;">
<div style="display:flex;flex-direction:column;align-items:center;gap:2px;"><span style="font-size:9px;color:var(--color-text-muted);">Mo</span><div style="width:100%;height:36px;background:var(--yellow-tint);border:2px solid var(--yellow);border-radius:3px;display:flex;align-items:center;justify-content:center;font-size:8px;font-weight:600;color:var(--yellow-text);">TOF</div></div>
<div style="display:flex;flex-direction:column;align-items:center;gap:2px;"><span style="font-size:9px;color:var(--color-text-muted);">Di</span><div style="width:100%;height:36px;background:var(--green-tint);border-radius:3px;display:flex;align-items:center;justify-content:center;font-size:8px;font-weight:600;color:var(--green-dark);">LIN</div></div>
<div style="display:flex;flex-direction:column;align-items:center;gap:2px;"><span style="font-size:9px;color:var(--color-text-muted);">Mi</span><div style="width:100%;height:36px;background:var(--yellow-tint);border:2px solid var(--yellow);border-radius:3px;display:flex;align-items:center;justify-content:center;font-size:8px;font-weight:600;color:var(--yellow-text);">TOF</div></div>
<div style="display:flex;flex-direction:column;align-items:center;gap:2px;"><span style="font-size:9px;color:var(--color-text-muted);">Do</span><div style="width:100%;height:36px;background:var(--green-tint);border-radius:3px;display:flex;align-items:center;justify-content:center;font-size:8px;font-weight:600;color:var(--green-dark);">GEM</div></div>
<div style="display:flex;flex-direction:column;align-items:center;gap:2px;"><span style="font-size:9px;color:var(--color-text-muted);">Fr</span><div style="width:100%;height:36px;background:var(--yellow-tint);border:2px solid var(--yellow);border-radius:3px;display:flex;align-items:center;justify-content:center;font-size:8px;font-weight:600;color:var(--yellow-text);">LIN</div></div>
<div style="display:flex;flex-direction:column;align-items:center;gap:2px;"><span style="font-size:9px;color:var(--color-text-muted);">Sa</span><div style="width:100%;height:36px;background:var(--color-subtle);border-radius:3px;"></div></div>
<div style="display:flex;flex-direction:column;align-items:center;gap:2px;"><span style="font-size:9px;color:var(--color-text-muted);">So</span><div style="width:100%;height:36px;background:var(--color-subtle);border-radius:3px;"></div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="preview-m-wrap">
<div class="preview-label">Mobile</div>
<div class="preview-m-clip">
<div class="preview-m-scale">
<div class="m-shell" style="min-height:680px;">
<div class="m-topbar"><span class="m-back"></span><span class="m-title">Abwechslungs-Analyse</span></div>
<div class="m-content">
<!-- Compact score mobile -->
<div style="display:flex;align-items:center;gap:12px;padding:12px 14px;background:white;border:1px solid var(--color-border);border-radius:var(--radius-lg);margin-bottom:16px;">
<div><span style="font-family:var(--font-display);font-size:32px;font-weight:300;color:var(--yellow-text);">6.5</span><span style="font-family:var(--font-display);font-size:14px;font-weight:300;color:var(--color-text-muted);">/10</span></div>
<div style="flex:1;"><div style="font-size:11px;font-weight:500;color:var(--yellow-text);margin-bottom:4px;">Verbesserbar</div><div style="height:4px;background:var(--color-subtle);border-radius:99px;overflow:hidden;"><div style="width:65%;height:100%;background:var(--yellow);border-radius:99px;"></div></div></div>
</div>
<div class="m-section-hd">Empfehlenswerte Tausche</div>
<!-- Action row mobile -->
<div style="background:white;border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:12px;margin-bottom:8px;">
<div style="font-size:12px;font-weight:500;margin-bottom:8px;">🔄 Tofu mehrfach diese Woche</div>
<div style="display:flex;align-items:center;justify-content:space-between;padding:6px 8px;background:var(--color-subtle);border-radius:var(--radius-md);margin-bottom:4px;"><span style="font-size:11px;font-weight:500;">Tofu-Curry <span style="color:var(--color-text-muted);font-weight:400;">Mo</span></span><button style="font-size:10px;font-weight:500;padding:3px 8px;background:white;border:1px solid var(--color-border);border-radius:var(--radius-md);color:var(--color-text-muted);">Tauschen →</button></div>
<div style="display:flex;align-items:center;justify-content:space-between;padding:6px 8px;background:var(--color-subtle);border-radius:var(--radius-md);"><span style="font-size:11px;font-weight:500;">Tofu-Bowl <span style="color:var(--color-text-muted);font-weight:400;">Mi</span></span><button style="font-size:10px;font-weight:500;padding:3px 8px;background:white;border:1px solid var(--color-border);border-radius:var(--radius-md);color:var(--color-text-muted);">Tauschen →</button></div>
</div>
<div style="background:white;border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:12px;margin-bottom:8px;">
<div style="font-size:12px;font-weight:500;margin-bottom:8px;">🔄 Linsen in mehreren Gerichten</div>
<div style="display:flex;align-items:center;justify-content:space-between;padding:6px 8px;background:var(--color-subtle);border-radius:var(--radius-md);margin-bottom:4px;"><span style="font-size:11px;font-weight:500;">Linsen-Suppe <span style="color:var(--color-text-muted);font-weight:400;">Di</span></span><button style="font-size:10px;font-weight:500;padding:3px 8px;background:white;border:1px solid var(--color-border);border-radius:var(--radius-md);color:var(--color-text-muted);">Tauschen →</button></div>
<div style="display:flex;align-items:center;justify-content:space-between;padding:6px 8px;background:var(--color-subtle);border-radius:var(--radius-md);"><span style="font-size:11px;font-weight:500;">Linsen-Dal <span style="color:var(--color-text-muted);font-weight:400;">Fr</span></span><button style="font-size:10px;font-weight:500;padding:3px 8px;background:white;border:1px solid var(--color-border);border-radius:var(--radius-md);color:var(--color-text-muted);">Tauschen →</button></div>
</div>
</div>
<div class="m-tabbar">
<div class="m-tab active"><div class="m-tab-icon">📅</div>Planer</div>
<div class="m-tab"><div class="m-tab-icon">🍽</div>Rezepte</div>
<div class="m-tab"><div class="m-tab-icon">🛒</div>Einkauf</div>
<div class="m-tab"><div class="m-tab-icon">⚙️</div>Einstellungen</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="notes">
<div class="notes-label">Notizen</div>
<ul>
<li>Score-Hero wird kompakt: Zahl + Label + Balken in einer horizontal komprimierten Leiste oben</li>
<li>Sub-Scores in aufklappbarem <code>&lt;details&gt;</code>-Element — zugänglich, kein JavaScript nötig</li>
<li>Jeder "Tauschen"-Button navigiert zum Planer mit dem spezifischen Slot vorselektiert</li>
<li>Wochentag als ausgeschriebenes Wort ("Montag") — nicht Kürzel — für bessere Lesbarkeit</li>
<li>Mobile: Score-Hero bleibt kompakt oben, Action-Rows nehmen den Hauptraum ein</li>
<li>Größerer Aufwand als V1: <code>VarietyWarningCards</code> grundlegend neu strukturieren</li>
</ul>
</div>
</div>
<!-- ═══════════════════════════════════════════════════════ -->
<div class="section-label">V3 — Wochenraster mit Kontext-Panel</div>
<div class="variation">
<div class="var-header">
<div class="var-num">3</div>
<div class="var-meta">
<div class="var-title">Wochenraster mit Kontext-Panel</div>
<div class="var-desc">Das bestehende Protein-Raster wird zum Haupt-Interface. Alle 7 Tage zeigen das vollständige Rezept. Problematische Slots sind gelb markiert — Klick öffnet das rechte Panel mit Erklärung und Swap-CTA.</div>
<span class="var-tag amb">Ambitiös · Meiste Übersicht</span>
</div>
</div>
<div class="preview-pair">
<div class="preview-d-wrap">
<div class="preview-label">Desktop</div>
<div class="preview-d-clip">
<div class="preview-d-scale">
<div class="shell" style="min-height:680px;">
<div class="sidebar">
<div class="sidebar-brand"><div class="sidebar-brand-row"><div class="sidebar-logo"></div><span class="sidebar-app">Mealplan</span></div><div class="sidebar-household">Familie Raddatz</div></div>
<div class="sidebar-nav">
<div class="sidebar-group-label">Plan</div>
<a class="sidebar-item active" href="#"><span class="sidebar-icon">📅</span>Planer</a>
<a class="sidebar-item" href="#"><span class="sidebar-icon">🍽</span>Rezepte</a>
<a class="sidebar-item" href="#"><span class="sidebar-icon">🛒</span>Einkauf</a>
</div>
</div>
<div style="flex:1;display:flex;flex-direction:column;overflow:hidden;">
<div class="topbar">
<a class="topbar-back" href="#">Planer</a>
<span class="topbar-sep">/</span>
<span class="topbar-title">Abwechslungs-Analyse</span>
<!-- Score badge in topbar -->
<div style="margin-left:auto;display:flex;align-items:center;gap:8px;">
<span style="font-size:11px;color:var(--color-text-muted);">Abwechslung</span>
<span style="font-family:var(--font-display);font-size:20px;font-weight:300;color:var(--yellow-text);">6.5</span>
<span style="font-family:var(--font-display);font-size:12px;color:var(--color-text-muted);">/10</span>
</div>
</div>
<div style="display:flex;flex:1;overflow:hidden;">
<!-- Main: week grid -->
<div class="v3-main">
<div class="section-hd">Wochenübersicht — gelb markierte Gerichte haben Hinweise</div>
<div class="week-grid">
<!-- Mon - Tofu-Curry WARN -->
<div class="day-col">
<div class="day-header">Mo</div>
<div class="recipe-slot warn selected">Tofu-Curry</div>
</div>
<!-- Tue - Linsen-Suppe WARN -->
<div class="day-col">
<div class="day-header">Di</div>
<div class="recipe-slot warn">Linsen-Suppe</div>
</div>
<!-- Wed - Tofu-Bowl WARN -->
<div class="day-col">
<div class="day-header">Mi</div>
<div class="recipe-slot warn">Tofu-Bowl</div>
</div>
<!-- Thu - Gemüse OK -->
<div class="day-col">
<div class="day-header">Do</div>
<div class="recipe-slot">Gemüse-Stir-Fry</div>
</div>
<!-- Fri - Linsen-Dal WARN -->
<div class="day-col">
<div class="day-header">Fr</div>
<div class="recipe-slot warn">Linsen-Dal</div>
</div>
<!-- Sat - empty -->
<div class="day-col">
<div class="day-header">Sa</div>
<div class="recipe-slot empty"></div>
</div>
<!-- Sun - empty -->
<div class="day-col">
<div class="day-header">So</div>
<div class="recipe-slot empty"></div>
</div>
</div>
<div class="section-hd" style="margin-top:16px;">Aufwandsverteilung</div>
<div style="display:flex;height:18px;border-radius:var(--radius-full);overflow:hidden;gap:2px;max-width:280px;">
<div style="flex:3;background:var(--green-dark);"></div>
<div style="flex:2;background:var(--yellow);"></div>
</div>
<div style="display:flex;gap:16px;margin-top:6px;font-size:11px;color:var(--color-text-muted);">
<span>Einfach ×3</span><span>Mittel ×2</span>
</div>
<div class="sub-scores" style="margin-top:20px;max-width:360px;">
<div class="sub-row"><span class="sub-label">Quellen-Vielfalt</span><span class="sub-val">6/10</span></div>
<div class="sub-row"><span class="sub-label">Zutaten-Überlappung</span><span class="sub-val ok">8/10</span></div>
<div class="sub-row"><span class="sub-label">Aufwandsbalance</span><span class="sub-val ok">9/10</span></div>
</div>
</div>
<!-- Right panel: context for selected slot -->
<div class="v3-panel">
<div class="panel-score">
<span class="panel-score-num" style="color:var(--yellow-text);">6.5</span>
<span class="panel-score-denom">/10</span>
</div>
<div class="panel-warn-title">Tofu-Curry — Montag</div>
<div class="panel-warn-desc">Tofu taucht diese Woche auch am Mittwoch auf (Tofu-Bowl). Ein Tausch würde die Quellen-Vielfalt verbessern.</div>
<div class="section-hd">Andere betroffene Gerichte</div>
<div class="panel-recipe-entry">
<div><div class="panel-recipe-name">Tofu-Bowl</div><div class="panel-recipe-day">Mittwoch</div></div>
</div>
<button class="btn-swap-primary">↔ Tofu-Curry tauschen</button>
<div class="panel-hint">Öffnet den Rezept-Picker für Montag.</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="preview-m-wrap">
<div class="preview-label">Mobile (Tab-Navigation)</div>
<div class="preview-m-clip">
<div class="preview-m-scale">
<div class="m-shell" style="min-height:680px;">
<div class="m-topbar"><span class="m-back"></span><span class="m-title">Abwechslungs-Analyse</span><span style="margin-left:auto;font-family:var(--font-display);font-size:18px;font-weight:300;color:var(--yellow-text);">6.5<span style="font-size:12px;color:var(--color-text-muted);">/10</span></span></div>
<div class="m-content">
<!-- Tab switcher for mobile (Übersicht | Hinweise) -->
<div style="display:flex;border:1px solid var(--color-border);border-radius:var(--radius-md);overflow:hidden;margin-bottom:14px;">
<button style="flex:1;padding:7px;font-size:11px;font-weight:500;background:var(--color-subtle);color:var(--color-text-muted);border:none;">Übersicht</button>
<button style="flex:1;padding:7px;font-size:11px;font-weight:500;background:var(--green-dark);color:white;border:none;">Hinweise (2)</button>
</div>
<!-- Hinweise tab active -->
<div style="background:white;border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:14px;margin-bottom:10px;">
<div style="font-size:12px;font-weight:500;margin-bottom:8px;color:var(--yellow-text);">Tofu mehrfach diese Woche</div>
<div style="display:flex;align-items:center;justify-content:space-between;padding:7px 10px;background:var(--yellow-tint);border:1px solid var(--yellow-light);border-radius:var(--radius-md);margin-bottom:5px;"><span style="font-size:11px;font-weight:500;">Tofu-Curry <span style="color:var(--color-text-muted);font-weight:400;">Mo</span></span><button style="font-size:10px;font-weight:500;padding:4px 8px;background:var(--green-dark);color:white;border:none;border-radius:var(--radius-md);">Tauschen</button></div>
<div style="display:flex;align-items:center;justify-content:space-between;padding:7px 10px;background:var(--yellow-tint);border:1px solid var(--yellow-light);border-radius:var(--radius-md);"><span style="font-size:11px;font-weight:500;">Tofu-Bowl <span style="color:var(--color-text-muted);font-weight:400;">Mi</span></span><button style="font-size:10px;font-weight:500;padding:4px 8px;background:var(--green-dark);color:white;border:none;border-radius:var(--radius-md);">Tauschen</button></div>
</div>
<div style="background:white;border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:14px;">
<div style="font-size:12px;font-weight:500;margin-bottom:8px;color:var(--yellow-text);">Linsen in mehreren Gerichten</div>
<div style="display:flex;align-items:center;justify-content:space-between;padding:7px 10px;background:var(--yellow-tint);border:1px solid var(--yellow-light);border-radius:var(--radius-md);margin-bottom:5px;"><span style="font-size:11px;font-weight:500;">Linsen-Suppe <span style="color:var(--color-text-muted);font-weight:400;">Di</span></span><button style="font-size:10px;font-weight:500;padding:4px 8px;background:var(--green-dark);color:white;border:none;border-radius:var(--radius-md);">Tauschen</button></div>
<div style="display:flex;align-items:center;justify-content:space-between;padding:7px 10px;background:var(--yellow-tint);border:1px solid var(--yellow-light);border-radius:var(--radius-md);"><span style="font-size:11px;font-weight:500;">Linsen-Dal <span style="color:var(--color-text-muted);font-weight:400;">Fr</span></span><button style="font-size:10px;font-weight:500;padding:4px 8px;background:var(--green-dark);color:white;border:none;border-radius:var(--radius-md);">Tauschen</button></div>
</div>
</div>
<div class="m-tabbar">
<div class="m-tab active"><div class="m-tab-icon">📅</div>Planer</div>
<div class="m-tab"><div class="m-tab-icon">🍽</div>Rezepte</div>
<div class="m-tab"><div class="m-tab-icon">🛒</div>Einkauf</div>
<div class="m-tab"><div class="m-tab-icon">⚙️</div>Einstellungen</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="notes">
<div class="notes-label">Notizen</div>
<ul>
<li>Wochenraster ersetzt das bisherige Protein-Grid (7 Spalten, Rezeptname statt Kürzel, größere Zellen)</li>
<li>Gelber Slot = mindestens ein Hinweis vorhanden. Klick selektiert den Slot, Panel rechts aktualisiert sich.</li>
<li>Panel zeigt: betroffenes Rezept + Wochentag + Erklärung + andere betroffene Slots + primären "Tauschen"-Button</li>
<li>Score-Zahl wandert in die Topbar-Leiste (kompakt, immer sichtbar)</li>
<li>Mobile: kein Panel — stattdessen Tab-Switcher "Übersicht | Hinweise (N)" mit aufklappbaren Einträgen</li>
<li>Größter Umbau: <code>+page.svelte</code> Struktur und alle beteiligten Komponenten müssen neu aufgebaut werden</li>
</ul>
</div>
</div>
<!-- ─── Agent section ─── -->
<div class="agent-section">
<h2>Maschinen-lesbare Spezifikation</h2>
<p>Gilt für alle drei Variationen. Implementierungs-Details werden nach Variantenwahl konkretisiert.</p>
<pre class="spec-comment">
/* spec:rules — Variety Page Rework (alle Variationen)
*
* RECIPE NAME MAPPING (frontend, no backend change)
* Source: weekPlan.slots[] → { dayOfWeek: "MON"|"TUE"|..., recipe: { id, name } }
* tagRepeats[].days[] contains dayOfWeek keys (e.g. "MON")
* slotsByDay = Object.fromEntries(weekPlan.slots.map(s => [s.dayOfWeek, s]))
* recipeName = slotsByDay[day]?.recipe?.name ?? day
* slotId = slotsByDay[day]?.id
*
* SWAP NAVIGATION
* "Tauschen" button href: /planner?week={weekStart}&swap={slotId}
* weekStart available in page data
* slotId from weekPlan.slots mapping above
* Opens RecipePicker for that slot (existing functionality in planner page)
*
* DAY LABEL MAPPING (for display)
* MON → "Montag" TUE → "Dienstag" WED → "Mittwoch" THU → "Donnerstag"
* FRI → "Freitag" SAT → "Samstag" SUN → "Sonntag"
* Short: Mo, Di, Mi, Do, Fr, Sa, So
*
* EMPTY SLOT HANDLING
* If slotsByDay[day] is undefined: show day key only, no swap button
* This can happen if slot was deleted since varietyScore was computed
*
* PROTEIN SCORE — VEGETARIAN NOTE
* Label "Protein-Vielfalt" in ScoreBreakdownList may change to "Quellen-Vielfalt"
* pending backend decision on scoring weight adjustment.
* No frontend change required until backend ships the updated score.
*
* VARIATION-SPECIFIC
* V1: Modify VarietyWarningCards + Warning type (add slots: { day, recipeName, slotId }[])
* computeWarnings() now returns slots[] instead of string days[]
* V2: Restructure VarietyWarningCards to ActionRows; VarietyScoreHero → compact variant
* <details> for sub-scores (no JS needed)
* V3: Replace protein grid with full week grid (recipe names); add side panel component
* Mobile: tab switcher (Übersicht | Hinweise) using $state activeTab
*/
</pre>
<table class="agent-table">
<thead>
<tr><th>Property</th><th>Value</th><th>Notes</th></tr>
</thead>
<tbody>
<tr class="group-row"><td colspan="3">Shared: Recipe Mapping</td></tr>
<tr><td>data-source</td><td>weekPlan.slots[].dayOfWeek + recipe</td><td>already in page data</td></tr>
<tr><td>swap-url</td><td>/planner?week={weekStart}&amp;swap={slotId}</td><td>RecipePicker pre-selects slot</td></tr>
<tr><td>day-long</td><td>MON→Montag, TUE→Dienstag…</td><td>for V2 display</td></tr>
<tr><td>day-short</td><td>MON→Mo, TUE→Di…</td><td>for V1 pills + V3 grid</td></tr>
<tr class="group-row"><td colspan="3">V1 Recipe Pills</td></tr>
<tr><td>pill-padding</td><td>5px 10px 5px 12px</td><td>left more for text</td></tr>
<tr><td>swap-btn-size</td><td>22×22px, border-radius 50%</td><td>within pill</td></tr>
<tr><td>pill-bg</td><td>white, border --yellow-light</td><td>on yellow-tint card</td></tr>
<tr class="group-row"><td colspan="3">V2 Action Rows</td></tr>
<tr><td>score-compact-height</td><td>~64px</td><td>replaces 180px hero</td></tr>
<tr><td>details-summary</td><td>native &lt;details&gt;, no JS</td><td>sub-scores hidden by default</td></tr>
<tr><td>recipe-row-bg</td><td>--color-subtle</td><td>within white action card</td></tr>
<tr class="group-row"><td colspan="3">V3 Week Grid</td></tr>
<tr><td>slot-height</td><td>52px min</td><td>enough for 2-line recipe name</td></tr>
<tr><td>warn-slot-ring</td><td>2px solid --yellow + yellow-tint bg</td><td>problem indicator</td></tr>
<tr><td>selected-slot-ring</td><td>2px solid --green-dark</td><td>active selection</td></tr>
<tr><td>panel-width</td><td>280px</td><td>fixed, right side</td></tr>
<tr><td>mobile-tab-active-bg</td><td>--green-dark</td><td>selected tab button</td></tr>
</tbody>
</table>
</div>
</div>
</body>
</html>