Files
mealprep/specs/planner-tall-tiles.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

848 lines
46 KiB
HTML
Raw Permalink 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 — Tall Tiles</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,.10),0 2px 4px rgba(28,28,24,.06);
--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;}
.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:44px;}
.block{margin-bottom:60px;}
.block-label{display:flex;align-items:baseline;gap:10px;margin-bottom:12px;}
.bl-num{font-family:var(--fm);font-size:11px;background:var(--subtle);color:var(--muted);padding:3px 8px;border-radius:var(--r-sm);}
.bl-name{font-family:var(--fd);font-size:22px;font-weight:300;}
.bl-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;}
/* 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);}
.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;}
.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;}
.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);}
.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);}
.sb-link{font-family:var(--fs);font-size:10px;font-weight:500;color:var(--yx);display:block;margin-top:8px;}
/* 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;}
.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;}
.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);}
.pick-top{font-family:var(--fm);font-size:9px;background:var(--gt);color:var(--gd);padding:2px 5px;border-radius:2px;}
/* Main */
.main{flex:1;overflow-y:auto;padding:13px;}
/* ── TALL TILE SYSTEM ────────────────────────── */
.grid7{display:grid;grid-template-columns:repeat(7,1fr);gap:7px;}
/* Filled tile */
.tile{
border-radius:var(--r-lg);
border:1px solid var(--border);
background:var(--surface);
cursor:pointer;
overflow:hidden;
box-shadow:var(--sh-card);
display:flex;
flex-direction:column;
transition:box-shadow .12s, border-color .12s;
}
.tile:hover{box-shadow:var(--sh-raised);}
.tile-today{border:2px solid var(--y);}
.tile-sel{border:2px solid var(--g);}
.tile-faded{opacity:.45;}
/* Image area (top of tile) */
.tile-img{
width:100%;
flex-shrink:0;
border-radius:0;
position:relative;
overflow:hidden;
}
/* Overlay gradient so text on image is readable if needed */
.tile-img::after{
content:'';
position:absolute;
inset:0;
background:linear-gradient(to bottom, transparent 40%, rgba(28,28,24,.18) 100%);
}
/* Day header (inside tile, above image or overlaid) */
.tile-head{
display:flex;
align-items:center;
justify-content:space-between;
padding:7px 8px 0;
flex-shrink:0;
}
.tile-day-abbr{font-family:var(--fs);font-size:9px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);}
.tile-day-num{
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;
color:var(--text);
}
.dn-today{background:var(--y);color:#fff;}
.dn-sel{background:var(--gd);color:#fff;}
/* Tile body text */
.tile-body{padding:7px 8px 8px;display:flex;flex-direction:column;flex:1;}
.tile-name{font-family:var(--fd);font-size:13px;font-weight:300;line-height:1.35;color:var(--text);}
.tile-meta{font-family:var(--fs);font-size:10px;color:var(--muted);margin-top:3px;}
.tile-tags{display:flex;gap:3px;flex-wrap:wrap;margin-top:6px;}
.tag{font-family:var(--fs);font-size:8px;font-weight:500;padding:2px 5px;border-radius:2px;}
.tag-e{background:var(--gt);color:var(--gd);}
.tag-m{background:var(--yt);color:var(--yx);}
.tag-h{background:var(--ot);color:var(--od);}
.tag-p{background:var(--pt);color:var(--p);}
.tile-serves{font-family:var(--fs);font-size:9px;color:var(--muted);margin-top:auto;padding-top:5px;}
/* Empty tile */
.tile-empty{
border-radius:var(--r-lg);
border:1px dashed var(--border);
background:transparent;
cursor:pointer;
display:flex;
flex-direction:column;
overflow:hidden;
}
.tile-empty-sel{border:2px dashed var(--g);background:rgba(232,245,234,.35);}
.tile-empty-head{
display:flex;align-items:center;justify-content:space-between;
padding:7px 8px 0;flex-shrink:0;
}
.tile-empty-body{
display:flex;flex-direction:column;
align-items:center;justify-content:center;
padding:8px 6px 4px;
gap:3px;
flex-shrink:0;
border-bottom:1px solid var(--border);
margin-bottom:0;
}
.tile-empty-plus{font-size:20px;color:var(--border);}
.tile-empty-label{font-family:var(--fs);font-size:9px;color:var(--muted);}
/* Inline suggestions inside empty tile */
.tile-sug-list{
display:flex;flex-direction:column;
padding:6px 7px;
gap:0;
flex:1;
overflow:hidden;
}
.tile-sug-hd{
font-family:var(--fs);font-size:8px;font-weight:500;
letter-spacing:.07em;text-transform:uppercase;
color:var(--muted);
padding:3px 0 5px;
border-bottom:1px solid var(--subtle);
margin-bottom:3px;
}
.tile-sug-item{
display:flex;align-items:center;gap:5px;
padding:5px 0;
border-bottom:1px solid var(--subtle);
cursor:pointer;
}
.tile-sug-item:last-child{border-bottom:none;}
.tile-sug-item:hover .tile-sug-name{color:var(--gd);}
.tile-sug-name{font-family:var(--fd);font-size:11px;font-weight:300;color:var(--text);flex:1;line-height:1.2;}
.tile-sug-tag{font-family:var(--fs);font-size:8px;font-weight:500;padding:1px 4px;border-radius:2px;white-space:nowrap;flex-shrink:0;}
.ts-green{background:var(--gt);color:var(--gd);}
.ts-yellow{background:var(--yt);color:var(--yx);}
.tile-sug-more{
font-family:var(--fs);font-size:9px;font-weight:500;
color:var(--yx);text-align:center;
padding:5px 0 2px;
margin-top:auto;
}
/* Expansion below grid */
.expand-wrap{position:relative;margin-top:3px;}
.exp-arrows{
display:grid;grid-template-columns:repeat(7,1fr);gap:7px;
position:absolute;top:-8px;left:0;right:0;pointer-events:none;
}
.exp-arr{display:flex;justify-content:center;}
.arr-shape{width:12px;height:12px;border-left:2px solid var(--g);border-top:2px solid var(--g);transform:rotate(45deg);}
.arr-bg-filled{background:var(--gt);}
.arr-bg-empty{background:rgba(232,245,234,.35);}
.expand{
border:2px solid var(--g);border-radius:var(--r-lg);
background:var(--gt);padding:14px;
display:flex;gap:14px;
}
.exp-left{flex:1;}
.exp-ctx{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;flex-wrap:wrap;margin-top:8px;}
.exp-right{display:flex;flex-direction:column;gap:5px;width:116px;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;}
/* Right panel idle */
.rp-today{background:var(--yt);border:1px solid var(--yl);border-radius:var(--r-md);padding:10px;margin-bottom:10px;}
.rtc-lbl{font-family:var(--fs);font-size:9px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--yx);margin-bottom:4px;}
.rtc-name{font-family:var(--fd);font-size:14px;font-weight:300;line-height:1.3;}
.rtc-meta{font-family:var(--fs);font-size:10px;color:var(--muted);margin-top:2px;}
</style>
</head>
<body>
<p class="eyebrow">Mealplan · Planer · Tall Tiles</p>
<h1 class="title">Hohe Kacheln — drei Zustände</h1>
<p class="sub">
Kein separater Agenda-Bereich. Die Kacheln selbst sind die Informationsschicht:
Bild-Placeholder oben, Rezeptname, Metadaten, Tags. Leere Kacheln nutzen die Höhe
für Vorschläge direkt inline. Unter dem Grid erscheint nur noch die Expansion beim Klick.
</p>
<!-- ══════════════════════════════════════════════════════════════ -->
<!-- ZUSTAND 1 — KEIN TAG AUSGEWÄHLT -->
<!-- ══════════════════════════════════════════════════════════════ -->
<div class="block">
<div class="block-label">
<span class="bl-num">01</span>
<span class="bl-name">Kein Tag ausgewählt</span>
<span class="bl-when">Standard beim Laden der Seite</span>
</div>
<div class="frame" style="height:580px;">
<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 class="sb-link">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 -->
<div class="main" style="padding:13px;">
<div class="grid7" style="height:calc(100% - 0px);">
<!-- Mo: Hähnchen-Curry — warm amber image -->
<div class="tile" style="height:100%;">
<div class="tile-head">
<span class="tile-day-abbr">Mo</span>
<span class="tile-day-num">7</span>
</div>
<div class="tile-img" style="height:90px;background:linear-gradient(135deg,#e8c88a 0%,#c9a05a 100%);flex-shrink:0;">
<!-- hero image placeholder — warm/spice tones for curry -->
<div style="position:absolute;inset:0;display:flex;align-items:flex-end;padding:5px 7px;">
</div>
</div>
<div class="tile-body">
<div class="tile-name">Hähnchen-Curry</div>
<div class="tile-meta">35 Min</div>
<div class="tile-tags">
<span class="tag tag-m">mittel</span>
<span class="tag tag-p">Hähnchen</span>
</div>
<div class="tile-serves">4 Portionen</div>
</div>
</div>
<!-- Di: Pasta Bolognese — rich red (TODAY) -->
<div class="tile tile-today" style="height:100%;">
<div class="tile-head">
<span class="tile-day-abbr" style="color:var(--yx);">Di</span>
<span class="tile-day-num dn-today">8</span>
</div>
<div class="tile-img" style="height:90px;background:linear-gradient(135deg,#c96060 0%,#8b2828 100%);flex-shrink:0;">
</div>
<div class="tile-body" style="background:var(--yt);">
<div class="tile-name">Pasta Bolognese</div>
<div class="tile-meta">45 Min</div>
<div class="tile-tags">
<span class="tag tag-m">mittel</span>
<span class="tag tag-p">Rind</span>
</div>
<div class="tile-serves">4 Portionen</div>
</div>
</div>
<!-- Mi: Gemüse-Stir-fry — fresh green -->
<div class="tile" style="height:100%;">
<div class="tile-head">
<span class="tile-day-abbr">Mi</span>
<span class="tile-day-num">9</span>
</div>
<div class="tile-img" style="height:90px;background:linear-gradient(135deg,#7bbf7e 0%,#3d7a42 100%);flex-shrink:0;">
</div>
<div class="tile-body">
<div class="tile-name">Gemüse-Stir-fry</div>
<div class="tile-meta">20 Min</div>
<div class="tile-tags">
<span class="tag tag-e">einfach</span>
<span class="tag tag-p">Tofu</span>
</div>
<div class="tile-serves">2 Portionen</div>
</div>
</div>
<!-- Do: Lachs — blue-teal -->
<div class="tile" style="height:100%;">
<div class="tile-head">
<span class="tile-day-abbr">Do</span>
<span class="tile-day-num">10</span>
</div>
<div class="tile-img" style="height:90px;background:linear-gradient(135deg,#6baed6 0%,#2171b5 100%);flex-shrink:0;">
</div>
<div class="tile-body">
<div class="tile-name">Lachs mit Kartoffeln</div>
<div class="tile-meta">30 Min</div>
<div class="tile-tags">
<span class="tag tag-e">einfach</span>
<span class="tag tag-p">Fisch</span>
</div>
<div class="tile-serves">2 Portionen</div>
</div>
</div>
<!-- Fr: Pizza — warm cream/yellow -->
<div class="tile" style="height:100%;">
<div class="tile-head">
<span class="tile-day-abbr">Fr</span>
<span class="tile-day-num">11</span>
</div>
<div class="tile-img" style="height:90px;background:linear-gradient(135deg,#f0d080 0%,#c8960a 100%);flex-shrink:0;">
</div>
<div class="tile-body">
<div class="tile-name">Pizza Margherita</div>
<div class="tile-meta">50 Min</div>
<div class="tile-tags">
<span class="tag tag-h">aufwändig</span>
<span class="tag tag-p">vegetarisch</span>
</div>
<div class="tile-serves">4 Portionen</div>
</div>
</div>
<!-- Sa: EMPTY — inline suggestions -->
<div class="tile-empty" style="height:100%;">
<div class="tile-empty-head">
<span class="tile-day-abbr">Sa</span>
<span class="tile-day-num" style="color:var(--muted);">12</span>
</div>
<div class="tile-empty-body">
<div class="tile-empty-plus">+</div>
<div class="tile-empty-label">Gericht wählen</div>
</div>
<div class="tile-sug-list">
<div class="tile-sug-hd">Vorschläge</div>
<div class="tile-sug-item">
<span class="tile-sug-name">Ramen mit Ei</span>
<span class="tile-sug-tag ts-green">Neues Protein</span>
</div>
<div class="tile-sug-item">
<span class="tile-sug-name">Shakshuka</span>
<span class="tile-sug-tag ts-green">Kein Overlap</span>
</div>
<div class="tile-sug-item">
<span class="tile-sug-name">Tacos</span>
<span class="tile-sug-tag ts-yellow">Aufwand: leicht</span>
</div>
<div class="tile-sug-more">Alle Rezepte →</div>
</div>
</div>
<!-- So: EMPTY — inline suggestions -->
<div class="tile-empty" style="height:100%;">
<div class="tile-empty-head">
<span class="tile-day-abbr">So</span>
<span class="tile-day-num" style="color:var(--muted);">13</span>
</div>
<div class="tile-empty-body">
<div class="tile-empty-plus">+</div>
<div class="tile-empty-label">Gericht wählen</div>
</div>
<div class="tile-sug-list">
<div class="tile-sug-hd">Vorschläge</div>
<div class="tile-sug-item">
<span class="tile-sug-name">Pho Bo</span>
<span class="tile-sug-tag ts-green">Neues Protein</span>
</div>
<div class="tile-sug-item">
<span class="tile-sug-name">Avocado-Bowl</span>
<span class="tile-sug-tag ts-green">Kein Overlap</span>
</div>
<div class="tile-sug-item">
<span class="tile-sug-name">Kürbissuppe</span>
<span class="tile-sug-tag ts-green">Kein Overlap</span>
</div>
<div class="tile-sug-more">Alle Rezepte →</div>
</div>
</div>
</div><!-- /grid7 -->
</div><!-- /main -->
<!-- Right panel: idle + heute -->
<div class="rp">
<div class="rp-today">
<div class="rtc-lbl">Heute Abend</div>
<div class="rtc-name">Pasta Bolognese</div>
<div class="rtc-meta">Dienstag · 45 Min · mittel</div>
<button class="rp-btn rp-pri" style="margin-top:8px;padding:6px;font-size:11px;">Koch-Modus starten</button>
</div>
<div class="hr"></div>
<div style="flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:6px;padding:16px;">
<div style="font-family:var(--fs);font-size:12px;color:var(--text);">Tag auswählen</div>
<div style="font-family:var(--fs);font-size:11px;color:var(--muted);max-width:152px;line-height:1.5;">Klicke eine Kachel um Details zu sehen oder ein Gericht zu planen</div>
</div>
</div>
</div>
</div>
<div class="note">
<strong>Kein Agenda-Bereich.</strong> Die Kacheln füllen die volle Höhe des Hauptbereichs.
Geplante Tage zeigen: farbiges Bild-Placeholder (wird durch <code>heroImageUrl</code> ersetzt),
Rezeptname, Kochzeit, Effort-Badge, Protein-Tag, Portionenanzahl.
Leere Kacheln (Sa, So) zeigen direkt 3 Vorschläge mit Begründungs-Tags — kein Scrollen nötig.
Klick auf einen Vorschlag-Eintrag → Rezept wird direkt eingetragen.
Klick auf die Kachel selbst → öffnet Expansion unten (Zustand 3).
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════ -->
<!-- ZUSTAND 2 — TAG MIT REZEPT ANGEKLICKT (Mi) -->
<!-- ══════════════════════════════════════════════════════════════ -->
<div class="block">
<div class="block-label">
<span class="bl-num">02</span>
<span class="bl-name">Tag mit Rezept angeklickt</span>
<span class="bl-when">Klick auf Mi — Gemüse-Stir-fry</span>
</div>
<div class="frame" style="height:700px;">
<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">
<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 class="sb-link">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>
<div class="main">
<!-- Tiles: Mi selected, others faded -->
<div class="grid7" style="height:320px;">
<div class="tile tile-faded" style="height:100%;">
<div class="tile-head"><span class="tile-day-abbr">Mo</span><span class="tile-day-num">7</span></div>
<div class="tile-img" style="height:80px;background:linear-gradient(135deg,#e8c88a,#c9a05a);flex-shrink:0;"></div>
<div class="tile-body"><div class="tile-name">Hähnchen-Curry</div><div class="tile-meta">35 Min</div></div>
</div>
<div class="tile tile-today tile-faded" style="height:100%;">
<div class="tile-head"><span class="tile-day-abbr" style="color:var(--yx);">Di</span><span class="tile-day-num dn-today">8</span></div>
<div class="tile-img" style="height:80px;background:linear-gradient(135deg,#c96060,#8b2828);flex-shrink:0;"></div>
<div class="tile-body" style="background:var(--yt);"><div class="tile-name">Pasta Bolognese</div><div class="tile-meta">45 Min</div></div>
</div>
<!-- Mi: SELECTED — full opacity, green border -->
<div class="tile tile-sel" style="height:100%;">
<div class="tile-head"><span class="tile-day-abbr" style="color:var(--gd);">Mi</span><span class="tile-day-num dn-sel">9</span></div>
<div class="tile-img" style="height:80px;background:linear-gradient(135deg,#7bbf7e,#3d7a42);flex-shrink:0;"></div>
<div class="tile-body" style="background:var(--gt);">
<div class="tile-name">Gemüse-Stir-fry</div>
<div class="tile-meta">20 Min</div>
<div class="tile-tags"><span class="tag tag-e">einfach</span><span class="tag tag-p">Tofu</span></div>
<div style="text-align:center;font-size:9px;color:var(--gd);margin-top:auto;padding-top:4px;"></div>
</div>
</div>
<div class="tile tile-faded" style="height:100%;">
<div class="tile-head"><span class="tile-day-abbr">Do</span><span class="tile-day-num">10</span></div>
<div class="tile-img" style="height:80px;background:linear-gradient(135deg,#6baed6,#2171b5);flex-shrink:0;"></div>
<div class="tile-body"><div class="tile-name">Lachs mit Kartoffeln</div><div class="tile-meta">30 Min</div></div>
</div>
<div class="tile tile-faded" style="height:100%;">
<div class="tile-head"><span class="tile-day-abbr">Fr</span><span class="tile-day-num">11</span></div>
<div class="tile-img" style="height:80px;background:linear-gradient(135deg,#f0d080,#c8960a);flex-shrink:0;"></div>
<div class="tile-body"><div class="tile-name">Pizza Margherita</div><div class="tile-meta">50 Min</div></div>
</div>
<div class="tile-empty tile-faded" style="height:100%;opacity:.3;">
<div class="tile-empty-head"><span class="tile-day-abbr">Sa</span><span class="tile-day-num">12</span></div>
<div class="tile-empty-body"><div class="tile-empty-plus">+</div></div>
</div>
<div class="tile-empty tile-faded" style="height:100%;opacity:.3;">
<div class="tile-empty-head"><span class="tile-day-abbr">So</span><span class="tile-day-num">13</span></div>
<div class="tile-empty-body"><div class="tile-empty-plus">+</div></div>
</div>
</div>
<!-- EXPANSION below grid -->
<div class="expand-wrap">
<div class="exp-arrows">
<div></div><div></div>
<div class="exp-arr"><div class="arr-shape arr-bg-filled"></div></div>
<div></div><div></div><div></div><div></div>
</div>
<div class="expand">
<div class="exp-left">
<div class="exp-ctx">Mittwoch, 9. Apr · Abendessen</div>
<div class="exp-name">Gemüse-Stir-fry</div>
<div class="exp-meta">20 Min · einfach · 2 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">Zucchini</span>
<span class="ing">Ingwer</span>
<span class="ing-s">Sesamöl</span>
<span class="ing-s">Sojasauce</span>
<span class="ing-s">Knoblauch</span>
<span class="ing-s">Salz, Pfeffer</span>
</div>
<div class="exp-badges">
<span class="tag tag-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>
</div>
<!-- Right: score context -->
<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 auf die Woche?</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" style="background:var(--border);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;">Bewertung</div>
<div style="display:flex;flex-direction:column;gap:6px;">
<div style="display:flex;align-items:center;gap:6px;font-family:var(--fs);font-size:11px;color:var(--gd);">✓ Kein Protein-Overlap</div>
<div style="display:flex;align-items:center;gap:6px;font-family:var(--fs);font-size:11px;color:var(--gd);">✓ Neue Zutaten</div>
<div style="display:flex;align-items:center;gap:6px;font-family:var(--fs);font-size:11px;color:var(--yx);">~ Tofu zum 2. Mal</div>
</div>
</div>
</div>
</div>
<div class="note">
<strong>Nach Klick auf Mittwoch:</strong> Nicht-ausgewählte Kacheln werden auf 45% Deckkraft gedimmt.
Die Expansion erscheint direkt unter dem Grid (Pfeil zeigt zu Mi).
Die Kacheln bleiben auf ihrer Höhe — der Expansion-Bereich wächst <em>zusätzlich</em> darunter.
Zutaten zeigen normale Zutaten als Pills; Grundzutaten (Sesamöl, Sojasauce…) gedimmt.
</div>
</div>
<!-- ══════════════════════════════════════════════════════════════ -->
<!-- ZUSTAND 3 — LEERER TAG ANGEKLICKT (Sa) -->
<!-- ══════════════════════════════════════════════════════════════ -->
<div class="block">
<div class="block-label">
<span class="bl-num">03</span>
<span class="bl-name">Leerer Tag angeklickt</span>
<span class="bl-when">Klick auf Sa — kein Gericht geplant</span>
</div>
<div class="frame" style="height:700px;">
<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">
<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 class="sb-link">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="main">
<div class="grid7" style="height:320px;">
<div class="tile tile-faded" style="height:100%;">
<div class="tile-head"><span class="tile-day-abbr">Mo</span><span class="tile-day-num">7</span></div>
<div class="tile-img" style="height:80px;background:linear-gradient(135deg,#e8c88a,#c9a05a);flex-shrink:0;"></div>
<div class="tile-body"><div class="tile-name">Hähnchen-Curry</div><div class="tile-meta">35 Min</div></div>
</div>
<div class="tile tile-today tile-faded" style="height:100%;">
<div class="tile-head"><span class="tile-day-abbr" style="color:var(--yx);">Di</span><span class="tile-day-num dn-today">8</span></div>
<div class="tile-img" style="height:80px;background:linear-gradient(135deg,#c96060,#8b2828);flex-shrink:0;"></div>
<div class="tile-body" style="background:var(--yt);"><div class="tile-name">Pasta Bolognese</div><div class="tile-meta">45 Min</div></div>
</div>
<div class="tile tile-faded" style="height:100%;">
<div class="tile-head"><span class="tile-day-abbr">Mi</span><span class="tile-day-num">9</span></div>
<div class="tile-img" style="height:80px;background:linear-gradient(135deg,#7bbf7e,#3d7a42);flex-shrink:0;"></div>
<div class="tile-body"><div class="tile-name">Gemüse-Stir-fry</div><div class="tile-meta">20 Min</div></div>
</div>
<div class="tile tile-faded" style="height:100%;">
<div class="tile-head"><span class="tile-day-abbr">Do</span><span class="tile-day-num">10</span></div>
<div class="tile-img" style="height:80px;background:linear-gradient(135deg,#6baed6,#2171b5);flex-shrink:0;"></div>
<div class="tile-body"><div class="tile-name">Lachs mit Kartoffeln</div><div class="tile-meta">30 Min</div></div>
</div>
<div class="tile tile-faded" style="height:100%;">
<div class="tile-head"><span class="tile-day-abbr">Fr</span><span class="tile-day-num">11</span></div>
<div class="tile-img" style="height:80px;background:linear-gradient(135deg,#f0d080,#c8960a);flex-shrink:0;"></div>
<div class="tile-body"><div class="tile-name">Pizza Margherita</div><div class="tile-meta">50 Min</div></div>
</div>
<!-- Sa: SELECTED EMPTY -->
<div class="tile-empty tile-empty-sel" style="height:100%;">
<div class="tile-empty-head">
<span class="tile-day-abbr" style="color:var(--gd);">Sa</span>
<span class="tile-day-num dn-sel">12</span>
</div>
<div class="tile-empty-body" style="border-bottom-color:var(--gl);">
<div class="tile-empty-plus" style="color:var(--gl);">+</div>
<div class="tile-empty-label" style="color:var(--gd);">Gericht wählen</div>
<div style="text-align:center;font-size:9px;color:var(--gd);margin-top:2px;"></div>
</div>
<div class="tile-sug-list">
<div class="tile-sug-hd">Vorschläge</div>
<div class="tile-sug-item">
<span class="tile-sug-name">Ramen mit Ei</span>
<span class="tile-sug-tag ts-green">Neues Protein</span>
</div>
<div class="tile-sug-item">
<span class="tile-sug-name">Shakshuka</span>
<span class="tile-sug-tag ts-green">Kein Overlap</span>
</div>
<div class="tile-sug-item">
<span class="tile-sug-name">Tacos</span>
<span class="tile-sug-tag ts-yellow">Aufwand: leicht</span>
</div>
<div class="tile-sug-more">Alle Rezepte →</div>
</div>
</div>
<div class="tile-empty tile-faded" style="height:100%;opacity:.3;">
<div class="tile-empty-head"><span class="tile-day-abbr">So</span><span class="tile-day-num">13</span></div>
<div class="tile-empty-body"><div class="tile-empty-plus">+</div></div>
</div>
</div>
<!-- EXPANSION: suggestions full width -->
<div class="expand-wrap">
<div class="exp-arrows">
<div></div><div></div><div></div><div></div><div></div>
<div class="exp-arr"><div class="arr-shape arr-bg-empty"></div></div>
<div></div>
</div>
<div class="expand" style="flex-direction:column;gap:10px;">
<div style="font-family:var(--fs);font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--gd);">Samstag, 12. Apr — Alle Vorschläge</div>
<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:7px;">
<div style="border:1px solid var(--gl);border-radius:var(--r-md);background:#fff;padding:10px;cursor:pointer;">
<div style="font-family:var(--fd);font-size:13px;font-weight:300;line-height:1.3;">Ramen mit Ei</div>
<div style="font-family:var(--fs);font-size:10px;color:var(--muted);margin-top:3px;">40 Min · mittel</div>
<span style="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;">Neues Protein</span>
</div>
<div style="border:1px solid var(--gl);border-radius:var(--r-md);background:#fff;padding:10px;cursor:pointer;">
<div style="font-family:var(--fd);font-size:13px;font-weight:300;line-height:1.3;">Shakshuka</div>
<div style="font-family:var(--fs);font-size:10px;color:var(--muted);margin-top:3px;">25 Min · einfach</div>
<span style="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;">Kein Overlap</span>
</div>
<div style="border:1px solid var(--gl);border-radius:var(--r-md);background:#fff;padding:10px;cursor:pointer;">
<div style="font-family:var(--fd);font-size:13px;font-weight:300;line-height:1.3;">Rindfleisch-Tacos</div>
<div style="font-family:var(--fs);font-size:10px;color:var(--muted);margin-top:3px;">30 Min · einfach</div>
<span style="font-family:var(--fs);font-size:9px;font-weight:500;padding:2px 6px;border-radius:2px;background:var(--yt);color:var(--yx);margin-top:6px;display:inline-block;">Gleiche Zutaten</span>
</div>
<div style="border:1px solid var(--gl);border-radius:var(--r-md);background:#fff;padding:10px;cursor:pointer;">
<div style="font-family:var(--fd);font-size:13px;font-weight:300;line-height:1.3;">Kürbissuppe</div>
<div style="font-family:var(--fs);font-size:10px;color:var(--muted);margin-top:3px;">35 Min · einfach</div>
<span style="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;">Kein Overlap</span>
</div>
</div>
</div>
</div>
</div>
<!-- Right: full recipe picker -->
<div class="rp">
<div class="rp-lbl">Samstag, 12. Apr</div>
<div class="picker-search">
<span style="font-size:12px;color:var(--muted);"></span>
<span style="font-family:var(--fs);font-size:11px;color:var(--muted);">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 class="pick-top">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 class="pick-top">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> Die Kachel selbst zeigt schon die 3 Inline-Vorschläge (sichtbar seit Zustand 1).
Der Pfeil-Indikator erscheint, die Expansion zeigt alle 4 Vorschläge nebeneinander als klickbare Karten.
Das rechte Panel öffnet gleichzeitig den vollständigen Rezept-Picker mit Suche — für alle anderen Optionen.
Klick auf eine Karte (main) oder Picker-Eintrag (rechts) trägt das Rezept ein und schließt die Expansion.
</div>
</div>
</body>
</html>