docs(specs): add detailed implementation spec for E4 variety settings (V2 Kontext-Preset)

5 states: S0 E1 hub update, S1 default, S2 preset selection + score simulation,
S3 advanced settings + Individuell chip, S4 reset confirmation dialog.
Includes API contract, preset mappings, weight multipliers, and LLM agent region.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-09 16:13:17 +02:00
parent c297403506
commit bd1604fc1d

View File

@@ -0,0 +1,981 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Recipe App — E4 Vielfalt-Einstellungen · Implementierungsspezifikation</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"/>
<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;--green-deeper:#1E4A26;--yellow-tint:#FDF6D8;--yellow-light:#F9E08A;--yellow:#F2C12E;--yellow-dark:#C49610;--yellow-text:#8A6800;--blue-tint:#E6F1FB;--blue-light:#A4CFF4;--blue:#2D7DD2;--blue-dark:#185FA5;--purple-tint:#EEEDFE;--purple-light:#CECBF6;--purple:#534AB7;--purple-dark:#3C3489;--orange-tint:#FEF0E6;--orange:#E8862A;--orange-dark:#B46820;--red-tint:#FDECEA;--red:#DC4C3E;--red-dark:#B03328;--color-error:#DC4C3E;--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;--shadow-card:0 1px 3px rgba(28,28,24,.06),0 1px 2px rgba(28,28,24,.04);--shadow-raised:0 4px 12px rgba(28,28,24,.08),0 2px 4px rgba(28,28,24,.04);--shadow-overlay:0 8px 32px rgba(28,28,24,.12),0 2px 8px rgba(28,28,24,.06);}
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}
body{font-family:var(--font-sans);background:#E8E7E2;color:var(--color-text);font-size:14px;line-height:1.6;}
.doc{max-width:1200px;margin:0 auto;padding:48px 40px 120px;}
.doc-header{display:flex;justify-content:space-between;align-items:flex-end;padding-bottom:28px;border-bottom:1px solid var(--color-border);margin-bottom:48px;background:var(--color-page);margin:-48px -40px 48px;padding:48px 40px 28px;border-radius:var(--radius-xl) var(--radius-xl) 0 0;}
.doc-header h1{font-family:var(--font-display);font-size:28px;font-weight:500;letter-spacing:-.02em;margin-bottom:4px;}
.doc-header p{font-size:13px;color:var(--color-text-muted);}
.doc-meta{font-family:var(--font-mono);font-size:11px;color:var(--color-text-muted);text-align:right;line-height:1.9;}
.pill{display:inline-block;padding:2px 8px;border-radius:var(--radius-sm);font-size:10px;font-weight:500;letter-spacing:.05em;background:var(--green-tint);color:var(--green-dark);}
.section{margin-bottom:64px;}
.section-title{font-size:10px;font-weight:500;letter-spacing:.12em;text-transform:uppercase;color:var(--color-text-muted);padding-bottom:10px;border-bottom:1px solid var(--color-border);margin-bottom:24px;}
.prose{font-size:13px;color:var(--color-text-muted);line-height:1.65;max-width:720px;margin-bottom:20px;}
/* Journey header */
.jh{padding:20px 24px;border-radius:var(--radius-xl);margin-bottom:40px;display:flex;align-items:center;gap:16px;}
.jh .jn{font-family:var(--font-display);font-size:48px;font-weight:300;line-height:1;opacity:.5;}
.jh h2{font-family:var(--font-display);font-size:22px;font-weight:500;letter-spacing:-.02em;margin-bottom:4px;}
.jh p{font-size:13px;line-height:1.5;}.jh .fl{font-family:var(--font-mono);font-size:11px;margin-top:6px;opacity:.7;}
.jh-p{background:var(--purple-tint);border:1px solid var(--purple-light);}.jh-p .jn{color:var(--purple);}.jh-p p,.jh-p .fl{color:var(--purple-dark);}
/* Screen block */
.scr{margin-bottom:56px;}
.scr-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;}
.scr-head h3{font-family:var(--font-display);font-size:20px;font-weight:500;letter-spacing:-.02em;}
.scr-id{font-family:var(--font-mono);font-size:11px;color:var(--color-text-muted);padding:2px 8px;border:1px solid var(--color-border);border-radius:var(--radius-sm);background:var(--color-page);}
.scr-desc{font-size:12px;color:var(--color-text-muted);line-height:1.6;max-width:720px;margin-bottom:6px;}
.scr-var{font-size:11px;color:var(--color-text-muted);margin-bottom:20px;}.scr-var strong{color:var(--color-text);}
/* Device frames */
.previews{display:flex;gap:32px;flex-wrap:wrap;justify-content:center;align-items:flex-start;margin-bottom:20px;}
.prev-col{display:flex;flex-direction:column;align-items:center;gap:10px;}
.bp-lbl{font-family:var(--font-mono);font-size:10px;color:var(--color-text-muted);}
.phone{width:320px;flex-shrink:0;background:var(--color-page);border-radius:36px;overflow:hidden;box-shadow:var(--shadow-overlay),0 0 0 1px rgba(0,0,0,.07);display:flex;flex-direction:column;border:6px solid #1C1C18;}
.pst{padding:10px 20px 0;display:flex;justify-content:space-between;align-items:center;font-size:12px;background:var(--color-page);}.pst b{font-weight:600;}.pst span{font-size:10px;}
.pb{flex:1;overflow-y:auto;display:flex;flex-direction:column;}
.desk{width:100%;max-width:1040px;background:var(--color-page);border-radius:var(--radius-xl);overflow:hidden;box-shadow:var(--shadow-overlay),0 0 0 1px rgba(0,0,0,.06);display:flex;min-height:520px;}
/* Agent spec block */
.agent{background:var(--color-text);color:#E8E8E2;padding:24px;border-radius:var(--radius-lg);margin-top:20px;}
.agent h4{font-size:9px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:#5A5A55;margin-bottom:12px;}
.agent pre{font-family:var(--font-mono);font-size:10px;color:#444440;margin-bottom:16px;line-height:1.8;white-space:pre-wrap;}
.at{width:100%;border-collapse:collapse;font-family:var(--font-mono);font-size:10px;}
.at thead tr{border-bottom:1px solid #2A2A26;}.at th{text-align:left;padding:6px 10px;font-size:8px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:#5A5A55;font-family:var(--font-sans);}.at td{padding:5px 10px;border-bottom:1px solid #1E1E1A;vertical-align:top;line-height:1.5;}.at tr:last-child td{border-bottom:none;}.at td:first-child{color:#7A7A72;}.at td:nth-child(2){color:#E8E8E2;font-weight:500;}.at td:nth-child(3){color:#5A5A55;}.at .grp td{padding-top:14px;font-family:var(--font-sans);font-size:8px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:#3A3A36;}
/* LLM section */
.llm{background:var(--color-page);border:2px solid var(--green);border-radius:var(--radius-xl);padding:32px 40px;margin-top:64px;}
.llm h2{font-family:var(--font-display);font-size:22px;font-weight:500;letter-spacing:-.02em;margin-bottom:8px;color:var(--green-dark);}
.llm h3{font-size:14px;font-weight:600;margin:20px 0 8px;color:var(--color-text);}
.llm p,.llm li{font-size:13px;color:var(--color-text-muted);line-height:1.65;}
.llm ul,.llm ol{padding-left:20px;margin-bottom:12px;}
.llm li{margin-bottom:4px;}
.llm code{font-family:var(--font-mono);font-size:11px;background:var(--color-surface);padding:1px 5px;border-radius:3px;}
.llm table{width:100%;border-collapse:collapse;margin:12px 0;font-size:12px;}
.llm th,.llm td{text-align:left;padding:6px 10px;border-bottom:1px solid var(--color-border);}
.llm th{font-weight:500;color:var(--color-text);font-size:11px;text-transform:uppercase;letter-spacing:.05em;}
.llm td{color:var(--color-text-muted);}
/* Shared nav chrome */
.mtb{padding:10px 16px;background:var(--color-page);border-bottom:1px solid var(--color-border);display:flex;align-items:center;gap:10px;}
.mtb-back{font-size:12px;color:var(--color-text-muted);display:flex;align-items:center;gap:4px;flex-shrink:0;}
.mtb-t{font-family:var(--font-display);font-size:18px;font-weight:500;letter-spacing:-.02em;flex:1;}
.mbt{border-top:1px solid var(--color-border);background:var(--color-surface);padding:8px 16px 28px;display:flex;justify-content:space-around;flex-shrink:0;}
.mt-i{display:flex;flex-direction:column;align-items:center;gap:2px;}
.mt-ic{width:20px;height:20px;border-radius:4px;background:var(--color-subtle);display:flex;align-items:center;justify-content:center;font-size:11px;}
.mt-i.a .mt-ic{background:var(--green-tint);}
.mt-l{font-size:9px;font-weight:500;color:var(--color-text-muted);}
.mt-i.a .mt-l{color:var(--green-dark);}
.dsb{width:224px;flex-shrink:0;background:var(--color-surface);border-right:1px solid var(--color-border);display:flex;flex-direction:column;}
.dsb-logo{padding:20px 16px 16px;border-bottom:1px solid var(--color-border);}
.dsb-lm{display:flex;align-items:center;gap:8px;margin-bottom:2px;}
.dsb-ic{width:24px;height:24px;border-radius:5px;background:var(--green);display:flex;align-items:center;justify-content:center;font-size:12px;}
.dsb-nm{font-family:var(--font-display);font-size:16px;font-weight:500;letter-spacing:-.02em;}
.dsb-sub{font-size:10px;color:var(--color-text-muted);padding-left:32px;}
.dsb-nav{padding:12px 10px;flex:1;}
.dsb-nl{font-size:8px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--color-text-muted);padding:0 8px;margin-bottom:4px;}
.dsb-ni{display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:var(--radius-md);font-size:13px;color:var(--color-text-muted);margin-bottom:2px;}
.dsb-ni.a{background:var(--green-tint);color:var(--green-dark);font-weight:500;}
.dsb-nc{font-size:13px;width:18px;text-align:center;}
.dm{flex:1;display:flex;flex-direction:column;min-width:0;}
.dtb{padding:14px 24px;border-bottom:1px solid var(--color-border);display:flex;justify-content:space-between;align-items:center;flex-shrink:0;}
.dtb-t{font-family:var(--font-display);font-size:18px;font-weight:500;letter-spacing:-.02em;}
.dtb-bc{font-size:12px;color:var(--color-text-muted);display:flex;align-items:center;gap:6px;margin-bottom:2px;}
.dtb-bc span{color:var(--color-border);}
.dmc{padding:24px;flex:1;overflow-y:auto;}
/* UI components */
.tog{display:flex;align-items:center;justify-content:space-between;padding:12px 0;border-bottom:1px solid var(--color-subtle);}
.tog:last-child{border-bottom:none;}
.tog-l{display:flex;flex-direction:column;gap:2px;}
.tog-name{font-size:13px;font-weight:500;}
.tog-hint{font-size:11px;color:var(--color-text-muted);}
.tog-sw{width:36px;height:20px;border-radius:10px;background:var(--green);flex-shrink:0;position:relative;}
.tog-sw::after{content:'';position:absolute;width:16px;height:16px;border-radius:50%;background:#fff;top:2px;right:2px;box-shadow:0 1px 3px rgba(0,0,0,.2);}
.tog-sw.off{background:var(--color-border);}
.tog-sw.off::after{right:auto;left:2px;}
.seg{display:flex;border:1px solid var(--color-border);border-radius:var(--radius-md);overflow:hidden;background:var(--color-surface);}
.seg-o{flex:1;text-align:center;font-size:11px;font-weight:500;padding:6px 0;color:var(--color-text-muted);}
.seg-o.a{background:var(--color-page);color:var(--color-text);box-shadow:var(--shadow-card);}
.seg-o.a-r{background:var(--red-tint);color:var(--red-dark);}
.seg-o.a-g{background:var(--green-tint);color:var(--green-dark);}
.grp{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);overflow:hidden;margin-bottom:12px;}
.grp-hd{padding:10px 14px;border-bottom:1px solid var(--color-border);background:var(--color-subtle);}
.grp-hd-t{font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--color-text-muted);}
.grp-b{padding:0 14px;}
.wr{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 0;border-bottom:1px solid var(--color-subtle);}
.wr:last-child{border-bottom:none;}
.wr-l{display:flex;flex-direction:column;gap:1px;min-width:0;}
.wr-name{font-size:12px;font-weight:500;}
.wr-sub{font-size:10px;color:var(--color-text-muted);}
/* Context chips */
.ctx-chips{display:flex;gap:8px;margin-bottom:16px;}
.ctx-chip{flex:1;padding:14px 12px;border-radius:var(--radius-xl);border:1.5px solid var(--color-border);background:var(--color-surface);display:flex;flex-direction:column;gap:3px;cursor:default;}
.ctx-chip.sel{border-color:var(--green-light);background:var(--green-tint);}
.ctx-chip.ind{border-color:var(--purple-light);background:var(--purple-tint);}
.ctx-em{font-size:18px;}
.ctx-name{font-size:12px;font-weight:600;color:var(--color-text);}
.ctx-chip.sel .ctx-name{color:var(--green-dark);}
.ctx-chip.ind .ctx-name{color:var(--purple-dark);}
.ctx-sub{font-size:10px;color:var(--color-text-muted);line-height:1.3;}
.ctx-chip.sel .ctx-sub{color:var(--green-dark);opacity:.7;}
.ctx-chip.ind .ctx-sub{color:var(--purple-dark);opacity:.7;}
/* Summary pills */
.s-pills{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:14px;}
.s-pill{font-size:10px;font-weight:500;padding:3px 8px;border-radius:20px;display:flex;align-items:center;gap:3px;}
.s-pill.on{background:var(--green-tint);color:var(--green-dark);}
.s-pill.off{background:var(--color-subtle);color:var(--color-text-muted);}
.s-pill.warn{background:var(--yellow-tint);color:var(--yellow-text);}
/* Accordion */
.acc{border:1px solid var(--color-border);border-radius:var(--radius-lg);overflow:hidden;margin-bottom:12px;}
.acc-hd{padding:12px 14px;display:flex;justify-content:space-between;align-items:center;background:var(--color-surface);}
.acc-hd-t{font-size:13px;font-weight:500;}
.acc-hd-r{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--color-text-muted);}
.acc-b{padding:14px;border-top:1px solid var(--color-border);background:var(--color-page);}
/* Score preview */
.score-banner{background:var(--color-text);border-radius:var(--radius-lg);padding:14px 16px;margin-bottom:14px;display:flex;align-items:center;justify-content:space-between;gap:12px;}
.score-banner-l{}
.score-banner-label{font-size:10px;color:#6B6A63;margin-bottom:2px;}
.score-banner-val{font-family:var(--font-display);font-size:30px;font-weight:300;letter-spacing:-.02em;color:#E8E8E2;line-height:1;}
.score-banner-sub{font-size:10px;margin-top:3px;}
.score-banner-up{color:#6FCF97;}
.score-banner-neutral{color:#6B6A63;}
.score-banner-r{font-size:28px;opacity:.7;}
/* Summary detail rows (desktop right column) */
.sum-rows{display:flex;flex-direction:column;gap:5px;}
.sum-row{display:flex;justify-content:space-between;align-items:center;padding:7px 10px;border-radius:var(--radius-md);font-size:12px;}
.sum-row.on{background:var(--green-tint);}
.sum-row.off{background:var(--color-subtle);}
.sum-row.warn{background:var(--yellow-tint);}
.sum-row-name{font-weight:500;}
.sum-row.on .sum-row-name{color:var(--green-dark);}
.sum-row.off .sum-row-name{color:var(--color-text-muted);}
.sum-row.warn .sum-row-name{color:var(--yellow-text);}
.sum-row-val{font-size:10px;font-weight:500;}
.sum-row.on .sum-row-val{color:var(--green-dark);}
.sum-row.off .sum-row-val{color:var(--color-text-muted);}
.sum-row.warn .sum-row-val{color:var(--yellow-text);}
/* Reset link */
.reset-link{font-size:12px;color:var(--red-dark);padding:10px 0;display:block;text-align:center;}
/* Divider */
.sec-lbl{font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--color-text-muted);margin-bottom:8px;}
/* Modal overlay */
.overlay{position:relative;border-radius:var(--radius-xl);overflow:hidden;}
.modal-backdrop{position:absolute;inset:0;background:rgba(28,28,24,.4);display:flex;align-items:center;justify-content:center;padding:24px;}
.modal{background:var(--color-page);border-radius:var(--radius-xl);padding:24px;width:100%;max-width:280px;box-shadow:var(--shadow-overlay);}
.modal-title{font-family:var(--font-display);font-size:18px;font-weight:500;letter-spacing:-.02em;margin-bottom:8px;}
.modal-body{font-size:13px;color:var(--color-text-muted);line-height:1.6;margin-bottom:20px;}
.modal-acts{display:flex;flex-direction:column;gap:8px;}
.btn-dest{padding:11px 16px;border-radius:var(--radius-md);background:var(--red);color:#fff;font-weight:500;font-size:13px;text-align:center;}
.btn-ghost{padding:11px 16px;border-radius:var(--radius-md);background:var(--color-surface);border:1px solid var(--color-border);color:var(--color-text-muted);font-weight:500;font-size:13px;text-align:center;}
/* E1 hub card */
.hub-grid{display:grid;grid-template-columns:2fr 1fr;gap:12px;margin-bottom:12px;}
.hub-card{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-xl);padding:16px;}
.hub-card.primary{border-left:3px solid var(--green-dark);}
.hub-card.variety{border-left:3px solid var(--purple);}
.hub-stat{font-family:var(--font-display);font-size:36px;font-weight:300;letter-spacing:-.02em;line-height:1;margin-bottom:4px;}
.hub-stat.green{color:var(--green-dark);}
.hub-stat.purple{color:var(--purple);}
.hub-name{font-size:12px;font-weight:500;margin-bottom:2px;}
.hub-sub{font-size:11px;color:var(--color-text-muted);}
.hub-arr{font-size:12px;color:var(--color-text-muted);margin-top:10px;}
/* Settings hub bottom row */
.hub-row{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
</style>
</head>
<body>
<div class="doc">
<!-- ── Header ── -->
<div class="doc-header">
<div>
<h1>E4 — Vielfalt-Einstellungen</h1>
<p>Implementierungsspezifikation · V2 Kontext-Preset · Journey J9</p>
</div>
<div class="doc-meta">
<span class="pill">v1.0</span><br>
Screens: E1 (Update) + E4<br>
States: 5<br>
Rolle: Planer only
</div>
</div>
<!-- ── Journey context ── -->
<div class="jh jh-p">
<div class="jn">J9</div>
<div>
<h2>Vielfalt-Algorithmus konfigurieren</h2>
<p>Planer passt Bewertungsregeln an den Haushaltskontext an — primär das Deaktivieren der Protein-Prüfung für vegetarische Haushalte.</p>
<div class="fl">E1 → E4 → C3 · Planer only · Auto-Save · Reset benötigt Bestätigung</div>
</div>
</div>
<!-- ════════════════════════════════════════
E1 — SETTINGS HUB UPDATE
═════════════════════════════════════════ -->
<div class="section">
<div class="section-title">E1 — Settings-Hub (Update)</div>
<p class="prose">Der bestehende Settings-Hub (E1) erhält eine dritte Kachel: "Vielfalt-Einstellungen". Die Kachel zeigt den aktuellen Vielfalt-Score als Kennzahl. Das Grid-Layout wird von 2-spaltig zu einem Mix aus Hauptkachel oben und zwei gleichbreiten Kacheln unten angepasst.</p>
<!-- S0: E1 Hub -->
<div class="scr">
<div class="scr-head"><h3>S0 · Settings-Hub mit Vielfalt-Kachel</h3><span class="scr-id">E1</span></div>
<div class="scr-desc">Die neue Vielfalt-Kachel erscheint in der unteren Reihe neben der Haushalt-Kachel. Zeigt den aktuellen Score als lila Kennzahl. Bei Score &lt; 6.0 färbt sich die Kennzahl orange als Aufmerksamkeitshinweis.</div>
<div class="scr-var"><strong>Änderung gegenüber E1 v1:</strong> dritte Kachel + Grid-Anpassung. Vorräte-Kachel bleibt primär (2fr oben).</div>
<div class="previews">
<div class="prev-col">
<div class="bp-lbl">Mobile · 320px</div>
<div class="phone">
<div class="pst"><b>9:41</b><span>●●●</span></div>
<div class="pb">
<div class="mtb"><div class="mtb-t">Einstellungen</div></div>
<div style="padding:16px;flex:1;">
<!-- Vorräte (primary, full width) -->
<div class="hub-card primary" style="margin-bottom:12px;">
<div class="hub-stat green">12</div>
<div class="hub-name">Vorräte</div>
<div class="hub-sub">Zutaten immer vorrätig</div>
<div class="hub-arr">Bearbeiten →</div>
</div>
<!-- Bottom row: 2 cards -->
<div class="hub-row">
<div class="hub-card">
<div class="hub-stat" style="font-size:28px;color:var(--blue-dark);">3</div>
<div class="hub-name">Haushalt</div>
<div class="hub-sub">Mitglieder</div>
<div class="hub-arr">Verwalten →</div>
</div>
<div class="hub-card variety">
<div class="hub-stat purple" style="font-size:28px;">7.4</div>
<div class="hub-name">Vielfalt</div>
<div class="hub-sub">Diese Woche</div>
<div class="hub-arr">Einstellungen →</div>
</div>
</div>
</div>
<div class="mbt">
<div class="mt-i"><div class="mt-ic">📅</div><div class="mt-l">Plan</div></div>
<div class="mt-i"><div class="mt-ic">🛒</div><div class="mt-l">Einkauf</div></div>
<div class="mt-i"><div class="mt-ic">🍳</div><div class="mt-l">Rezepte</div></div>
<div class="mt-i a"><div class="mt-ic">⚙️</div><div class="mt-l">Einstellungen</div></div>
</div>
</div>
</div>
</div>
<div class="prev-col" style="flex:1;min-width:600px;">
<div class="bp-lbl">Desktop · 1040px</div>
<div class="desk">
<div class="dsb">
<div class="dsb-logo"><div class="dsb-lm"><div class="dsb-ic">🥦</div><div class="dsb-nm">Mealprep</div></div><div class="dsb-sub">Familie Raddatz</div></div>
<div class="dsb-nav">
<div class="dsb-nl">Planung</div>
<div class="dsb-ni"><span class="dsb-nc">📅</span> Wochenplan</div>
<div class="dsb-ni"><span class="dsb-nc">🛒</span> Einkaufsliste</div>
<div class="dsb-ni"><span class="dsb-nc">🍳</span> Rezepte</div>
<div class="dsb-nl" style="margin-top:12px;">Haushalt</div>
<div class="dsb-ni a"><span class="dsb-nc">⚙️</span> Einstellungen</div>
</div>
</div>
<div class="dm">
<div class="dtb"><div class="dtb-t">Einstellungen</div></div>
<div class="dmc">
<div style="max-width:640px;">
<!-- Vorräte primary -->
<div class="hub-card primary" style="margin-bottom:16px;display:flex;align-items:center;justify-content:space-between;">
<div>
<div class="hub-stat green">12</div>
<div class="hub-name">Vorräte</div>
<div class="hub-sub">Zutaten, die immer vorrätig sind und nicht auf die Einkaufsliste kommen</div>
</div>
<div style="font-size:13px;font-weight:500;color:var(--green-dark);">Bearbeiten →</div>
</div>
<!-- Bottom row: 2 cards -->
<div class="hub-row">
<div class="hub-card" style="display:flex;align-items:center;justify-content:space-between;">
<div>
<div class="hub-stat" style="font-size:28px;color:var(--blue-dark);">3</div>
<div class="hub-name">Haushalt</div>
<div class="hub-sub">Mitglieder &amp; Rollen</div>
</div>
<div style="font-size:13px;font-weight:500;color:var(--blue-dark);">Verwalten →</div>
</div>
<div class="hub-card variety" style="display:flex;align-items:center;justify-content:space-between;">
<div>
<div class="hub-stat purple" style="font-size:28px;">7.4</div>
<div class="hub-name">Vielfalt-Einstellungen</div>
<div class="hub-sub">Algorithmus anpassen</div>
</div>
<div style="font-size:13px;font-weight:500;color:var(--purple-dark);">Einstellungen →</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="agent">
<h4>E1 Hub Update · S0</h4>
<pre>/* E1 grid: Vorräte (full width, 2fr, border-left: 3px solid --green-dark) on top row.
* Bottom row: 2 equal columns — Haushalt + Vielfalt-Einstellungen.
* Vielfalt card: border-left: 3px solid --purple. Stat color: --purple (7.4).
* If score < 6.0: stat color switches to --orange (Aufmerksamkeit) with no other change.
* Score value: load from GET /v1/week-plans?weekStart=current GET /v1/week-plans/{id}/variety-score.
* If no current plan: show "" as stat value, sub: "Kein Plan".
* Tap/click Vielfalt card navigate to E4. */</pre>
<table class="at"><thead><tr><th>Element</th><th>Wert</th><th>Notizen</th></tr></thead><tbody>
<tr class="grp"><td colspan="3">Vielfalt-Kachel</td></tr>
<tr><td>Kennzahl</td><td>varietyScore.score, 1 Dezimalstelle</td><td>Farbe: --purple normal, --orange wenn &lt; 6.0</td></tr>
<tr><td>Label</td><td>Vielfalt-Einstellungen</td><td>Desktop; Mobile: "Vielfalt"</td></tr>
<tr><td>Sub-Label</td><td>"Diese Woche" / "Kein Plan" / ""</td><td>Kein Plan = kein weekPlan für aktuelle Woche</td></tr>
<tr><td>Rand</td><td>border-left: 3px solid --purple</td><td>Analog zu Vorräte → --green-dark</td></tr>
<tr><td>Aktion</td><td>Tap → navigate /settings/variety</td><td>Route: +page.svelte unter (app)/settings/variety/</td></tr>
<tr class="grp"><td colspan="3">Grid-Layout</td></tr>
<tr><td>Mobile</td><td>Vorräte fullwidth + grid-template-columns: 1fr 1fr unten</td><td>Gap: 12px</td></tr>
<tr><td>Desktop</td><td>Vorräte fullwidth + grid-template-columns: 1fr 1fr unten</td><td>Max-width: 640px, gap: 16px</td></tr>
</tbody></table>
</div>
</div>
</div>
<!-- ════════════════════════════════════════
S1 — DEFAULT (KEIN CUSTOM-CONFIG)
═════════════════════════════════════════ -->
<div class="section">
<div class="section-title">E4 — Vielfalt-Einstellungen · States</div>
<div class="scr">
<div class="scr-head"><h3>S1 · Standard (kein Custom-Config)</h3><span class="scr-id">E4</span></div>
<div class="scr-desc">Erster Aufruf, kein haushaltsindividueller Config-Eintrag. Omnivor-Chip ist ausgewählt (Default-Zustand). Score-Preview zeigt den aktuellen tatsächlichen Score — keine Simulation nötig, da noch nichts geändert wurde. Hinweis-Text erklärt kurz den Zweck der Seite.</div>
<div class="scr-var"><strong>S1</strong> · Omnivor selected · Score-Preview = aktueller Score · Erweiterte Einstellungen eingeklappt</div>
<div class="previews">
<div class="prev-col">
<div class="bp-lbl">Mobile · 320px</div>
<div class="phone">
<div class="pst"><b>9:41</b><span>●●●</span></div>
<div class="pb">
<div class="mtb"><div class="mtb-back">← Einstellungen</div><div class="mtb-t">Vielfalt</div></div>
<div style="padding:16px;flex:1;overflow-y:auto;">
<div style="font-size:12px;color:var(--color-text-muted);line-height:1.6;margin-bottom:14px;">Passe den Algorithmus an deinen Haushalt an. Änderungen werden sofort übernommen.</div>
<div class="sec-lbl">Haushaltskontext</div>
<div class="ctx-chips">
<div class="ctx-chip sel">
<div class="ctx-em">🥩</div>
<div class="ctx-name">Omnivor</div>
<div class="ctx-sub">Alle Regeln aktiv</div>
</div>
<div class="ctx-chip">
<div class="ctx-em">🥦</div>
<div class="ctx-name">Vegetarisch</div>
<div class="ctx-sub">Protein deaktiviert</div>
</div>
<div class="ctx-chip">
<div class="ctx-em">🌱</div>
<div class="ctx-name">Vegan</div>
<div class="ctx-sub">Protein deaktiviert</div>
</div>
</div>
<div class="sec-lbl">Aktive Regeln</div>
<div class="s-pills">
<div class="s-pill on">✓ Protein</div>
<div class="s-pill on">✓ Küche</div>
<div class="s-pill on">✓ Zutaten · Mittel</div>
<div class="s-pill on">✓ Letzte Wochen · Mittel</div>
<div class="s-pill warn">⚠ Duplikate · Hoch</div>
</div>
<div class="acc">
<div class="acc-hd">
<div class="acc-hd-t">Erweiterte Einstellungen</div>
<div class="acc-hd-r"></div>
</div>
</div>
<div class="score-banner">
<div class="score-banner-l">
<div class="score-banner-label">Aktueller Score</div>
<div class="score-banner-val">7.4</div>
<div class="score-banner-sub score-banner-neutral">Keine Änderungen</div>
</div>
<div class="score-banner-r">📊</div>
</div>
<div class="reset-link" style="color:var(--color-text-muted);">Bereits Standard-Einstellungen</div>
</div>
<div class="mbt">
<div class="mt-i"><div class="mt-ic">📅</div><div class="mt-l">Plan</div></div>
<div class="mt-i"><div class="mt-ic">🛒</div><div class="mt-l">Einkauf</div></div>
<div class="mt-i"><div class="mt-ic">🍳</div><div class="mt-l">Rezepte</div></div>
<div class="mt-i a"><div class="mt-ic">⚙️</div><div class="mt-l">Einstellungen</div></div>
</div>
</div>
</div>
</div>
<div class="prev-col" style="flex:1;min-width:600px;">
<div class="bp-lbl">Desktop · 1040px</div>
<div class="desk">
<div class="dsb">
<div class="dsb-logo"><div class="dsb-lm"><div class="dsb-ic">🥦</div><div class="dsb-nm">Mealprep</div></div><div class="dsb-sub">Familie Raddatz</div></div>
<div class="dsb-nav">
<div class="dsb-nl">Planung</div>
<div class="dsb-ni"><span class="dsb-nc">📅</span> Wochenplan</div>
<div class="dsb-ni"><span class="dsb-nc">🛒</span> Einkaufsliste</div>
<div class="dsb-ni"><span class="dsb-nc">🍳</span> Rezepte</div>
<div class="dsb-nl" style="margin-top:12px;">Haushalt</div>
<div class="dsb-ni a"><span class="dsb-nc">⚙️</span> Einstellungen</div>
</div>
</div>
<div class="dm">
<div class="dtb"><div><div class="dtb-bc">Einstellungen <span></span> Vielfalt-Einstellungen</div><div class="dtb-t">Vielfalt-Einstellungen</div></div></div>
<div class="dmc">
<div style="display:grid;grid-template-columns:1fr 280px;gap:24px;max-width:800px;">
<div>
<div style="font-size:12px;color:var(--color-text-muted);line-height:1.6;margin-bottom:16px;">Passe den Algorithmus an deinen Haushaltskontext an. Änderungen werden sofort übernommen und wirken sich auf den nächsten Score-Abruf aus.</div>
<div class="sec-lbl">Haushaltskontext</div>
<div class="ctx-chips" style="margin-bottom:20px;">
<div class="ctx-chip sel"><div class="ctx-em">🥩</div><div class="ctx-name">Omnivor</div><div class="ctx-sub">Alle Regeln aktiv</div></div>
<div class="ctx-chip"><div class="ctx-em">🥦</div><div class="ctx-name">Vegetarisch</div><div class="ctx-sub">Protein deaktiviert</div></div>
<div class="ctx-chip"><div class="ctx-em">🌱</div><div class="ctx-name">Vegan</div><div class="ctx-sub">Protein deaktiviert</div></div>
</div>
<div class="acc">
<div class="acc-hd"><div class="acc-hd-t">Erweiterte Einstellungen</div><div class="acc-hd-r"></div></div>
</div>
<div class="reset-link" style="text-align:left;color:var(--color-text-muted);">Bereits Standard-Einstellungen</div>
</div>
<div>
<div class="score-banner">
<div>
<div class="score-banner-label">Aktueller Score</div>
<div class="score-banner-val">7.4 <span style="font-size:13px;opacity:.5;">/ 10</span></div>
<div class="score-banner-sub score-banner-neutral">Keine Änderungen aktiv</div>
</div>
<div class="score-banner-r">📊</div>
</div>
<div class="sec-lbl">Aktive Regeln</div>
<div class="sum-rows">
<div class="sum-row on"><span class="sum-row-name">Protein</span><span class="sum-row-val">Mittel</span></div>
<div class="sum-row on"><span class="sum-row-name">Küche</span><span class="sum-row-val">Mittel</span></div>
<div class="sum-row on"><span class="sum-row-name">Zutaten</span><span class="sum-row-val">Niedrig</span></div>
<div class="sum-row on"><span class="sum-row-name">Letzte Wochen</span><span class="sum-row-val">Mittel</span></div>
<div class="sum-row warn"><span class="sum-row-name">Duplikate</span><span class="sum-row-val">Hoch</span></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="agent">
<h4>E4 · S1 Default</h4>
<pre>/* Load: GET /v1/households/mine/variety-config → 404 if no custom config.
* On 404: use defaults (Omnivor preset), show Omnivor chip as selected.
* Score banner: show actual GET /v1/week-plans/{id}/variety-score (no simulation).
* "Bereits Standard-Einstellungen" replaces reset link if no custom config exists.
* Accordion: closed. */</pre>
<table class="at"><thead><tr><th>Element</th><th>Wert</th><th>Notizen</th></tr></thead><tbody>
<tr class="grp"><td colspan="3">Laden</td></tr>
<tr><td>Config-Load</td><td>GET /v1/households/mine/variety-config</td><td>404 → Defaults verwenden, Omnivor selected</td></tr>
<tr><td>Score-Load</td><td>GET /v1/week-plans/{id}/variety-score</td><td>Nur wenn weekPlan existiert; sonst Score-Banner ausblenden</td></tr>
<tr class="grp"><td colspan="3">Kontext-Chips</td></tr>
<tr><td>Omnivor</td><td>repeatTagTypes: ["protein","cuisine"], alle Gewichte Standard</td><td>Default-Preset = backend defaults</td></tr>
<tr><td>Vegetarisch</td><td>repeatTagTypes: ["cuisine"], wTagRepeat Standard</td><td>Protein deaktiviert</td></tr>
<tr><td>Vegan</td><td>repeatTagTypes: ["cuisine"], wTagRepeat Standard</td><td>Identisch zu Vegetarisch in v1</td></tr>
<tr><td>Individuell</td><td>Erscheint automatisch wenn Advanced abweicht vom Preset</td><td>Kein manuell wählbarer Chip — nur automatisch</td></tr>
<tr class="grp"><td colspan="3">Score-Banner (S1)</td></tr>
<tr><td>Wert</td><td>Aktueller Score (keine Simulation)</td><td>Label: "Aktueller Score"</td></tr>
<tr><td>Sub-Label</td><td>"Keine Änderungen"</td><td>Neutral-Farbe (#6B6A63)</td></tr>
</tbody></table>
</div>
</div>
<!-- S2: Vegetarisch selected -->
<div class="scr">
<div class="scr-head"><h3>S2 · Vegetarisch ausgewählt — Score-Simulation</h3><span class="scr-id">E4</span></div>
<div class="scr-desc">Planer tippt auf "Vegetarisch". Config wird sofort per PATCH gespeichert. Score-Banner lädt die simulierte Punktzahl: wie würde der aktuelle Plan mit der neuen Config abschneiden. Delta wird grün hervorgehoben. Protein-Pill wechselt zu "off". Erweiterte Einstellungen zeigt Protein-Toggle als deaktiviert.</div>
<div class="scr-var"><strong>S2</strong> · Vegetarisch selected · Score-Preview = simuliert · Protein-Pill = off</div>
<div class="previews">
<div class="prev-col">
<div class="bp-lbl">Mobile · 320px</div>
<div class="phone">
<div class="pst"><b>9:41</b><span>●●●</span></div>
<div class="pb">
<div class="mtb"><div class="mtb-back">← Einstellungen</div><div class="mtb-t">Vielfalt</div></div>
<div style="padding:16px;flex:1;overflow-y:auto;">
<div style="font-size:12px;color:var(--color-text-muted);line-height:1.6;margin-bottom:14px;">Passe den Algorithmus an deinen Haushalt an. Änderungen werden sofort übernommen.</div>
<div class="sec-lbl">Haushaltskontext</div>
<div class="ctx-chips">
<div class="ctx-chip"><div class="ctx-em">🥩</div><div class="ctx-name">Omnivor</div><div class="ctx-sub">Alle Regeln aktiv</div></div>
<div class="ctx-chip sel"><div class="ctx-em">🥦</div><div class="ctx-name">Vegetarisch</div><div class="ctx-sub">Protein deaktiviert</div></div>
<div class="ctx-chip"><div class="ctx-em">🌱</div><div class="ctx-name">Vegan</div><div class="ctx-sub">Protein deaktiviert</div></div>
</div>
<div class="sec-lbl">Aktive Regeln</div>
<div class="s-pills">
<div class="s-pill off"> Protein</div>
<div class="s-pill on">✓ Küche</div>
<div class="s-pill on">✓ Zutaten · Mittel</div>
<div class="s-pill on">✓ Letzte Wochen · Mittel</div>
<div class="s-pill warn">⚠ Duplikate · Hoch</div>
</div>
<div class="acc">
<div class="acc-hd"><div class="acc-hd-t">Erweiterte Einstellungen</div><div class="acc-hd-r"></div></div>
</div>
<div class="score-banner">
<div class="score-banner-l">
<div class="score-banner-label">Mit diesen Einstellungen</div>
<div class="score-banner-val">8.9</div>
<div class="score-banner-sub score-banner-up">↑ +1.5 gegenüber vorher</div>
</div>
<div class="score-banner-r">📈</div>
</div>
<div class="reset-link">Auf Standard zurücksetzen</div>
</div>
<div class="mbt">
<div class="mt-i"><div class="mt-ic">📅</div><div class="mt-l">Plan</div></div>
<div class="mt-i"><div class="mt-ic">🛒</div><div class="mt-l">Einkauf</div></div>
<div class="mt-i"><div class="mt-ic">🍳</div><div class="mt-l">Rezepte</div></div>
<div class="mt-i a"><div class="mt-ic">⚙️</div><div class="mt-l">Einstellungen</div></div>
</div>
</div>
</div>
</div>
<div class="prev-col" style="flex:1;min-width:600px;">
<div class="bp-lbl">Desktop · 1040px</div>
<div class="desk">
<div class="dsb">
<div class="dsb-logo"><div class="dsb-lm"><div class="dsb-ic">🥦</div><div class="dsb-nm">Mealprep</div></div><div class="dsb-sub">Familie Raddatz</div></div>
<div class="dsb-nav">
<div class="dsb-nl">Planung</div>
<div class="dsb-ni"><span class="dsb-nc">📅</span> Wochenplan</div>
<div class="dsb-ni"><span class="dsb-nc">🛒</span> Einkaufsliste</div>
<div class="dsb-ni"><span class="dsb-nc">🍳</span> Rezepte</div>
<div class="dsb-nl" style="margin-top:12px;">Haushalt</div>
<div class="dsb-ni a"><span class="dsb-nc">⚙️</span> Einstellungen</div>
</div>
</div>
<div class="dm">
<div class="dtb"><div><div class="dtb-bc">Einstellungen <span></span> Vielfalt-Einstellungen</div><div class="dtb-t">Vielfalt-Einstellungen</div></div></div>
<div class="dmc">
<div style="display:grid;grid-template-columns:1fr 280px;gap:24px;max-width:800px;">
<div>
<div style="font-size:12px;color:var(--color-text-muted);line-height:1.6;margin-bottom:16px;">Passe den Algorithmus an deinen Haushaltskontext an. Änderungen werden sofort übernommen und wirken sich auf den nächsten Score-Abruf aus.</div>
<div class="sec-lbl">Haushaltskontext</div>
<div class="ctx-chips" style="margin-bottom:20px;">
<div class="ctx-chip"><div class="ctx-em">🥩</div><div class="ctx-name">Omnivor</div><div class="ctx-sub">Alle Regeln aktiv</div></div>
<div class="ctx-chip sel"><div class="ctx-em">🥦</div><div class="ctx-name">Vegetarisch</div><div class="ctx-sub">Protein deaktiviert</div></div>
<div class="ctx-chip"><div class="ctx-em">🌱</div><div class="ctx-name">Vegan</div><div class="ctx-sub">Protein deaktiviert</div></div>
</div>
<div class="acc">
<div class="acc-hd"><div class="acc-hd-t">Erweiterte Einstellungen</div><div class="acc-hd-r"></div></div>
</div>
<div class="reset-link" style="text-align:left;">Auf Standard zurücksetzen</div>
</div>
<div>
<div class="score-banner">
<div>
<div class="score-banner-label">Mit diesen Einstellungen</div>
<div class="score-banner-val">8.9 <span style="font-size:13px;opacity:.5;">/ 10</span></div>
<div class="score-banner-sub score-banner-up">↑ +1.5 gegenüber vorher</div>
</div>
<div class="score-banner-r">📈</div>
</div>
<div class="sec-lbl">Aktive Regeln</div>
<div class="sum-rows">
<div class="sum-row off"><span class="sum-row-name">Protein</span><span class="sum-row-val">Deaktiviert</span></div>
<div class="sum-row on"><span class="sum-row-name">Küche</span><span class="sum-row-val">Mittel</span></div>
<div class="sum-row on"><span class="sum-row-name">Zutaten</span><span class="sum-row-val">Niedrig</span></div>
<div class="sum-row on"><span class="sum-row-name">Letzte Wochen</span><span class="sum-row-val">Mittel</span></div>
<div class="sum-row warn"><span class="sum-row-name">Duplikate</span><span class="sum-row-val">Hoch</span></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="agent">
<h4>E4 · S2 Vegetarisch</h4>
<pre>/* On chip tap (Vegetarisch):
* 1. Optimistic UI: swap selected chip, update pills, update sum-rows immediately.
* 2. PATCH /v1/households/mine/variety-config { repeatTagTypes: ["cuisine"],
* wTagRepeat: 1.5, wIngredientOverlap: 0.3, wRecentRepeat: 1.0, wPlanDuplicate: 2.0 }
* 3. On PATCH success: fire GET /v1/week-plans/{id}/variety-score?simulate=true
* with same config body → update score-banner with simulated score + delta.
* 4. On PATCH error: rollback to previous chip selection + show toast "Fehler beim Speichern".
* Score-Banner during load: show spinner in place of val. */</pre>
<table class="at"><thead><tr><th>Element</th><th>Wert</th><th>Notizen</th></tr></thead><tbody>
<tr class="grp"><td colspan="3">Score-Banner (S2)</td></tr>
<tr><td>Label</td><td>"Mit diesen Einstellungen"</td><td>Statt "Aktueller Score"</td></tr>
<tr><td>Delta</td><td>"↑ +X.X gegenüber vorher"</td><td>Grün (#6FCF97) wenn positiv; rot wenn negativ; neutral wenn = 0</td></tr>
<tr><td>Simulation-Endpoint</td><td>POST /v1/week-plans/{id}/variety-score/simulate</td><td>Body: VarietyScoreConfig-Felder. Neuer Endpoint nötig (Backend-Task).</td></tr>
<tr><td>Kein Plan</td><td>Score-Banner ausblenden</td><td>Kein simulierter Score ohne Plan möglich</td></tr>
<tr class="grp"><td colspan="3">Chip-Preset Vegetarisch</td></tr>
<tr><td>repeatTagTypes</td><td>["cuisine"]</td><td>Protein entfernt</td></tr>
<tr><td>wTagRepeat</td><td>1.5 (Standard)</td><td>Unverändert</td></tr>
<tr><td>wIngredientOverlap</td><td>0.3 (Standard)</td><td>Unverändert</td></tr>
<tr><td>wRecentRepeat</td><td>1.0 (Standard)</td><td>Unverändert</td></tr>
<tr><td>wPlanDuplicate</td><td>2.0 (Standard)</td><td>Unverändert</td></tr>
</tbody></table>
</div>
</div>
<!-- S3: Erweiterte Einstellungen -->
<div class="scr">
<div class="scr-head"><h3>S3 · Erweiterte Einstellungen geöffnet</h3><span class="scr-id">E4</span></div>
<div class="scr-desc">Planer öffnet das Accordion "Erweiterte Einstellungen". Er sieht Segmented Controls (Niedrig / Mittel / Hoch) für jeden Gewichts-Parameter. Ändert er einen Wert, der nicht mehr dem aktuellen Preset entspricht, erscheint automatisch ein vierter Chip "Individuell" (lila) und ersetzt den aktiven Preset-Chip. Score-Banner aktualisiert sich nach jeder Änderung.</div>
<div class="scr-var"><strong>S3</strong> · Erweiterte Einstellungen offen · "Individuell"-Chip erschienen (Planer hat Zutaten-Gewicht angepasst)</div>
<div class="previews">
<div class="prev-col">
<div class="bp-lbl">Mobile · 320px</div>
<div class="phone">
<div class="pst"><b>9:41</b><span>●●●</span></div>
<div class="pb">
<div class="mtb"><div class="mtb-back">← Einstellungen</div><div class="mtb-t">Vielfalt</div></div>
<div style="padding:16px;flex:1;overflow-y:auto;">
<div class="sec-lbl">Haushaltskontext</div>
<div class="ctx-chips" style="flex-wrap:wrap;">
<div class="ctx-chip" style="flex:1;min-width:60px;"><div class="ctx-em">🥩</div><div class="ctx-name">Omnivor</div></div>
<div class="ctx-chip" style="flex:1;min-width:60px;"><div class="ctx-em">🥦</div><div class="ctx-name">Vegetarisch</div></div>
<div class="ctx-chip" style="flex:1;min-width:60px;"><div class="ctx-em">🌱</div><div class="ctx-name">Vegan</div></div>
<div class="ctx-chip ind" style="flex:1;min-width:60px;"><div class="ctx-em"></div><div class="ctx-name">Individuell</div></div>
</div>
<div class="s-pills" style="margin-top:10px;">
<div class="s-pill off"> Protein</div>
<div class="s-pill on">✓ Küche</div>
<div class="s-pill on">✓ Zutaten · Hoch</div>
<div class="s-pill on">✓ Letzte Wochen · Mittel</div>
<div class="s-pill warn">⚠ Duplikate · Hoch</div>
</div>
<div class="acc">
<div class="acc-hd"><div class="acc-hd-t">Erweiterte Einstellungen</div><div class="acc-hd-r"></div></div>
<div class="acc-b">
<div style="font-size:10px;color:var(--color-text-muted);margin-bottom:10px;">Protein ist über den Kontext deaktiviert. Die übrigen Gewichte kannst du hier anpassen.</div>
<div class="wr">
<div class="wr-l"><div class="wr-name">Küche</div><div class="wr-sub">Tag-Wiederholung</div></div>
<div class="seg" style="width:108px"><div class="seg-o">Niedrig</div><div class="seg-o a">Mittel</div><div class="seg-o">Hoch</div></div>
</div>
<div class="wr">
<div class="wr-l"><div class="wr-name">Zutaten</div><div class="wr-sub">Überschneidung</div></div>
<div class="seg" style="width:108px"><div class="seg-o">Niedrig</div><div class="seg-o">Mittel</div><div class="seg-o a-r">Hoch</div></div>
</div>
<div class="wr">
<div class="wr-l"><div class="wr-name">Letzte Wochen</div><div class="wr-sub">Kochverlauf</div></div>
<div class="seg" style="width:108px"><div class="seg-o">Niedrig</div><div class="seg-o a">Mittel</div><div class="seg-o">Hoch</div></div>
</div>
<div class="wr">
<div class="wr-l"><div class="wr-name">Duplikate</div><div class="wr-sub">Im Plan</div></div>
<div class="seg" style="width:108px"><div class="seg-o">Niedrig</div><div class="seg-o">Mittel</div><div class="seg-o a-r">Hoch</div></div>
</div>
</div>
</div>
<div class="score-banner">
<div class="score-banner-l">
<div class="score-banner-label">Mit diesen Einstellungen</div>
<div class="score-banner-val">8.1</div>
<div class="score-banner-sub score-banner-up">↑ +0.7 gegenüber vorher</div>
</div>
<div class="score-banner-r">📈</div>
</div>
<div class="reset-link">Auf Standard zurücksetzen</div>
</div>
<div class="mbt">
<div class="mt-i"><div class="mt-ic">📅</div><div class="mt-l">Plan</div></div>
<div class="mt-i"><div class="mt-ic">🛒</div><div class="mt-l">Einkauf</div></div>
<div class="mt-i"><div class="mt-ic">🍳</div><div class="mt-l">Rezepte</div></div>
<div class="mt-i a"><div class="mt-ic">⚙️</div><div class="mt-l">Einstellungen</div></div>
</div>
</div>
</div>
</div>
<div class="prev-col" style="flex:1;min-width:600px;">
<div class="bp-lbl">Desktop · 1040px</div>
<div class="desk">
<div class="dsb">
<div class="dsb-logo"><div class="dsb-lm"><div class="dsb-ic">🥦</div><div class="dsb-nm">Mealprep</div></div><div class="dsb-sub">Familie Raddatz</div></div>
<div class="dsb-nav">
<div class="dsb-nl">Planung</div>
<div class="dsb-ni"><span class="dsb-nc">📅</span> Wochenplan</div>
<div class="dsb-ni"><span class="dsb-nc">🛒</span> Einkaufsliste</div>
<div class="dsb-ni"><span class="dsb-nc">🍳</span> Rezepte</div>
<div class="dsb-nl" style="margin-top:12px;">Haushalt</div>
<div class="dsb-ni a"><span class="dsb-nc">⚙️</span> Einstellungen</div>
</div>
</div>
<div class="dm">
<div class="dtb"><div><div class="dtb-bc">Einstellungen <span></span> Vielfalt-Einstellungen</div><div class="dtb-t">Vielfalt-Einstellungen</div></div></div>
<div class="dmc">
<div style="display:grid;grid-template-columns:1fr 280px;gap:24px;max-width:800px;">
<div>
<div class="sec-lbl">Haushaltskontext</div>
<div class="ctx-chips" style="margin-bottom:20px;">
<div class="ctx-chip"><div class="ctx-em">🥩</div><div class="ctx-name">Omnivor</div><div class="ctx-sub">Alle Regeln</div></div>
<div class="ctx-chip"><div class="ctx-em">🥦</div><div class="ctx-name">Vegetarisch</div><div class="ctx-sub">Protein aus</div></div>
<div class="ctx-chip"><div class="ctx-em">🌱</div><div class="ctx-name">Vegan</div><div class="ctx-sub">Protein aus</div></div>
<div class="ctx-chip ind"><div class="ctx-em"></div><div class="ctx-name">Individuell</div><div class="ctx-sub">Benutzerdefiniert</div></div>
</div>
<div class="acc">
<div class="acc-hd"><div class="acc-hd-t">Erweiterte Einstellungen</div><div class="acc-hd-r"></div></div>
<div class="acc-b">
<div style="font-size:11px;color:var(--color-text-muted);margin-bottom:12px;">Protein ist über den Haushaltskontext deaktiviert. Passe die Stärke der übrigen Regeln an.</div>
<div class="wr">
<div class="wr-l"><div class="wr-name">Küchen-Wiederholung</div><div class="wr-sub">Gleiche Küche an aufeinanderfolgenden Tagen</div></div>
<div class="seg" style="width:160px"><div class="seg-o">Niedrig</div><div class="seg-o a">Mittel</div><div class="seg-o">Hoch</div></div>
</div>
<div class="wr">
<div class="wr-l"><div class="wr-name">Zutaten-Überschneidung</div><div class="wr-sub">Gleiche Zutaten an aufeinanderfolgenden Tagen</div></div>
<div class="seg" style="width:160px"><div class="seg-o">Niedrig</div><div class="seg-o">Mittel</div><div class="seg-o a-r">Hoch</div></div>
</div>
<div class="wr">
<div class="wr-l"><div class="wr-name">Letzte Wochen</div><div class="wr-sub">Kochverlauf (14 Tage)</div></div>
<div class="seg" style="width:160px"><div class="seg-o">Niedrig</div><div class="seg-o a">Mittel</div><div class="seg-o">Hoch</div></div>
</div>
<div class="wr">
<div class="wr-l"><div class="wr-name">Doppelte Rezepte</div><div class="wr-sub">Gleiches Rezept mehrfach im Plan</div></div>
<div class="seg" style="width:160px"><div class="seg-o">Niedrig</div><div class="seg-o">Mittel</div><div class="seg-o a-r">Hoch</div></div>
</div>
</div>
</div>
<div class="reset-link" style="text-align:left;">Auf Standard zurücksetzen</div>
</div>
<div>
<div class="score-banner">
<div>
<div class="score-banner-label">Mit diesen Einstellungen</div>
<div class="score-banner-val">8.1 <span style="font-size:13px;opacity:.5;">/ 10</span></div>
<div class="score-banner-sub score-banner-up">↑ +0.7 gegenüber vorher</div>
</div>
<div class="score-banner-r">📈</div>
</div>
<div class="sec-lbl">Aktive Regeln</div>
<div class="sum-rows">
<div class="sum-row off"><span class="sum-row-name">Protein</span><span class="sum-row-val">Deaktiviert</span></div>
<div class="sum-row on"><span class="sum-row-name">Küche</span><span class="sum-row-val">Mittel</span></div>
<div class="sum-row warn"><span class="sum-row-name">Zutaten</span><span class="sum-row-val">Hoch ↑</span></div>
<div class="sum-row on"><span class="sum-row-name">Letzte Wochen</span><span class="sum-row-val">Mittel</span></div>
<div class="sum-row warn"><span class="sum-row-name">Duplikate</span><span class="sum-row-val">Hoch</span></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="agent">
<h4>E4 · S3 Erweiterte Einstellungen</h4>
<pre>/* Accordion öffnet sich per Click/Tap auf acc-hd. Keine Animation nötig — display toggle reicht.
* Erweiterte Einstellungen zeigt NUR aktive Tag-Typen als Gewichts-Rows.
* Wenn Protein deaktiviert (über Preset): Protein-Row wird in acc-b NICHT angezeigt.
* "Individuell"-Chip: erscheint automatisch wenn die Kombination repeatTagTypes+weights
* nicht exakt einem der drei Presets entspricht. Kein manueller Auslöser.
* Gewichts-Änderung → PATCH → Score-Simulation → Banner-Update.
* Debounce der Simulation: 300ms nach letzter Interaktion. */</pre>
<table class="at"><thead><tr><th>Element</th><th>Wert</th><th>Notizen</th></tr></thead><tbody>
<tr class="grp"><td colspan="3">Gewicht-Mapping</td></tr>
<tr><td>Niedrig</td><td>Faktor 0.5 × Standard-Gewicht</td><td>wTagRepeat: 0.75, wIngredient: 0.15, wRecent: 0.5, wDuplicate: 1.0</td></tr>
<tr><td>Mittel</td><td>Faktor 1.0 (Standard)</td><td>wTagRepeat: 1.5, wIngredient: 0.3, wRecent: 1.0, wDuplicate: 2.0</td></tr>
<tr><td>Hoch</td><td>Faktor 1.5 × Standard-Gewicht</td><td>wTagRepeat: 2.25, wIngredient: 0.45, wRecent: 1.5, wDuplicate: 3.0</td></tr>
<tr class="grp"><td colspan="3">Individuell-Chip</td></tr>
<tr><td>Trigger</td><td>Wenn gespeicherter Config ≠ Omnivor, Vegetarisch, oder Vegan Preset</td><td>Lila Border + Hintergrund</td></tr>
<tr><td>Symbol</td><td>✦ (U+2726)</td><td>Statt Emoji</td></tr>
<tr><td>Label</td><td>Individuell</td><td>Nicht anklickbar — nur Status-Indikator</td></tr>
<tr class="grp"><td colspan="3">Simulation-Debounce</td></tr>
<tr><td>Delay</td><td>300ms</td><td>Nach letzter Segmented-Control-Interaktion</td></tr>
<tr><td>Während Laden</td><td>Score-Wert zeigt Spinner (CSS animation)</td><td>Kein Skeleton — nur val-Bereich</td></tr>
</tbody></table>
</div>
</div>
<!-- S4: Reset confirmation -->
<div class="scr">
<div class="scr-head"><h3>S4 · Reset-Bestätigung</h3><span class="scr-id">E4</span></div>
<div class="scr-desc">Planer tippt "Auf Standard zurücksetzen". Ein Dialog erscheint und benennt explizit, was zurückgesetzt wird. Bestätigung löscht den Custom-Config-Eintrag (DELETE) und stellt die Omnivor-Defaults wieder her. Kein Backdrop-Dismiss — der Planer muss explizit wählen.</div>
<div class="scr-var"><strong>S4</strong> · Modal über S2-Zustand · Backdrop nicht anklickbar · Mobile: Bottom Sheet</div>
<div class="previews">
<div class="prev-col">
<div class="bp-lbl">Mobile · 320px (Bottom Sheet)</div>
<div class="phone">
<div class="pst"><b>9:41</b><span>●●●</span></div>
<div class="pb">
<!-- Blurred background state -->
<div class="mtb"><div class="mtb-back">← Einstellungen</div><div class="mtb-t">Vielfalt</div></div>
<div style="padding:16px;flex:1;overflow-y:auto;opacity:.35;pointer-events:none;">
<div class="ctx-chips">
<div class="ctx-chip sel"><div class="ctx-em">🥦</div><div class="ctx-name">Vegetarisch</div></div>
</div>
</div>
<!-- Bottom sheet -->
<div style="background:var(--color-page);border-radius:20px 20px 0 0;padding:20px;border-top:1px solid var(--color-border);box-shadow:0 -4px 24px rgba(0,0,0,.12);">
<div style="width:36px;height:4px;background:var(--color-border);border-radius:2px;margin:0 auto 16px;"></div>
<div style="font-family:var(--font-display);font-size:18px;font-weight:500;margin-bottom:8px;">Auf Standard zurücksetzen?</div>
<div style="font-size:12px;color:var(--color-text-muted);line-height:1.6;margin-bottom:16px;">Alle individuellen Einstellungen werden gelöscht. Der Algorithmus verwendet dann wieder:<br><br>• Protein: Aktiv<br>• Küche: Aktiv<br>• Alle Gewichte: Mittel</div>
<div class="btn-dest" style="margin-bottom:8px;">Zurücksetzen</div>
<div class="btn-ghost">Abbrechen</div>
</div>
<div class="mbt">
<div class="mt-i"><div class="mt-ic">📅</div><div class="mt-l">Plan</div></div>
<div class="mt-i"><div class="mt-ic">🛒</div><div class="mt-l">Einkauf</div></div>
<div class="mt-i"><div class="mt-ic">🍳</div><div class="mt-l">Rezepte</div></div>
<div class="mt-i a"><div class="mt-ic">⚙️</div><div class="mt-l">Einstellungen</div></div>
</div>
</div>
</div>
</div>
<div class="prev-col" style="flex:1;min-width:600px;">
<div class="bp-lbl">Desktop · 1040px (Centered Modal)</div>
<div class="desk overlay">
<div class="dsb" style="opacity:.35;">
<div class="dsb-logo"><div class="dsb-lm"><div class="dsb-ic">🥦</div><div class="dsb-nm">Mealprep</div></div></div>
</div>
<div class="dm" style="opacity:.35;">
<div class="dtb"><div class="dtb-t">Vielfalt-Einstellungen</div></div>
<div class="dmc"><div class="ctx-chips"><div class="ctx-chip sel"><div class="ctx-em">🥦</div><div class="ctx-name">Vegetarisch</div></div></div></div>
</div>
<div class="modal-backdrop">
<div class="modal">
<div class="modal-title">Auf Standard zurücksetzen?</div>
<div class="modal-body">Alle individuellen Einstellungen werden gelöscht. Der Algorithmus verwendet dann wieder die Standard-Werte:<br><br>
<strong>Protein-Prüfung:</strong> Aktiv<br>
<strong>Küchen-Vielfalt:</strong> Aktiv<br>
<strong>Alle Gewichte:</strong> Mittel</div>
<div class="modal-acts">
<div class="btn-dest">Zurücksetzen</div>
<div class="btn-ghost">Abbrechen</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="agent">
<h4>E4 · S4 Reset-Bestätigung</h4>
<pre>/* Reset-Link Tap → Dialog öffnet (kein Backdrop-Dismiss, kein Escape-Dismiss).
* "Zurücksetzen" → DELETE /v1/households/mine/variety-config
* On success: optimistic reset von UI zu S1 (Omnivor), Score-Banner zeigt echten Score.
* On error: Toast "Fehler beim Zurücksetzen".
* Mobile: Bottom Sheet (position:fixed, bottom 0, border-radius 20px 20px 0 0).
* Desktop: centered modal, backdrop rgba(28,28,24,0.4), max-width 380px. */</pre>
<table class="at"><thead><tr><th>Element</th><th>Wert</th><th>Notizen</th></tr></thead><tbody>
<tr class="grp"><td colspan="3">Dialog-Inhalt</td></tr>
<tr><td>Titel</td><td>"Auf Standard zurücksetzen?"</td><td>Fraunces 18px (Mobile), 20px (Desktop)</td></tr>
<tr><td>Body</td><td>Auflistung der zurückgesetzten Werte</td><td>Muss konkret benennen: Protein aktiv, Küche aktiv, alle Gewichte Mittel</td></tr>
<tr><td>Primär-Aktion</td><td>"Zurücksetzen" → DELETE</td><td>Hintergrund: --red, Text: weiß</td></tr>
<tr><td>Sekundär-Aktion</td><td>"Abbrechen"</td><td>Ghost-Button, schließt Dialog</td></tr>
<tr class="grp"><td colspan="3">API</td></tr>
<tr><td>Endpoint</td><td>DELETE /v1/households/mine/variety-config</td><td>Löscht Custom-Config-Row; Backend fällt auf Defaults zurück</td></tr>
<tr><td>On Success</td><td>UI reset zu S1</td><td>Omnivor chip selected, Score-Banner: echter Score</td></tr>
</tbody></table>
</div>
</div>
</div>
<!-- ════════════════════════════════════════
LLM / AGENT REGION
═════════════════════════════════════════ -->
<div class="llm">
<h2>Maschinenlesbare Spezifikation — E4 Vielfalt-Einstellungen</h2>
<h3>Screens</h3>
<table>
<thead><tr><th>Screen</th><th>Route</th><th>Zugriff</th><th>Zweck</th></tr></thead>
<tbody>
<tr><td>E1 (Update)</td><td>/settings</td><td>Planer</td><td>Settings-Hub: dritte Kachel "Vielfalt-Einstellungen" mit aktuellem Score</td></tr>
<tr><td>E4</td><td>/settings/variety</td><td>Planer only</td><td>Vielfalt-Algorithmus per Kontext-Preset und Feineinstellungen konfigurieren</td></tr>
</tbody>
</table>
<h3>States</h3>
<table>
<thead><tr><th>State</th><th>Trigger</th><th>Beschreibung</th></tr></thead>
<tbody>
<tr><td>S0</td><td>E1 load</td><td>Settings-Hub zeigt Score-Kachel (lila Kennzahl)</td></tr>
<tr><td>S1</td><td>E4 load, kein Custom-Config</td><td>Omnivor chip selected, Score = aktueller echter Score, Reset-Link = deaktiviert/neutral</td></tr>
<tr><td>S2</td><td>Preset-Chip tap</td><td>Chip wechselt, PATCH, Score-Simulation lädt und zeigt Delta</td></tr>
<tr><td>S3</td><td>Accordion öffnen + Gewicht ändern</td><td>Individuell-Chip erscheint, Score-Simulation mit Debounce 300ms</td></tr>
<tr><td>S4</td><td>Reset-Link tap</td><td>Modal/Bottom Sheet — Bestätigung vor DELETE</td></tr>
</tbody>
</table>
<h3>API-Endpoints (neu + bestehend)</h3>
<table>
<thead><tr><th>Method</th><th>Endpoint</th><th>Neu?</th><th>Zweck</th></tr></thead>
<tbody>
<tr><td>GET</td><td>/v1/households/mine/variety-config</td><td>Neu</td><td>Aktuellen Config laden; 404 = Defaults verwenden</td></tr>
<tr><td>PATCH</td><td>/v1/households/mine/variety-config</td><td>Neu</td><td>Config speichern (auto-save bei jedem Preset/Gewicht-Wechsel)</td></tr>
<tr><td>DELETE</td><td>/v1/households/mine/variety-config</td><td>Neu</td><td>Custom-Config löschen, Backend fällt auf Defaults zurück</td></tr>
<tr><td>POST</td><td>/v1/week-plans/{id}/variety-score/simulate</td><td>Neu</td><td>Score simulieren mit temporärem Config-Body (nicht persistiert)</td></tr>
<tr><td>GET</td><td>/v1/week-plans/{id}/variety-score</td><td>Bestehend</td><td>Aktuellen Score laden (für S1 Banner + E1 Kachel)</td></tr>
</tbody>
</table>
<h3>Kontext-Preset Mapping</h3>
<table>
<thead><tr><th>Preset</th><th>repeatTagTypes</th><th>wTagRepeat</th><th>wIngredientOverlap</th><th>wRecentRepeat</th><th>wPlanDuplicate</th></tr></thead>
<tbody>
<tr><td>Omnivor (Default)</td><td>["protein","cuisine"]</td><td>1.5</td><td>0.3</td><td>1.0</td><td>2.0</td></tr>
<tr><td>Vegetarisch</td><td>["cuisine"]</td><td>1.5</td><td>0.3</td><td>1.0</td><td>2.0</td></tr>
<tr><td>Vegan</td><td>["cuisine"]</td><td>1.5</td><td>0.3</td><td>1.0</td><td>2.0</td></tr>
<tr><td>Individuell</td><td>Beliebig (≠ obige Presets)</td><td>Beliebig</td><td>Beliebig</td><td>Beliebig</td><td>Beliebig</td></tr>
</tbody>
</table>
<h3>Gewicht-Preset Mapping</h3>
<table>
<thead><tr><th>Stufe</th><th>Faktor</th><th>wTagRepeat</th><th>wIngredientOverlap</th><th>wRecentRepeat</th><th>wPlanDuplicate</th></tr></thead>
<tbody>
<tr><td>Niedrig</td><td>×0.5</td><td>0.75</td><td>0.15</td><td>0.5</td><td>1.0</td></tr>
<tr><td>Mittel</td><td>×1.0</td><td>1.5</td><td>0.3</td><td>1.0</td><td>2.0</td></tr>
<tr><td>Hoch</td><td>×1.5</td><td>2.25</td><td>0.45</td><td>1.5</td><td>3.0</td></tr>
</tbody>
</table>
<h3>Implementierungsregeln (für Agenten)</h3>
<ul>
<li>E4 ist nur für <code>rolle === 'planer'</code> zugänglich. Mitglieder werden auf E1 redirected.</li>
<li>Auto-Save auf jede Preset- oder Gewicht-Änderung. Kein expliziter Speichern-Button.</li>
<li>Optimistic Update: UI wechselt sofort; Rollback mit Toast bei API-Fehler.</li>
<li>Score-Simulation: Debounce 300ms. Während Laden: Spinner im Score-Wert-Bereich (nicht Skeleton).</li>
<li>"Individuell"-Chip ist nicht anklickbar — er ist ein reiner Status-Indikator.</li>
<li>Reset-Bestätigung: Backdrop-Dismiss deaktiviert (nicht schließbar durch Klick/Tap auf Overlay).</li>
<li>Mobile Reset: Bottom Sheet mit Handle-Bar (36×4px, --color-border, border-radius 2px). Kein Backdrop-Dismiss.</li>
<li>Desktop Reset: Zentriertes Modal, max-width 380px. Backdrop rgba(28,28,24,0.4).</li>
<li>E1 Vielfalt-Kachel: Score < 6.0 Kennzahl in --orange; Score 6.0 Kennzahl in --purple.</li>
<li>E4-Route: <code>(app)/settings/variety/+page.svelte</code>. Load-Funktion: <code>+page.server.ts</code> → Promise.all([GET variety-config, GET variety-score]).</li>
</ul>
</div>
</div>
</body>
</html>