Files
mealprep/specs/frontend/j3-cook-tonight.html
Marcel Raddatz b36d4c731d Add frontend journey specs with visual previews and LLM instructions
Six self-contained HTML documents, one per user journey, each combining
mobile/desktop previews with machine-readable implementation guides:

- j1-add-recipe.html (B1, B3)
- j2-plan-the-week.html (C1, C2, C3)
- j3-cook-tonight.html (B2, B4)
- j4-adapt-on-the-fly.html (swap trigger, C2 swap)
- j5-shopping-list.html (D1)
- j6-household-setup.html (A1, A2, A3/D3, A4)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 12:17:47 +02:00

396 lines
35 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>J3 — Cook Tonight</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:#534AB7;--purple-dark:#3C3489;--orange-tint:#FEF0E6;--orange:#E8862A;--orange-dark:#B46820;--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;}
/* Header */
.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);}
/* Sections */
.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 headers */
.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 #CECBF6;}.jh-p .jn{color:var(--purple);}.jh-p p,.jh-p .fl{color:var(--purple-dark);}
.jh-g{background:var(--green-tint);border:1px solid var(--green-light);}.jh-g .jn{color:var(--green);}.jh-g p,.jh-g .fl{color:var(--green-dark);}
.jh-y{background:var(--yellow-tint);border:1px solid var(--yellow-light);}.jh-y .jn{color:var(--yellow-dark);}.jh-y p,.jh-y .fl{color:var(--yellow-text);}
.jh-o{background:var(--orange-tint);border:1px solid #FBCDA4;}.jh-o .jn{color:var(--orange);}.jh-o p,.jh-o .fl{color:var(--orange-dark);}
.jh-b{background:var(--blue-tint);border:1px solid var(--blue-light);}.jh-b .jn{color:var(--blue);}.jh-b p,.jh-b .fl{color:var(--blue-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);}
/* Preview container */
.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 frame - 320px */
.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;}
/* Desktop frame - 1040px */
.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;}
/* Shared nav components */
.mtb{padding:10px 16px;background:var(--color-page);border-bottom:1px solid var(--color-border);display:flex;justify-content:space-between;align-items:center;}
.mtb-t{font-family:var(--font-display);font-size:20px;font-weight:500;letter-spacing:-.02em;}
.mi{width:32px;height:32px;border-radius:var(--radius-md);border:1px solid var(--color-border);background:var(--color-surface);display:flex;align-items:center;justify-content:center;font-size:13px;color:var(--color-text-muted);flex-shrink:0;}.mi.gn{background:var(--green);border-color:var(--green);color:#fff;}
.mbt{border-top:1px solid var(--color-border);background:var(--color-surface);padding:8px 16px 28px;display:flex;justify-content:space-around;}
.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);}
/* Desktop sidebar - 224px per nav-spec */
.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;cursor:default;}.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:12px 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-r{display:flex;align-items:center;gap:8px;}
.dab{font-family:var(--font-sans);font-size:13px;font-weight:500;padding:7px 16px;border-radius:var(--radius-md);background:var(--green);color:#fff;border:none;}
.dab-b{background:var(--blue);}
/* Shared form */
.fi{width:100%;font-family:var(--font-sans);font-size:14px;padding:10px 12px;border-radius:var(--radius-md);border:1px solid var(--color-border);background:var(--color-page);color:var(--color-text);outline:none;}
.fl{font-size:12px;font-weight:500;color:var(--color-text);margin-bottom:6px;display:block;}
.fg{margin-bottom:16px;}
.bp{font-family:var(--font-sans);font-size:14px;font-weight:500;padding:12px 24px;border-radius:var(--radius-md);background:var(--green);color:#fff;border:none;cursor:pointer;width:100%;}
.bg{font-family:var(--font-sans);font-size:13px;font-weight:500;padding:10px 20px;border-radius:var(--radius-md);background:var(--color-subtle);color:var(--color-text-muted);border:1px solid var(--color-border);cursor:pointer;}
/* Tags */
.tc{display:inline-flex;font-size:12px;font-weight:500;padding:6px 12px;border-radius:20px;border:1px solid var(--color-border);background:var(--color-surface);color:var(--color-text-muted);cursor:pointer;margin:0 4px 4px 0;user-select:none;}.tc.s{background:var(--green-tint);color:var(--green-dark);border-color:var(--green-light);}
.badge{font-size:9px;font-weight:500;padding:2px 6px;border-radius:3px;display:inline-block;}.badge-g{background:var(--green-tint);color:var(--green-dark);}.badge-y{background:var(--yellow-tint);color:var(--yellow-text);}.badge-m{background:var(--color-subtle);color:var(--color-text-muted);}
/* Ingredient rows */
.ir{display:flex;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--color-subtle);}.ir:last-child{border-bottom:none;}.ir-q{font-family:var(--font-mono);font-size:12px;color:var(--color-text-muted);width:55px;flex-shrink:0;text-align:right;}.ir-n{font-size:13px;color:var(--color-text);flex:1;}.ir-x{font-size:14px;color:var(--color-border);cursor:pointer;width:20px;text-align:center;}
/* Checklist */
.ck{display:flex;align-items:center;gap:10px;padding:10px 0;border-bottom:1px solid var(--color-subtle);cursor:pointer;}.ck:last-child{border-bottom:none;}.ck-b{width:22px;height:22px;border-radius:4px;border:2px solid var(--color-border);flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:11px;}.ck.d .ck-b{background:var(--green);border-color:var(--green);color:#fff;}.ck-c{flex:1;}.ck-n{font-size:14px;color:var(--color-text);}.ck.d .ck-n{text-decoration:line-through;color:var(--color-text-muted);}.ck-s{font-size:10px;color:var(--color-text-muted);}.ck-q{font-family:var(--font-mono);font-size:12px;color:var(--color-text-muted);flex-shrink:0;}
/* Suggestion cards */
.sg{background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:12px;margin-bottom:8px;display:flex;align-items:center;gap:10px;}.sg-r{font-family:var(--font-display);font-size:16px;font-weight:300;color:var(--color-text-muted);width:20px;text-align:center;flex-shrink:0;}.sg-b{flex:1;}.sg-n{font-family:var(--font-display);font-size:13px;font-weight:400;color:var(--color-text);margin-bottom:2px;}.sg-i{font-size:10px;color:var(--color-text-muted);}.sg-w{font-size:9px;color:var(--green-dark);background:var(--green-tint);padding:2px 6px;border-radius:3px;display:inline-block;margin-top:3px;}.sg-p{font-size:11px;font-weight:500;color:var(--green);flex-shrink:0;}
/* Eyebrow labels */
.eye{font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--color-text-muted);}
/* Agent table */
.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 instruction 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);}
@media(max-width:900px){.doc{padding:24px 16px 80px;}}
</style>
</head>
<body>
<div class="doc">
<!-- ═══ J3 COOK TONIGHT ═══ -->
<div class="jh jh-g" style="background:var(--green-tint);">
<div class="jn" style="color:var(--green-dark);">J3</div>
<div><h2>Cook tonight</h2><p>Recipe detail → cook mode → mark as cooked. Kitchen context.</p><div class="fl">C1 → B2 → B4 → C1 · 16px body, 1.75 line-height, wake lock</div></div>
</div>
<!-- ═══ B2 RECIPE DETAIL ═══ -->
<div class="scr" id="b2">
<div class="scr-head"><h3>Recipe detail</h3><span class="scr-id">B2</span></div>
<div class="scr-desc">V2 Hero header. Desktop: sidebar + full-width hero banner spanning the content area + two-column content below (ingredients left, steps right). The hero fills the horizontal space — it's not a card, it's a page section with a distinct background.</div>
<div class="scr-var"><strong>V2 · Hero header</strong> — banner CTA, 2-col content on desktop</div>
<div class="previews">
<div class="prev-col">
<div class="bp-lbl">Mobile · 320px</div>
<div class="phone">
<div class="pst"><b>18:32</b><span>●●● WiFi 🔋</span></div>
<div class="pb">
<div style="background:var(--green-tint);padding:24px 20px 20px;border-bottom:1px solid var(--green-light);">
<div style="font-size:13px;color:var(--green-dark);font-weight:500;margin-bottom:12px;">← Planner</div>
<div style="font-family:var(--font-display);font-size:24px;font-weight:500;letter-spacing:-.02em;color:var(--green-deeper);margin-bottom:6px;">Slow-roasted tomato pasta</div>
<div style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:8px;">
<span style="font-size:10px;font-weight:500;padding:3px 8px;border-radius:12px;background:rgba(255,255,255,.6);color:var(--green-dark);">45 min</span>
<span style="font-size:10px;font-weight:500;padding:3px 8px;border-radius:12px;background:rgba(255,255,255,.6);color:var(--green-dark);">Easy</span>
<span style="font-size:10px;font-weight:500;padding:3px 8px;border-radius:12px;background:rgba(255,255,255,.6);color:var(--green-dark);">Serves 4</span>
</div>
<button class="bp" style="background:var(--green-dark);font-size:15px;padding:12px;">🍳 Start cooking</button>
</div>
<div style="padding:16px;">
<div class="eye" style="margin-bottom:8px;">Ingredients</div>
<div style="border:1px solid var(--color-border);border-radius:var(--radius-lg);padding:4px 12px;margin-bottom:16px;">
<div class="ir"><div class="ir-q">500g</div><div class="ir-n">Cherry tomatoes</div></div>
<div class="ir"><div class="ir-q">300g</div><div class="ir-n">Penne pasta</div></div>
<div class="ir"><div class="ir-q">3 cloves</div><div class="ir-n">Garlic</div></div>
<div class="ir"><div class="ir-q">2 tbsp</div><div class="ir-n">Olive oil</div></div>
</div>
<div class="eye" style="margin-bottom:8px;">Steps</div>
<div style="display:flex;gap:10px;padding:8px 0;border-bottom:1px solid var(--color-subtle);"><div style="width:22px;height:22px;border-radius:50%;background:var(--color-subtle);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:500;flex-shrink:0;">1</div><div style="font-size:13px;line-height:1.5;">Preheat oven to 180°C. Halve tomatoes.</div></div>
<div style="display:flex;gap:10px;padding:8px 0;border-bottom:1px solid var(--color-subtle);"><div style="width:22px;height:22px;border-radius:50%;background:var(--color-subtle);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:500;flex-shrink:0;">2</div><div style="font-size:13px;line-height:1.5;">Drizzle with oil, season, roast 40 min.</div></div>
<div style="display:flex;gap:10px;padding:8px 0;"><div style="width:22px;height:22px;border-radius:50%;background:var(--color-subtle);display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:500;flex-shrink:0;">3</div><div style="font-size:13px;line-height:1.5;">Cook pasta. Toss with roasted tomatoes and garlic.</div></div>
</div>
</div>
</div>
</div>
<div class="prev-col">
<div class="bp-lbl">Desktop · 1040px</div>
<div class="desk" style="min-height:560px;">
<div class="dsb">
<div class="dsb-logo"><div class="dsb-lm"><div class="dsb-ic">🥗</div><div class="dsb-nm">Mealplan</div></div><div class="dsb-sub">Smith household</div></div>
<div class="dsb-nav"><div><div class="dsb-nl">Plan</div><div class="dsb-ni"><span class="dsb-nc">📅</span>Planner</div><div class="dsb-ni a"><span class="dsb-nc">📖</span>Recipes</div><div class="dsb-ni"><span class="dsb-nc">🛒</span>Shopping</div></div></div>
</div>
<div class="dm">
<div class="dtb"><div style="display:flex;align-items:center;gap:8px;"><span style="font-size:13px;color:var(--color-text-muted);">← Recipes</span><span style="color:var(--color-border);">/</span><span class="dtb-t">Slow-roasted tomato pasta</span></div><div class="dtb-r"><button class="bg" style="padding:7px 14px;font-size:12px;">✏️ Edit</button></div></div>
<!-- Hero banner: full content width -->
<div style="background:var(--green-tint);padding:32px;border-bottom:1px solid var(--green-light);display:flex;align-items:center;gap:32px;">
<div style="flex:1;">
<div style="font-family:var(--font-display);font-size:28px;font-weight:500;letter-spacing:-.02em;color:var(--green-deeper);margin-bottom:8px;">Slow-roasted tomato pasta</div>
<div style="display:flex;gap:6px;margin-bottom:12px;">
<span style="font-size:11px;font-weight:500;padding:4px 10px;border-radius:12px;background:rgba(255,255,255,.6);color:var(--green-dark);">45 min</span>
<span style="font-size:11px;font-weight:500;padding:4px 10px;border-radius:12px;background:rgba(255,255,255,.6);color:var(--green-dark);">Easy</span>
<span style="font-size:11px;font-weight:500;padding:4px 10px;border-radius:12px;background:rgba(255,255,255,.6);color:var(--green-dark);">Serves 4</span>
<span style="font-size:11px;font-weight:500;padding:4px 10px;border-radius:12px;background:rgba(255,255,255,.6);color:var(--green-dark);">Vegetarian</span>
<span style="font-size:11px;font-weight:500;padding:4px 10px;border-radius:12px;background:rgba(255,255,255,.6);color:var(--green-dark);">Child-friendly</span>
</div>
<div style="font-size:13px;color:var(--green-dark);line-height:1.5;max-width:400px;">Roasting the tomatoes concentrates their sweetness — great for the kids and easy to batch cook.</div>
</div>
<button class="bp" style="width:auto;padding:14px 28px;font-size:15px;background:var(--green-dark);flex-shrink:0;">🍳 Start cooking</button>
</div>
<!-- 2-col: ingredients left, steps right -->
<div style="flex:1;display:flex;overflow:hidden;">
<div style="flex:1;padding:24px;border-right:1px solid var(--color-border);overflow-y:auto;">
<div class="eye" style="margin-bottom:10px;">Ingredients · 4 items</div>
<div class="ir"><div class="ir-q">500g</div><div class="ir-n">Cherry tomatoes</div></div>
<div class="ir"><div class="ir-q">300g</div><div class="ir-n">Penne pasta</div></div>
<div class="ir"><div class="ir-q">3 cloves</div><div class="ir-n">Garlic</div></div>
<div class="ir"><div class="ir-q">2 tbsp</div><div class="ir-n">Olive oil</div></div>
</div>
<div style="flex:1;padding:24px;overflow-y:auto;">
<div class="eye" style="margin-bottom:10px;">Steps · 3</div>
<div style="display:flex;gap:12px;padding:10px 0;border-bottom:1px solid var(--color-subtle);"><div style="width:28px;height:28px;border-radius:50%;background:var(--color-subtle);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;flex-shrink:0;">1</div><div style="font-size:14px;line-height:1.6;">Preheat oven to 180°C. Halve the cherry tomatoes and place cut-side up on a large baking tray.</div></div>
<div style="display:flex;gap:12px;padding:10px 0;border-bottom:1px solid var(--color-subtle);"><div style="width:28px;height:28px;border-radius:50%;background:var(--color-subtle);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;flex-shrink:0;">2</div><div style="font-size:14px;line-height:1.6;">Drizzle generously with olive oil, season with salt and pepper. Roast for 40 minutes until caramelized.</div></div>
<div style="display:flex;gap:12px;padding:10px 0;"><div style="width:28px;height:28px;border-radius:50%;background:var(--color-subtle);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;flex-shrink:0;">3</div><div style="font-size:14px;line-height:1.6;">Cook pasta according to package. Toss with roasted tomatoes and minced garlic. Serve with fresh basil.</div></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="agent">
<h4>B2 · Recipe detail</h4>
<pre>/* Desktop: sidebar + topbar (breadcrumb + Edit button) + hero banner (full width, green-tint) + 2-col below.
* Hero: name Fraunces 28px + tag pills + description + Cook button on the right.
* Below hero: ingredients (left, border-right) + steps (right). Both panels scroll independently.
* Hero with image: hero_image_url as bg, 40% dark overlay, text in white.
* Mobile: hero banner → stacked ingredients → steps.
* "Start cooking" → B4. "Edit" → B3 in edit mode. */</pre>
<table class="at"><thead><tr><th>Element</th><th>Value</th><th>Notes</th></tr></thead><tbody>
<tr class="grp"><td colspan="3">Desktop hero</td></tr>
<tr><td>Layout</td><td>Full content width, green-tint bg, 32px padding</td><td>Flex: info left (flex:1) + Cook button right (flex-shrink:0)</td></tr>
<tr><td>Name</td><td>Fraunces 28px/500, green-deeper</td><td>With image: #fff on dark overlay</td></tr>
<tr class="grp"><td colspan="3">Desktop content below hero</td></tr>
<tr><td>Ingredients</td><td>flex:1, 24px padding, border-right</td><td>ir-row component. Scrolls independently.</td></tr>
<tr><td>Steps</td><td>flex:1, 24px padding</td><td>Numbered circles (28px) + 14px body text, 1.6 line-height.</td></tr>
</tbody></table>
</div>
</div>
<!-- ═══ B4 COOK MODE ═══ -->
<div class="scr" id="b4">
<div class="scr-head"><h3>Cook mode</h3><span class="scr-id">B4</span></div>
<div class="scr-desc">V1 Centered step. Full-screen on ALL breakpoints — intentionally no sidebar, no tabs, no nav chrome. Kitchen context doesn't change with screen size. Only the text max-width scales (260→400px). The entire screen body is the tap target.</div>
<div class="scr-var"><strong>V1 · Centered step</strong> — same layout everywhere. No desktop sidebar. Tap anywhere.</div>
<div class="previews">
<div class="prev-col">
<div class="bp-lbl">Mobile · Step 2 of 3</div>
<div class="phone">
<div class="pst"><b>18:45</b><span>●●● WiFi 🔋</span></div>
<div class="pb" style="cursor:pointer;">
<div style="padding:10px 16px;display:flex;justify-content:space-between;align-items:center;">
<div style="font-size:12px;color:var(--color-error);font-weight:500;">✕ Exit</div>
<div style="font-size:11px;color:var(--color-text-muted);">Step 2 of 3</div>
<div style="width:40px;"></div>
</div>
<div style="padding:0 16px;"><div style="height:4px;background:var(--color-subtle);border-radius:2px;overflow:hidden;"><div style="width:66%;height:100%;background:var(--green);border-radius:2px;"></div></div></div>
<div style="flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:32px 24px;text-align:center;">
<div style="font-family:var(--font-display);font-size:56px;font-weight:300;color:var(--green-light);margin-bottom:16px;line-height:1;">2</div>
<div style="font-size:16px;line-height:1.75;color:var(--color-text);max-width:260px;">Drizzle with olive oil, season generously with salt and pepper. Roast for 40 minutes until caramelized.</div>
</div>
<div style="padding:16px;text-align:center;font-size:12px;color:var(--color-text-muted);">Tap anywhere for next step →</div>
</div>
</div>
</div>
<div class="prev-col">
<div class="bp-lbl">Desktop · SAME layout, wider text</div>
<div class="desk" style="min-height:480px;flex-direction:column;">
<div style="padding:14px 24px;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--color-border);">
<div style="font-size:13px;color:var(--color-error);font-weight:500;cursor:pointer;">✕ Exit</div>
<div style="font-size:12px;color:var(--color-text-muted);">Step 2 of 3</div>
<div style="width:60px;"></div>
</div>
<div style="padding:0 24px;margin-top:4px;"><div style="height:4px;background:var(--color-subtle);border-radius:2px;overflow:hidden;"><div style="width:66%;height:100%;background:var(--green);border-radius:2px;"></div></div></div>
<div style="flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:48px;text-align:center;cursor:pointer;">
<div style="font-family:var(--font-display);font-size:72px;font-weight:300;color:var(--green-light);margin-bottom:24px;line-height:1;">2</div>
<div style="font-size:16px;line-height:1.75;color:var(--color-text);max-width:400px;">Drizzle with olive oil, season generously with salt and pepper. Roast for 40 minutes until caramelized.</div>
</div>
<div style="padding:20px;text-align:center;font-size:13px;color:var(--color-text-muted);">Tap anywhere for next step →</div>
</div>
</div>
</div>
<div class="agent">
<h4>B4 · Cook mode · KITCHEN CRITICAL</h4>
<pre>/* FULL SCREEN on all breakpoints. NO sidebar. NO tabs. NO nav chrome.
* Body text: EXACTLY 16px, line-height 1.75. NON-NEGOTIABLE.
* Max text width: 260px mobile, 320px tablet, 400px desktop.
* Step number: Fraunces 56px mobile, 72px desktop. Green-light.
* TAP ANYWHERE to advance. Wake lock on enter. Exit = top-left error red.
* Final step: "Done — mark as cooked" → cooking_log INSERT → C1.
* This is an EXCEPTION to nav-spec: no sidebar, no breadcrumbs, no tabs. */</pre>
<table class="at"><thead><tr><th>Element</th><th>Value</th><th>Notes</th></tr></thead><tbody>
<tr class="grp"><td colspan="3">Layout — IDENTICAL all breakpoints</td></tr>
<tr><td>Body text</td><td>16px, line-height 1.75</td><td>NON-NEGOTIABLE</td></tr>
<tr><td>Max text width</td><td>260px mobile / 320px tablet / 400px desktop</td><td>Only difference between breakpoints</td></tr>
<tr><td>Step number</td><td>Fraunces 56px mobile / 72px desktop, weight 300, green-light</td><td>Visible from arm's length</td></tr>
<tr><td>Tap target</td><td>Entire body area</td><td>onclick → next step</td></tr>
<tr><td>Wake lock</td><td>navigator.wakeLock.request('screen')</td><td>On enter, release on exit/done</td></tr>
</tbody></table>
</div>
</div>
<!-- ═══ LLM INSTRUCTIONS ═══ -->
<div class="llm">
<h2>LLM Implementation Instructions — J3 Cook Tonight</h2>
<p>This section provides structured guidance for code-generating LLMs implementing the J3 journey. Follow these rules exactly.</p>
<h3>1. Journey Flow</h3>
<p><strong>C1</strong> (today highlight) → <strong>B2</strong> (recipe detail) → <strong>B4</strong> (cook mode) → <strong>C1</strong></p>
<ul>
<li><strong>Actor:</strong> Planner</li>
<li><strong>Context:</strong> Mobile, hands busy, kitchen environment</li>
<li>The user taps today's meal on the planner (C1), views the recipe (B2), enters cook mode (B4), steps through instructions, marks as cooked, and returns to the planner (C1).</li>
</ul>
<h3>2. Screen B2 — Recipe Detail</h3>
<h3>Mobile layout</h3>
<ul>
<li>Green-tint hero banner at top: back link ("← Planner"), title in Fraunces 24px, pill tags (time, difficulty, servings), and a full-width "Start cooking" button.</li>
<li>Below the hero: stacked ingredients section, then steps section.</li>
</ul>
<h3>Desktop layout</h3>
<ul>
<li>Sidebar (224px) + topbar with breadcrumb ("← Recipes / Recipe Name") and Edit button.</li>
<li>Full-width hero banner: green-tint background, 32px padding. Flex layout with recipe info left (<code>flex:1</code>) and Cook button right (<code>flex-shrink:0</code>).</li>
<li>Below hero: 2-column layout. Ingredients left (<code>flex:1</code>, <code>border-right</code>) + steps right (<code>flex:1</code>). Both panels scroll independently.</li>
</ul>
<h3>Hero variants</h3>
<ul>
<li><strong>With image:</strong> <code>hero_image_url</code> as background, 40% dark overlay, all text rendered in white.</li>
<li><strong>Without image:</strong> green-tint background, dark text (green-deeper for title).</li>
</ul>
<h3>Component details</h3>
<ul>
<li><strong>Ingredients:</strong> Read-only <code>.ir</code> rows (quantity + name). Quantities are scaled to the saved serving count for the planned meal.</li>
<li><strong>Steps:</strong> Numbered circles (28px diameter on desktop, 22px mobile) + step text (14px, line-height 1.6 on desktop; 13px, line-height 1.5 on mobile).</li>
</ul>
<h3>Navigation</h3>
<ul>
<li>"Start cooking" button → navigates to <strong>B4</strong> (cook mode).</li>
<li>"Edit" button → navigates to <strong>B3</strong> (recipe form, prefilled with current recipe data).</li>
</ul>
<h3>3. Screen B4 — Cook Mode (KITCHEN CRITICAL)</h3>
<p>This screen is the single exception to all responsive and navigation patterns in the app.</p>
<h3>Layout rules</h3>
<ul>
<li><strong>IDENTICAL LAYOUT on ALL breakpoints</strong> — this is the ONLY screen that ignores responsive patterns.</li>
<li><strong>NO sidebar, NO tabs, NO navigation chrome on ANY breakpoint.</strong> This is an explicit exception to the nav-spec.</li>
</ul>
<h3>Topbar</h3>
<ul>
<li>Three-column flex: Exit button (left, error red <code>var(--color-error)</code>) + progress indicator (center, "Step N of M") + empty spacer (right).</li>
</ul>
<h3>Progress bar</h3>
<ul>
<li>Height: 4px. Track: <code>var(--color-subtle)</code>. Fill: <code>var(--green)</code>. Border-radius: 2px.</li>
<li>Width percentage: <code>(currentStep / totalSteps) * 100%</code>.</li>
</ul>
<h3>Body</h3>
<ul>
<li>Centered step number: Fraunces, weight 300, <code>var(--green-light)</code>. Size: 56px (mobile) / 72px (desktop).</li>
<li>Step text: <strong>EXACTLY 16px, line-height 1.75 — NON-NEGOTIABLE.</strong> This is a readability requirement for kitchen use with dirty hands.</li>
<li>Max text width: 260px (mobile) / 320px (tablet) / 400px (desktop).</li>
</ul>
<h3>Interaction</h3>
<ul>
<li><strong>TAP ANYWHERE to advance:</strong> The entire body area is the tap target. No fine motor precision required.</li>
<li>On the final step, the tap target label changes to "Done — mark as cooked".</li>
<li>Tapping on the final step triggers: <code>cooking_log INSERT</code> with <code>recipe_id</code> and <code>cooked_date</code> set to today's date, then navigates back to <strong>C1</strong>.</li>
</ul>
<h3>Wake lock</h3>
<ul>
<li>On entering B4: call <code>navigator.wakeLock.request('screen')</code> to prevent the screen from sleeping.</li>
<li>On exiting B4 (via Exit button or "Done"): release the wake lock.</li>
</ul>
<h3>4. Critical Feedback Loop</h3>
<p>The <code>cooking_log</code> table is the data source for the variety/repetition algorithm used in J2 (meal suggestions). Meals cooked more recently are weighted more heavily in the repetition filter, causing the algorithm to deprioritize them in future suggestions. This means J3's "mark as cooked" action directly makes J2's suggestions smarter over time.</p>
<h3>5. Data Operations</h3>
<table>
<thead><tr><th>Screen</th><th>Operation</th><th>Tables</th></tr></thead>
<tbody>
<tr><td>B2</td><td>READ</td><td><code>recipe</code>, <code>recipe_ingredient</code>, <code>ingredient</code>, <code>recipe_step</code></td></tr>
<tr><td>B4</td><td>WRITE</td><td><code>cooking_log</code> INSERT (<code>recipe_id</code>, <code>cooked_date</code>)</td></tr>
</tbody>
</table>
<h3>6. Accessibility</h3>
<ul>
<li>B4's tap target is the entire screen body — accessible with one finger, no fine motor precision needed. This is intentional for kitchen use where hands may be wet or dirty.</li>
<li>The wake lock prevents the screen from sleeping mid-recipe, eliminating the need to unlock the device with messy hands.</li>
<li>Step text at 16px with 1.75 line-height ensures readability at arm's length.</li>
</ul>
</div>
</div>
</body>
</html>