Files
mealprep/specs/planner-c-e-combined.html
Marcel Raddatz 520dae5adf feat(recipes): add image upload, fix save 500, seed HelloFresh data
- 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>
2026-04-09 20:23:28 +02:00

756 lines
46 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>Planner C+E — Drei Zustände</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 {
--page: #fafaf7;
--surface: #f5f4ee;
--subtle: #edecea;
--border: #d8d7d0;
--text: #1c1c18;
--muted: #6b6a63;
--gt: #e8f5ea; --gl: #aedcb0; --g: #3d8c4a; --gd: #2e6e39;
--yt: #fdf6d8; --yl: #f9e08a; --y: #f2c12e; --yx: #8a6800;
--pt: #eeedfe; --p: #534ab7;
--ot: #fef0e6; --o: #e8862a; --od: #b46820;
--err: #dc4c3e;
--r-sm: 4px; --r-md: 6px; --r-lg: 10px; --r-xl: 16px; --r-full: 9999px;
--sh-card: 0 1px 3px rgba(28,28,24,.06),0 1px 2px rgba(28,28,24,.04);
--sh-raised: 0 4px 12px rgba(28,28,24,.08),0 2px 4px rgba(28,28,24,.04);
--fd: 'Fraunces', Georgia, serif;
--fs: 'DM Sans', system-ui, sans-serif;
--fm: 'DM Mono', monospace;
}
*{box-sizing:border-box;margin:0;padding:0;}
body{font-family:var(--fs);background:#dddcd7;color:var(--text);padding:40px 24px 80px;line-height:1.4;}
/* ── Page chrome ─── */
.eyebrow{font-family:var(--fs);font-size:11px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin-bottom:6px;}
.title{font-family:var(--fd);font-size:34px;font-weight:300;margin-bottom:6px;}
.sub{font-family:var(--fs);font-size:14px;color:var(--muted);max-width:700px;line-height:1.65;margin-bottom:20px;}
.flow-legend{display:flex;gap:20px;margin-bottom:44px;flex-wrap:wrap;}
.fl-item{display:flex;align-items:center;gap:8px;font-family:var(--fs);font-size:12px;color:var(--muted);}
.fl-dot{width:10px;height:10px;border-radius:50%;}
/* ── Frame chrome ─── */
.state-block{margin-bottom:60px;}
.state-label{display:flex;align-items:center;gap:10px;margin-bottom:12px;}
.state-num{font-family:var(--fm);font-size:11px;background:var(--subtle);color:var(--muted);padding:3px 8px;border-radius:var(--r-sm);}
.state-name{font-family:var(--fd);font-size:22px;font-weight:300;}
.state-when{font-family:var(--fs);font-size:12px;color:var(--muted);margin-left:auto;}
.note{font-family:var(--fs);font-size:12px;color:var(--muted);border-left:3px solid var(--border);padding:10px 14px;margin-top:14px;line-height:1.6;}
.note strong{color:var(--text);font-weight:500;}
/* ── Desktop frame ─── */
.frame{display:flex;flex-direction:column;background:var(--page);border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--sh-raised);}
/* Topbar */
.tb{display:flex;align-items:center;gap:7px;padding:11px 18px;border-bottom:1px solid var(--border);background:var(--page);flex-shrink:0;}
.tb-h1{font-family:var(--fd);font-size:17px;font-weight:300;}
.tb-range{font-family:var(--fs);font-size:11px;color:var(--muted);}
.tb-arr{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border:1px solid var(--border);border-radius:var(--r-md);font-size:13px;color:var(--muted);}
.tb-btn{height:28px;padding:0 10px;border:1px solid var(--border);border-radius:var(--r-md);font-family:var(--fs);font-size:11px;font-weight:500;letter-spacing:.04em;color:var(--text);background:var(--page);}
.tb-ml{margin-left:auto;}
.tb-pri{background:var(--gd);color:#fff;border:none;}
/* 3-panel body */
.body{display:flex;flex:1;overflow:hidden;}
/* Sidebar */
.sb{width:184px;flex-shrink:0;border-right:1px solid var(--border);background:var(--surface);padding:13px;display:flex;flex-direction:column;gap:13px;overflow-y:auto;}
.sb-lbl{font-family:var(--fs);font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin-bottom:5px;}
.score-box{background:var(--yt);border:1px solid var(--yl);border-radius:var(--r-md);padding:10px;}
.sc-big{font-family:var(--fd);font-size:27px;font-weight:300;line-height:1;}
.sc-den{font-family:var(--fs);font-size:11px;color:var(--muted);}
.pbar{height:4px;border-radius:var(--r-full);background:var(--yl);overflow:hidden;margin-top:6px;}
.pb-fill{height:100%;border-radius:var(--r-full);background:var(--y);}
.pbg{background:var(--g);}
.pbt{background:var(--border);}
.sr{display:flex;align-items:center;gap:6px;margin-top:6px;}
.sr-l{font-family:var(--fs);font-size:10px;color:var(--muted);width:68px;flex-shrink:0;}
.sr-b{flex:1;height:3px;border-radius:var(--r-full);background:var(--border);overflow:hidden;}
.sr-f{height:100%;border-radius:var(--r-full);}
.sr-v{font-family:var(--fm);font-size:9px;color:var(--muted);width:18px;text-align:right;}
.w-item{font-family:var(--fs);font-size:10px;color:var(--yx);margin-top:4px;line-height:1.4;}
.dp{display:flex;gap:2px;margin-top:5px;}
.dp-s{flex:1;height:4px;border-radius:var(--r-full);}
/* Right panel */
.rp{width:228px;flex-shrink:0;border-left:1px solid var(--border);background:var(--page);padding:13px;display:flex;flex-direction:column;overflow-y:auto;}
.rp-lbl{font-family:var(--fs);font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin-bottom:7px;}
.rp-name{font-family:var(--fd);font-size:16px;font-weight:300;line-height:1.35;}
.rp-meta{font-family:var(--fs);font-size:11px;color:var(--muted);margin-top:3px;}
.rp-btn{display:block;width:100%;padding:7px;border-radius:var(--r-md);border:1px solid var(--border);background:var(--page);font-family:var(--fs);font-size:11px;font-weight:500;letter-spacing:.04em;text-align:center;color:var(--text);margin-top:5px;}
.rp-pri{background:var(--gd);color:#fff;border:none;}
.rp-err{color:var(--err);border-color:var(--err);background:transparent;}
.hr{height:1px;background:var(--border);margin:10px 0;}
/* Main area */
.main{flex:1;overflow-y:auto;padding:13px;}
/* Calendar grid */
.grid7{display:grid;grid-template-columns:repeat(7,1fr);gap:6px;}
.d-abbr{font-family:var(--fs);font-size:9px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);text-align:center;margin-bottom:3px;}
.d-badge{width:20px;height:20px;border-radius:var(--r-full);display:flex;align-items:center;justify-content:center;font-family:var(--fs);font-size:10px;font-weight:500;margin:0 auto 5px;color:var(--text);}
.db-t{background:var(--y);color:#fff;}
.db-s{background:var(--gt);color:var(--gd);}
.tile{border-radius:var(--r-md);border:1px solid var(--border);background:var(--surface);padding:7px;cursor:pointer;box-shadow:var(--sh-card);}
.tile-t{border:2px solid var(--y);background:var(--yt);}
.tile-s{border:2px solid var(--g);background:var(--gt);}
.tile-e{border-style:dashed;background:transparent;display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--muted);gap:2px;}
.tile-e-s{border:2px dashed var(--g);background:var(--gt);}
.tr{font-family:var(--fd);font-size:11px;font-weight:300;color:var(--text);line-height:1.3;}
.tm{font-family:var(--fs);font-size:9px;color:var(--muted);margin-top:2px;}
.tbdg{display:inline-flex;align-items:center;padding:1px 4px;border-radius:2px;font-family:var(--fs);font-size:8px;font-weight:500;margin-top:3px;}
.b-e{background:var(--gt);color:var(--gd);}
.b-m{background:var(--yt);color:var(--yx);}
.b-h{background:var(--ot);color:var(--od);}
/* Section header */
.sec-hd{display:flex;align-items:center;justify-content:space-between;margin-bottom:9px;padding-bottom:7px;border-bottom:1px solid var(--border);}
.sec-t{font-family:var(--fs);font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);}
.sec-link{font-family:var(--fs);font-size:10px;font-weight:500;color:var(--yx);}
/* Agenda list */
.agenda{display:flex;flex-direction:column;gap:4px;}
.ag-item{display:flex;align-items:center;gap:10px;padding:7px 10px;border-radius:var(--r-md);border:1px solid var(--border);background:var(--surface);cursor:pointer;}
.ag-item:hover{border-color:var(--gl);}
.ag-t{border-style:dashed;background:transparent;}
.ag-t .ag-day{color:var(--muted);}
.ag-day{font-family:var(--fs);font-size:10px;color:var(--muted);width:48px;flex-shrink:0;}
.ag-name{font-family:var(--fd);font-size:13px;font-weight:300;flex:1;}
.ag-meta{font-family:var(--fs);font-size:10px;color:var(--muted);flex-shrink:0;}
.ag-action{font-family:var(--fs);font-size:10px;font-weight:500;color:var(--gd);flex-shrink:0;}
.ag-today-dot{width:6px;height:6px;border-radius:50%;background:var(--y);flex-shrink:0;}
.ag-item-today{border-color:var(--yl);background:var(--yt);}
/* Suggestions for empty days (in agenda / standalone) */
.sug-block{margin-top:14px;}
.sug-day-hd{display:flex;align-items:center;gap:6px;margin-bottom:6px;}
.sug-day-name{font-family:var(--fs);font-size:11px;font-weight:500;color:var(--text);}
.sug-empty-pill{font-family:var(--fs);font-size:9px;background:var(--subtle);color:var(--muted);padding:1px 6px;border-radius:var(--r-full);}
.sug-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;}
.sc-item{border:1px solid var(--border);border-radius:var(--r-md);background:var(--surface);padding:9px;cursor:pointer;transition:border-color .1s,box-shadow .1s;}
.sc-item:hover{border-color:var(--gl);box-shadow:var(--sh-raised);}
.sc-name{font-family:var(--fd);font-size:12px;font-weight:300;line-height:1.35;color:var(--text);}
.sc-meta{font-family:var(--fs);font-size:10px;color:var(--muted);margin-top:3px;}
.sc-tag{font-family:var(--fs);font-size:9px;font-weight:500;padding:2px 6px;border-radius:2px;margin-top:6px;display:inline-block;background:var(--gt);color:var(--gd);}
.sc-tag-y{background:var(--yt);color:var(--yx);}
.sc-add{display:flex;align-items:center;justify-content:center;height:100%;min-height:72px;border:1px dashed var(--border);border-radius:var(--r-md);font-family:var(--fs);font-size:11px;color:var(--muted);cursor:pointer;}
.sc-add:hover{border-color:var(--gl);color:var(--gd);}
/* Expansion panel */
.expand{border:2px solid var(--g);border-radius:var(--r-lg);background:var(--gt);padding:14px;display:flex;gap:14px;position:relative;margin-top:10px;}
.expand-empty{border:2px solid var(--g);border-radius:var(--r-lg);background:var(--gt);padding:14px;position:relative;margin-top:10px;}
.exp-arrow-wrap{display:grid;grid-template-columns:repeat(7,1fr);gap:6px;position:absolute;top:-8px;left:13px;right:13px;pointer-events:none;}
.exp-arrow{display:flex;justify-content:center;}
.exp-arr-shape{width:12px;height:12px;background:var(--gt);border-left:2px solid var(--g);border-top:2px solid var(--g);transform:rotate(45deg);}
.exp-arr-shape-e{background:var(--gt);}
.exp-left{flex:1;}
.exp-context{font-family:var(--fs);font-size:10px;font-weight:500;letter-spacing:.07em;text-transform:uppercase;color:var(--gd);margin-bottom:4px;}
.exp-name{font-family:var(--fd);font-size:22px;font-weight:300;line-height:1.25;}
.exp-meta{font-family:var(--fs);font-size:12px;color:var(--muted);margin-top:4px;}
.ing-wrap{display:flex;flex-wrap:wrap;gap:4px;margin-top:10px;}
.ing{font-family:var(--fs);font-size:10px;background:#fff;border:1px solid var(--border);border-radius:var(--r-full);padding:2px 8px;color:var(--text);}
.ing-s{background:var(--subtle);border-color:var(--subtle);color:var(--muted);}
.exp-badges{display:flex;gap:6px;margin-top:8px;flex-wrap:wrap;}
.exp-right{display:flex;flex-direction:column;gap:5px;width:118px;flex-shrink:0;}
.exp-btn{padding:7px;border-radius:var(--r-md);border:1px solid var(--border);background:#fff;font-family:var(--fs);font-size:11px;font-weight:500;text-align:center;cursor:pointer;letter-spacing:.04em;}
.exp-pri{background:var(--gd);color:#fff;border:none;}
.exp-err{color:var(--err);border-color:var(--err);background:transparent;}
/* Compact remaining below expansion */
.remaining{margin-top:10px;}
.rem-hd{font-family:var(--fs);font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin-bottom:6px;}
/* State 3: empty slot expansion */
.exp-sug-title{font-family:var(--fs);font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--gd);margin-bottom:10px;}
.exp-sug-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:7px;}
.exp-sc{border:1px solid var(--gl);border-radius:var(--r-md);background:#fff;padding:10px;cursor:pointer;}
.exp-sc:hover{box-shadow:var(--sh-raised);}
.exp-sc-name{font-family:var(--fd);font-size:13px;font-weight:300;line-height:1.3;color:var(--text);}
.exp-sc-meta{font-family:var(--fs);font-size:10px;color:var(--muted);margin-top:3px;}
.exp-sc-tag{font-family:var(--fs);font-size:9px;font-weight:500;padding:2px 6px;border-radius:2px;background:var(--gt);color:var(--gd);margin-top:6px;display:inline-block;}
.exp-all{font-family:var(--fs);font-size:11px;font-weight:500;color:var(--yx);margin-top:10px;display:block;}
/* Right panel: idle hint */
.rp-idle{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:6px;padding:16px;}
.rp-idle-t{font-family:var(--fs);font-size:12px;color:var(--text);}
.rp-idle-s{font-family:var(--fs);font-size:11px;color:var(--muted);max-width:150px;line-height:1.5;}
/* Right panel: today card */
.today-card{background:var(--yt);border:1px solid var(--yl);border-radius:var(--r-md);padding:10px;margin-bottom:10px;}
.tc-label{font-family:var(--fs);font-size:9px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--yx);margin-bottom:4px;}
.tc-name{font-family:var(--fd);font-size:14px;font-weight:300;line-height:1.3;}
.tc-meta{font-family:var(--fs);font-size:10px;color:var(--muted);margin-top:2px;}
/* Right panel: picker mode */
.picker-search{display:flex;align-items:center;gap:6px;background:var(--surface);border:1px solid var(--border);border-radius:var(--r-md);padding:6px 9px;margin-bottom:9px;}
.ps-icon{font-size:11px;color:var(--muted);}
.ps-text{font-family:var(--fs);font-size:11px;color:var(--muted);}
.pick-item{display:flex;align-items:center;gap:7px;padding:7px 0;border-bottom:1px solid var(--subtle);cursor:pointer;}
.pick-item:last-child{border-bottom:none;}
.pick-name{font-family:var(--fd);font-size:12px;font-weight:300;flex:1;line-height:1.3;}
.pick-meta{font-family:var(--fs);font-size:10px;color:var(--muted);}
</style>
</head>
<body>
<p class="eyebrow">Mealplan · Planer · Konzept</p>
<h1 class="title">C + E Kombiniert — Drei Zustände</h1>
<p class="sub">
Der Hauptbereich unterhalb des Kalender-Grids zeigt immer nützlichen Inhalt — je nach Zustand.
Kein leerer Raum, kein Tab-Wechsel nötig. Das rechte Panel bleibt für den Rezept-Picker reserviert.
</p>
<div class="flow-legend">
<div class="fl-item"><div class="fl-dot" style="background:var(--muted);"></div>Zustand 1 — Kein Tag ausgewählt</div>
<div class="fl-item"><div class="fl-dot" style="background:var(--g);"></div>Zustand 2 — Tag mit Rezept angeklickt</div>
<div class="fl-item"><div class="fl-dot" style="background:var(--yx);"></div>Zustand 3 — Leerer Tag angeklickt</div>
</div>
<!-- ══════════════════════════════════════════════════════════════ -->
<!-- ZUSTAND 1: KEIN TAG AUSGEWÄHLT -->
<!-- ══════════════════════════════════════════════════════════════ -->
<div class="state-block">
<div class="state-label">
<span class="state-num">Zustand 1</span>
<span class="state-name">Kein Tag ausgewählt</span>
<span class="state-when">Standard beim Laden der Seite</span>
</div>
<div class="frame" style="height:670px;">
<div class="tb">
<span class="tb-h1">Wochenplaner</span>
<span class="tb-range">7.13. Apr</span>
<div class="tb-arr"></div><div class="tb-arr"></div>
<button class="tb-btn">Heute</button>
<button class="tb-btn tb-ml tb-pri">+ Gericht hinzufügen</button>
</div>
<div class="body">
<!-- Sidebar -->
<div class="sb">
<div class="score-box">
<div class="sb-lbl">Abwechslungs-Score</div>
<div style="display:flex;align-items:baseline;gap:4px;"><span class="sc-big">7.8</span><span class="sc-den">/10</span></div>
<div class="pbar"><div class="pb-fill" style="width:78%;"></div></div>
<div class="sr"><span class="sr-l">Protein</span><div class="sr-b"><div class="sr-f" style="width:80%;background:var(--g);"></div></div><span class="sr-v">8.0</span></div>
<div class="sr"><span class="sr-l">Zutaten</span><div class="sr-b"><div class="sr-f" style="width:72%;background:var(--y);"></div></div><span class="sr-v">7.2</span></div>
<div class="sr"><span class="sr-l">Aufwand</span><div class="sr-b"><div class="sr-f" style="width:82%;background:var(--g);"></div></div><span class="sr-v">8.2</span></div>
<a style="display:block;margin-top:8px;font-family:var(--fs);font-size:10px;font-weight:500;color:var(--yx);">Variety-Analyse →</a>
</div>
<div>
<div class="sb-lbl">Überschneidungen</div>
<div class="w-item">⚠ Hähnchen an Mo + Do</div>
<div class="w-item">⚠ Tomaten an Di + Do</div>
</div>
<div>
<div class="sb-lbl">Geplant</div>
<div style="display:flex;align-items:baseline;gap:3px;"><span style="font-family:var(--fd);font-size:20px;font-weight:300;">5</span><span style="font-family:var(--fs);font-size:10px;color:var(--muted);">/ 7 Tage</span></div>
<div class="dp" style="margin-top:5px;">
<div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--border);"></div><div class="dp-s" style="background:var(--border);"></div>
</div>
</div>
</div>
<!-- Main area -->
<div class="main">
<!-- Calendar grid: no selection -->
<div class="grid7">
<div><div class="d-abbr">Mo</div><div class="d-badge">7</div><div class="tile" style="height:86px;"><p class="tr">Hähnchen-Curry</p><p class="tm">35 Min</p><span class="tbdg b-m">mittel</span></div></div>
<div><div class="d-abbr">Di</div><div class="d-badge db-t">8</div><div class="tile tile-t" style="height:86px;"><p class="tr">Pasta Bolognese</p><p class="tm">45 Min</p><span class="tbdg b-m">mittel</span></div></div>
<div><div class="d-abbr">Mi</div><div class="d-badge">9</div><div class="tile" style="height:86px;"><p class="tr">Gemüse-Stir-fry</p><p class="tm">20 Min</p><span class="tbdg b-e">einfach</span></div></div>
<div><div class="d-abbr">Do</div><div class="d-badge">10</div><div class="tile" style="height:86px;"><p class="tr">Lachs mit Kartoffeln</p><p class="tm">30 Min</p><span class="tbdg b-e">einfach</span></div></div>
<div><div class="d-abbr">Fr</div><div class="d-badge">11</div><div class="tile" style="height:86px;"><p class="tr">Pizza Margherita</p><p class="tm">50 Min</p><span class="tbdg b-h">aufwändig</span></div></div>
<div><div class="d-abbr">Sa</div><div class="d-badge">12</div><div class="tile tile-e" style="height:86px;"><span style="font-size:16px;">+</span><span style="font-family:var(--fs);font-size:9px;">wählen</span></div></div>
<div><div class="d-abbr">So</div><div class="d-badge">13</div><div class="tile tile-e" style="height:86px;"><span style="font-size:16px;">+</span><span style="font-family:var(--fs);font-size:9px;">wählen</span></div></div>
</div>
<!-- ▼ BELOW GRID: Agenda (all 7 days) ▼ -->
<div style="margin-top:16px;">
<div class="sec-hd">
<span class="sec-t">Diese Woche</span>
</div>
<div class="agenda">
<div class="ag-item">
<div class="ag-day">Mo 7.4</div>
<div class="ag-name">Hähnchen-Curry</div>
<div class="ag-meta">35 Min · mittel</div>
</div>
<div class="ag-item ag-item-today">
<div class="ag-today-dot"></div>
<div class="ag-day" style="color:var(--yx);">Di 8.4</div>
<div class="ag-name">Pasta Bolognese</div>
<div class="ag-meta">45 Min · mittel</div>
</div>
<div class="ag-item">
<div class="ag-day">Mi 9.4</div>
<div class="ag-name">Gemüse-Stir-fry</div>
<div class="ag-meta">20 Min · einfach</div>
</div>
<div class="ag-item">
<div class="ag-day">Do 10.4</div>
<div class="ag-name">Lachs mit Kartoffeln</div>
<div class="ag-meta">30 Min · einfach</div>
</div>
<div class="ag-item">
<div class="ag-day">Fr 11.4</div>
<div class="ag-name">Pizza Margherita</div>
<div class="ag-meta">50 Min · aufwändig</div>
</div>
<div class="ag-item ag-t">
<div class="ag-day">Sa 12.4</div>
<div class="ag-name" style="font-family:var(--fs);font-size:12px;color:var(--muted);">Noch kein Gericht</div>
<div class="ag-action">+ Hinzufügen</div>
</div>
<div class="ag-item ag-t">
<div class="ag-day">So 13.4</div>
<div class="ag-name" style="font-family:var(--fs);font-size:12px;color:var(--muted);">Noch kein Gericht</div>
<div class="ag-action">+ Hinzufügen</div>
</div>
</div>
</div>
<!-- ▼ BELOW AGENDA: Suggestions for empty days ▼ -->
<div style="margin-top:18px;">
<div class="sec-hd">
<span class="sec-t">Vorschläge für ungeplante Tage</span>
<a class="sec-link">Alle Rezepte →</a>
</div>
<!-- Sa -->
<div class="sug-block">
<div class="sug-day-hd">
<span class="sug-day-name">Samstag, 12. Apr</span>
<span class="sug-empty-pill">kein Gericht</span>
</div>
<div class="sug-cards">
<div class="sc-item">
<div class="sc-name">Ramen mit Ei</div>
<div class="sc-meta">40 Min · mittel</div>
<span class="sc-tag">Neues Protein</span>
</div>
<div class="sc-item">
<div class="sc-name">Shakshuka</div>
<div class="sc-meta">25 Min · einfach</div>
<span class="sc-tag">Keine Überschneidung</span>
</div>
<div class="sc-item">
<div class="sc-name">Rindfleisch-Tacos</div>
<div class="sc-meta">30 Min · einfach</div>
<span class="sc-tag sc-tag-y">Aufwand: einfach</span>
</div>
</div>
</div>
<!-- So -->
<div class="sug-block" style="margin-top:14px;">
<div class="sug-day-hd">
<span class="sug-day-name">Sonntag, 13. Apr</span>
<span class="sug-empty-pill">kein Gericht</span>
</div>
<div class="sug-cards">
<div class="sc-item">
<div class="sc-name">Pho Bo</div>
<div class="sc-meta">60 Min · aufwändig</div>
<span class="sc-tag">Neues Protein</span>
</div>
<div class="sc-item">
<div class="sc-name">Lachs-Avocado-Bowl</div>
<div class="sc-meta">15 Min · einfach</div>
<span class="sc-tag">Keine Überschneidung</span>
</div>
<div class="sc-item">
<div class="sc-name">Kürbissuppe</div>
<div class="sc-meta">35 Min · einfach</div>
<span class="sc-tag">Keine Überschneidung</span>
</div>
</div>
</div>
</div>
</div>
<!-- Right panel: idle, shows today quick-start -->
<div class="rp">
<div class="today-card">
<div class="tc-label">Heute Abend</div>
<div class="tc-name">Pasta Bolognese</div>
<div class="tc-meta">Dienstag · 45 Min · mittel</div>
<button class="rp-btn rp-pri" style="margin-top:8px;padding:6px;">Koch-Modus starten</button>
</div>
<div class="hr"></div>
<div class="rp-idle" style="flex:1;">
<div class="rp-idle-t">Tag auswählen</div>
<div class="rp-idle-s">Klicke eine Kachel um Details zu sehen oder ein Gericht zu wählen</div>
</div>
</div>
</div>
</div>
<div class="note">
<strong>Inhalt ohne Klick:</strong> Agenda aller 7 Tage (geplante + leere), darunter Vorschläge für die beiden
ungeplanten Tage — anstelle von Score-Delta zeigen die Karten kurze Begründungs-Tags
(Neues Protein / Keine Überschneidung / Aufwand-Hinweis). Das rechte Panel zeigt „Heute Abend" als
direkte Koch-Modus-Abkürzung. Kein leerer Raum, kein Klick nötig.
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════ -->
<!-- ZUSTAND 2: TAG MIT REZEPT AUSGEWÄHLT (Mi) -->
<!-- ══════════════════════════════════════════════════════════════ -->
<div class="state-block">
<div class="state-label">
<span class="state-num">Zustand 2</span>
<span class="state-name">Tag mit Rezept angeklickt</span>
<span class="state-when">Klick auf Mi, 9. Apr → Gemüse-Stir-fry</span>
</div>
<div class="frame" style="height:680px;">
<div class="tb">
<span class="tb-h1">Wochenplaner</span>
<span class="tb-range">7.13. Apr</span>
<div class="tb-arr"></div><div class="tb-arr"></div>
<button class="tb-btn">Heute</button>
<button class="tb-btn tb-ml tb-pri">+ Gericht hinzufügen</button>
</div>
<div class="body">
<!-- Sidebar (same) -->
<div class="sb">
<div class="score-box">
<div class="sb-lbl">Abwechslungs-Score</div>
<div style="display:flex;align-items:baseline;gap:4px;"><span class="sc-big">7.8</span><span class="sc-den">/10</span></div>
<div class="pbar"><div class="pb-fill" style="width:78%;"></div></div>
<div class="sr"><span class="sr-l">Protein</span><div class="sr-b"><div class="sr-f" style="width:80%;background:var(--g);"></div></div><span class="sr-v">8.0</span></div>
<div class="sr"><span class="sr-l">Zutaten</span><div class="sr-b"><div class="sr-f" style="width:72%;background:var(--y);"></div></div><span class="sr-v">7.2</span></div>
<div class="sr"><span class="sr-l">Aufwand</span><div class="sr-b"><div class="sr-f" style="width:82%;background:var(--g);"></div></div><span class="sr-v">8.2</span></div>
<a style="display:block;margin-top:8px;font-family:var(--fs);font-size:10px;font-weight:500;color:var(--yx);">Variety-Analyse →</a>
</div>
<div>
<div class="sb-lbl">Überschneidungen</div>
<div class="w-item">⚠ Hähnchen an Mo + Do</div>
<div class="w-item">⚠ Tomaten an Di + Do</div>
</div>
<div>
<div class="sb-lbl">Geplant</div>
<div style="display:flex;align-items:baseline;gap:3px;"><span style="font-family:var(--fd);font-size:20px;font-weight:300;">5</span><span style="font-family:var(--fs);font-size:10px;color:var(--muted);">/ 7 Tage</span></div>
<div class="dp" style="margin-top:5px;">
<div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--border);"></div><div class="dp-s" style="background:var(--border);"></div>
</div>
</div>
</div>
<!-- Main area -->
<div class="main">
<!-- Calendar grid: Mi selected -->
<div class="grid7">
<div><div class="d-abbr">Mo</div><div class="d-badge">7</div><div class="tile" style="height:86px;"><p class="tr">Hähnchen-Curry</p><p class="tm">35 Min</p><span class="tbdg b-m">mittel</span></div></div>
<div><div class="d-abbr">Di</div><div class="d-badge db-t">8</div><div class="tile tile-t" style="height:86px;"><p class="tr">Pasta Bolognese</p><p class="tm">45 Min</p><span class="tbdg b-m">mittel</span></div></div>
<!-- Mi SELECTED -->
<div style="position:relative;">
<div class="d-abbr" style="color:var(--gd);">Mi</div>
<div class="d-badge db-s">9</div>
<div class="tile tile-s" style="height:86px;position:relative;">
<p class="tr">Gemüse-Stir-fry</p>
<p class="tm">20 Min</p>
<span class="tbdg b-e">einfach</span>
<div style="position:absolute;bottom:5px;left:50%;transform:translateX(-50%);font-size:8px;color:var(--gd);"></div>
</div>
</div>
<div><div class="d-abbr">Do</div><div class="d-badge">10</div><div class="tile" style="height:86px;opacity:.55;"><p class="tr">Lachs mit Kartoffeln</p><p class="tm">30 Min</p></div></div>
<div><div class="d-abbr">Fr</div><div class="d-badge">11</div><div class="tile" style="height:86px;opacity:.55;"><p class="tr">Pizza Margherita</p><p class="tm">50 Min</p></div></div>
<div><div class="d-abbr">Sa</div><div class="d-badge">12</div><div class="tile tile-e" style="height:86px;opacity:.55;"><span style="font-size:16px;">+</span></div></div>
<div><div class="d-abbr">So</div><div class="d-badge">13</div><div class="tile tile-e" style="height:86px;opacity:.55;"><span style="font-size:16px;">+</span></div></div>
</div>
<!-- ▼ EXPANSION: full-width, below grid, arrow to Mi (3rd column) ▼ -->
<div style="position:relative;margin-top:2px;">
<!-- Arrow pointing up to Mi tile (column 3 of 7) -->
<div style="display:grid;grid-template-columns:repeat(7,1fr);gap:6px;position:absolute;top:-8px;left:0;right:0;pointer-events:none;">
<div></div><div></div>
<div class="exp-arrow"><div class="exp-arr-shape"></div></div>
<div></div><div></div><div></div><div></div>
</div>
<div class="expand">
<div class="exp-left">
<div class="exp-context">Mittwoch, 9. Apr · Abendessen</div>
<div class="exp-name">Gemüse-Stir-fry</div>
<div class="exp-meta">20 Min · einfach · 4 Portionen</div>
<div class="ing-wrap">
<span class="ing">Tofu</span>
<span class="ing">Paprika</span>
<span class="ing">Brokkoli</span>
<span class="ing">Karotten</span>
<span class="ing">Ingwer</span>
<span class="ing">Zucchini</span>
<span class="ing-s">Sesamöl</span>
<span class="ing-s">Sojasauce</span>
<span class="ing-s">Knoblauch</span>
</div>
<div class="exp-badges">
<span class="tbdg b-e" style="font-size:10px;padding:3px 7px;">einfach</span>
<span style="font-family:var(--fs);font-size:10px;font-weight:500;padding:3px 7px;border-radius:2px;background:var(--pt);color:var(--p);">Protein: Tofu</span>
<span style="font-family:var(--fs);font-size:10px;font-weight:500;padding:3px 7px;border-radius:2px;background:var(--gt);color:var(--gd);">Score ▲ +0.4</span>
</div>
</div>
<div class="exp-right">
<button class="exp-btn exp-pri">Koch-Modus</button>
<button class="exp-btn">Rezept ansehen</button>
<button class="exp-btn">Gericht tauschen</button>
<button class="exp-btn exp-err">Entfernen</button>
</div>
</div>
</div>
<!-- ▼ REMAINING WEEK below expansion ▼ -->
<div class="remaining">
<div class="rem-hd">Restliche Woche</div>
<div class="agenda">
<div class="ag-item">
<div class="ag-day">Do 10.4</div>
<div class="ag-name">Lachs mit Kartoffeln</div>
<div class="ag-meta">30 Min · einfach</div>
</div>
<div class="ag-item">
<div class="ag-day">Fr 11.4</div>
<div class="ag-name">Pizza Margherita</div>
<div class="ag-meta">50 Min · aufwändig</div>
</div>
<div class="ag-item ag-t">
<div class="ag-day">Sa 12.4</div>
<div class="ag-name" style="font-family:var(--fs);font-size:12px;color:var(--muted);">Noch kein Gericht</div>
<div class="ag-action">+ Hinzufügen</div>
</div>
<div class="ag-item ag-t">
<div class="ag-day">So 13.4</div>
<div class="ag-name" style="font-family:var(--fs);font-size:12px;color:var(--muted);">Noch kein Gericht</div>
<div class="ag-action">+ Hinzufügen</div>
</div>
</div>
</div>
</div>
<!-- Right panel: score context for selected day -->
<div class="rp">
<div class="rp-lbl">Mittwoch, 9. Apr</div>
<div style="font-family:var(--fs);font-size:11px;color:var(--muted);margin-bottom:10px;">Wie wirkt dieses Gericht?</div>
<div style="display:flex;align-items:baseline;gap:4px;margin-bottom:4px;">
<span style="font-family:var(--fd);font-size:22px;font-weight:300;">7.8</span>
<span style="font-family:var(--fs);font-size:11px;color:var(--muted);">/10</span>
<span style="font-family:var(--fs);font-size:11px;color:var(--gd);font-weight:500;margin-left:6px;">▲ +0.4</span>
</div>
<div class="pbar pbt" style="margin-bottom:12px;"><div class="pb-fill pbg" style="width:78%;"></div></div>
<div class="hr"></div>
<div style="font-family:var(--fs);font-size:10px;font-weight:500;letter-spacing:.07em;text-transform:uppercase;color:var(--muted);margin-bottom:8px;">Dieses Gericht</div>
<div style="display:flex;flex-direction:column;gap:5px;">
<div style="display:flex;align-items:center;gap:6px;font-family:var(--fs);font-size:11px;color:var(--gd);"><span></span><span>Kein Protein-Overlap</span></div>
<div style="display:flex;align-items:center;gap:6px;font-family:var(--fs);font-size:11px;color:var(--gd);"><span></span><span>Neue Zutaten (Tofu, Paprika)</span></div>
<div style="display:flex;align-items:center;gap:6px;font-family:var(--fs);font-size:11px;color:var(--yx);"><span>~</span><span>Tofu 2× diese Woche</span></div>
</div>
</div>
</div>
</div>
<div class="note">
<strong>Nach Klick auf Mittwoch:</strong> Expansion öffnet sich direkt unter dem Grid mit Pfeil-Indikator.
Enthält Rezeptname groß, Zutaten-Tags (normale vs. Grundzutaten <span style="opacity:.6;">gedimmt</span>),
Score-Impact-Badge und alle Aktionen. Unselektierte Kacheln werden leicht ausgeblendet (opacity 55%).
Darunter: kompakte Liste der restlichen Woche — geplante Tage + leere Tage mit „+ Hinzufügen".
Das rechte Panel wechselt auf einen Variety-Kontext: zeigt was dieses Gericht zur Woche beiträgt (positiv/neutral/negativ).
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════ -->
<!-- ZUSTAND 3: LEERER TAG AUSGEWÄHLT (Sa) -->
<!-- ══════════════════════════════════════════════════════════════ -->
<div class="state-block">
<div class="state-label">
<span class="state-num">Zustand 3</span>
<span class="state-name">Leerer Tag angeklickt</span>
<span class="state-when">Klick auf Sa, 12. Apr → kein Gericht</span>
</div>
<div class="frame" style="height:680px;">
<div class="tb">
<span class="tb-h1">Wochenplaner</span>
<span class="tb-range">7.13. Apr</span>
<div class="tb-arr"></div><div class="tb-arr"></div>
<button class="tb-btn">Heute</button>
<button class="tb-btn tb-ml tb-pri">+ Gericht hinzufügen</button>
</div>
<div class="body">
<!-- Sidebar -->
<div class="sb">
<div class="score-box">
<div class="sb-lbl">Abwechslungs-Score</div>
<div style="display:flex;align-items:baseline;gap:4px;"><span class="sc-big">7.8</span><span class="sc-den">/10</span></div>
<div class="pbar"><div class="pb-fill" style="width:78%;"></div></div>
<div class="sr"><span class="sr-l">Protein</span><div class="sr-b"><div class="sr-f" style="width:80%;background:var(--g);"></div></div><span class="sr-v">8.0</span></div>
<div class="sr"><span class="sr-l">Zutaten</span><div class="sr-b"><div class="sr-f" style="width:72%;background:var(--y);"></div></div><span class="sr-v">7.2</span></div>
<div class="sr"><span class="sr-l">Aufwand</span><div class="sr-b"><div class="sr-f" style="width:82%;background:var(--g);"></div></div><span class="sr-v">8.2</span></div>
<a style="display:block;margin-top:8px;font-family:var(--fs);font-size:10px;font-weight:500;color:var(--yx);">Variety-Analyse →</a>
</div>
<div>
<div class="sb-lbl">Überschneidungen</div>
<div class="w-item">⚠ Hähnchen an Mo + Do</div>
<div class="w-item">⚠ Tomaten an Di + Do</div>
</div>
<div>
<div class="sb-lbl">Geplant</div>
<div style="display:flex;align-items:baseline;gap:3px;"><span style="font-family:var(--fd);font-size:20px;font-weight:300;">5</span><span style="font-family:var(--fs);font-size:10px;color:var(--muted);">/ 7 Tage</span></div>
<div class="dp" style="margin-top:5px;">
<div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--border);"></div><div class="dp-s" style="background:var(--border);"></div>
</div>
</div>
</div>
<!-- Main area -->
<div class="main">
<!-- Calendar grid: Sa selected (empty) -->
<div class="grid7">
<div><div class="d-abbr">Mo</div><div class="d-badge">7</div><div class="tile" style="height:86px;opacity:.55;"><p class="tr">Hähnchen-Curry</p><p class="tm">35 Min</p></div></div>
<div><div class="d-abbr">Di</div><div class="d-badge db-t">8</div><div class="tile tile-t" style="height:86px;opacity:.55;"><p class="tr">Pasta Bolognese</p><p class="tm">45 Min</p></div></div>
<div><div class="d-abbr">Mi</div><div class="d-badge">9</div><div class="tile" style="height:86px;opacity:.55;"><p class="tr">Gemüse-Stir-fry</p><p class="tm">20 Min</p></div></div>
<div><div class="d-abbr">Do</div><div class="d-badge">10</div><div class="tile" style="height:86px;opacity:.55;"><p class="tr">Lachs mit Kartoffeln</p><p class="tm">30 Min</p></div></div>
<div><div class="d-abbr">Fr</div><div class="d-badge">11</div><div class="tile" style="height:86px;opacity:.55;"><p class="tr">Pizza Margherita</p><p class="tm">50 Min</p></div></div>
<!-- Sa: SELECTED EMPTY -->
<div style="position:relative;">
<div class="d-abbr" style="color:var(--gd);">Sa</div>
<div class="d-badge db-s">12</div>
<div class="tile tile-e tile-e-s" style="height:86px;">
<span style="font-size:20px;color:var(--gd);">+</span>
<span style="font-family:var(--fs);font-size:9px;color:var(--gd);">wählen</span>
<div style="position:absolute;bottom:5px;left:50%;transform:translateX(-50%);font-size:8px;color:var(--gd);"></div>
</div>
</div>
<div><div class="d-abbr">So</div><div class="d-badge">13</div><div class="tile tile-e" style="height:86px;opacity:.55;"><span style="font-size:16px;">+</span></div></div>
</div>
<!-- ▼ EXPANSION: suggestion cards for Sa ▼ -->
<div style="position:relative;margin-top:2px;">
<!-- Arrow to Sa (column 6) -->
<div style="display:grid;grid-template-columns:repeat(7,1fr);gap:6px;position:absolute;top:-8px;left:0;right:0;pointer-events:none;">
<div></div><div></div><div></div><div></div><div></div>
<div class="exp-arrow"><div class="exp-arr-shape exp-arr-shape-e"></div></div>
<div></div>
</div>
<div class="expand-empty">
<div class="exp-sug-title">Vorschläge für Samstag, 12. Apr</div>
<div class="exp-sug-cards">
<div class="exp-sc">
<div class="exp-sc-name">Ramen mit Ei</div>
<div class="exp-sc-meta">40 Min · mittel</div>
<span class="exp-sc-tag">Neues Protein</span>
</div>
<div class="exp-sc">
<div class="exp-sc-name">Shakshuka</div>
<div class="exp-sc-meta">25 Min · einfach</div>
<span class="exp-sc-tag">Keine Überschneidung</span>
</div>
<div class="exp-sc">
<div class="exp-sc-name">Rindfleisch-Tacos</div>
<div class="exp-sc-meta">30 Min · einfach</div>
<span class="exp-sc-tag">Keine Überschneidung</span>
</div>
<div class="exp-sc">
<div class="exp-sc-name">Kürbissuppe</div>
<div class="exp-sc-meta">35 Min · einfach</div>
<span class="exp-sc-tag" style="background:var(--yt);color:var(--yx);">Aufwand: einfach</span>
</div>
<div class="exp-sc">
<div class="exp-sc-name">Tofu-Teriyaki</div>
<div class="exp-sc-meta">30 Min · einfach</div>
<span class="exp-sc-tag" style="background:var(--yt);color:var(--yx);">Gleiche Zutaten</span>
</div>
<!-- Alle Rezepte card -->
<div class="sc-add" style="min-height:auto;">Alle Rezepte →</div>
</div>
</div>
</div>
<!-- ▼ REMAINING WEEK below ▼ -->
<div class="remaining">
<div class="rem-hd">Noch diese Woche</div>
<div class="agenda">
<div class="ag-item">
<div class="ag-day">Mo 7.4</div>
<div class="ag-name">Hähnchen-Curry</div>
<div class="ag-meta">35 Min · mittel</div>
</div>
<div class="ag-item ag-item-today">
<div class="ag-today-dot"></div>
<div class="ag-day" style="color:var(--yx);">Di 8.4</div>
<div class="ag-name">Pasta Bolognese</div>
<div class="ag-meta">45 Min</div>
</div>
<div class="ag-item ag-t">
<div class="ag-day">So 13.4</div>
<div class="ag-name" style="font-family:var(--fs);font-size:12px;color:var(--muted);">Noch kein Gericht</div>
<div class="ag-action">+ Hinzufügen</div>
</div>
</div>
</div>
</div>
<!-- Right panel: full recipe picker (search + list) -->
<div class="rp">
<div class="rp-lbl">Samstag, 12. Apr</div>
<div class="picker-search">
<span class="ps-icon"></span>
<span class="ps-text">Rezept suchen…</span>
</div>
<div style="overflow-y:auto;flex:1;">
<div class="pick-item">
<div style="flex:1;"><div class="pick-name">Ramen mit Ei</div><div class="pick-meta">40 Min · mittel</div></div>
<span style="font-family:var(--fm);font-size:9px;background:var(--gt);color:var(--gd);padding:2px 5px;border-radius:2px;">Top</span>
</div>
<div class="pick-item">
<div style="flex:1;"><div class="pick-name">Shakshuka</div><div class="pick-meta">25 Min · einfach</div></div>
<span style="font-family:var(--fm);font-size:9px;background:var(--gt);color:var(--gd);padding:2px 5px;border-radius:2px;">Top</span>
</div>
<div class="pick-item">
<div style="flex:1;"><div class="pick-name">Kürbissuppe</div><div class="pick-meta">35 Min · einfach</div></div>
</div>
<div class="pick-item">
<div style="flex:1;"><div class="pick-name">Tofu-Teriyaki</div><div class="pick-meta">30 Min · einfach</div></div>
</div>
<div class="pick-item">
<div style="flex:1;"><div class="pick-name">Gemüse-Curry</div><div class="pick-meta">40 Min · mittel</div></div>
</div>
<div class="pick-item">
<div style="flex:1;"><div class="pick-name">Linseneintopf</div><div class="pick-meta">50 Min · einfach</div></div>
</div>
<div class="pick-item">
<div style="flex:1;"><div class="pick-name">Ofen-Lachs</div><div class="pick-meta">35 Min · einfach</div></div>
</div>
</div>
</div>
</div>
</div>
<div class="note">
<strong>Nach Klick auf leeren Samstag:</strong> Expansion zeigt 5 Vorschläge (3×3 Grid + „Alle Rezepte" als letztes Feld)
mit Begründungs-Tags statt Score-Delta. Die Farbkodierung der Tags macht die Qualität der Empfehlung lesbar ohne Zahlenwert:
Grün = klar besser, Gelb = neutral/tradeoff. Das rechte Panel öffnet gleichzeitig den vollständigen Rezept-Picker mit Suche —
für Nutzer die keinen der Vorschläge wollen. Klick auf eine Karte (main) oder Picker-Item (rechts) führt dasselbe aus: Rezept eintragen.
<br><br>
<strong>Tofu-Teriyaki</strong> erscheint mit „Gleiche Zutaten" (gelb) — das ist die sinnvolle Alternative zu einem Score-Delta von 0.2:
nicht versteckt, aber klar als Abwägung markiert.
</div>
</div>
</body>
</html>