Final design spec for the planner desktop layout overhaul: full-bleed color tiles, CSS 3D card flip for recipe detail, no persistent right panel, inline suggestions on empty days. Includes interactive mockup and written component spec. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
763 lines
39 KiB
HTML
763 lines
39 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Planner — Flip Tiles</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||
<link href="https://fonts.googleapis.com/css2?family=Fraunces:wght@300;400&family=DM+Sans:wght@400;500;600&family=DM+Mono&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root {
|
||
--page: #fafaf7;
|
||
--surface: #f5f4ee;
|
||
--subtle: #edecea;
|
||
--border: #d8d7d0;
|
||
--text: #1c1c18;
|
||
--muted: #6b6a63;
|
||
--gt: #e8f5ea; --gl: #aedcb0; --g: #3d8c4a; --gd: #2e6e39;
|
||
--yt: #fdf6d8; --yl: #f9e08a; --y: #f2c12e; --yx: #8a6800;
|
||
--pt: #eeedfe; --p: #534ab7;
|
||
--ot: #fef0e6; --od: #b46820;
|
||
--err: #dc4c3e;
|
||
--r-sm: 4px; --r-md: 6px; --r-lg: 10px; --r-full: 9999px;
|
||
--sh-card: 0 1px 3px rgba(28,28,24,.06),0 1px 2px rgba(28,28,24,.04);
|
||
--sh-raised: 0 6px 18px rgba(28,28,24,.14),0 2px 6px rgba(28,28,24,.08);
|
||
--fd: 'Fraunces', Georgia, serif;
|
||
--fs: 'DM Sans', system-ui, sans-serif;
|
||
--fm: 'DM Mono', monospace;
|
||
}
|
||
|
||
/* ── Ingredient / cuisine colour palette ──────────────────────── */
|
||
/* Protein-based */
|
||
--col-haehnchen: linear-gradient(160deg,#d4923a 0%,#a85e1a 50%,#7a3d0c 100%);
|
||
--col-rind: linear-gradient(160deg,#c04545 0%,#8b2020 50%,#5a1010 100%);
|
||
--col-fisch: linear-gradient(160deg,#5b9fd4 0%,#2868a0 50%,#10406e 100%);
|
||
--col-tofu: linear-gradient(160deg,#5fa85e 0%,#2e7031 50%,#1a4a1e 100%);
|
||
--col-veg: linear-gradient(160deg,#7bc47b 0%,#3d8c3d 50%,#1e5a1e 100%);
|
||
--col-schwein: linear-gradient(160deg,#d4785a 0%,#a04535 50%,#6e2418 100%);
|
||
--col-lamm: linear-gradient(160deg,#9e6b3a 0%,#6b3f1a 50%,#3e2208 100%);
|
||
--col-ei: linear-gradient(160deg,#d4b832 0%,#a07010 50%,#6e4800 100%);
|
||
--col-linsen: linear-gradient(160deg,#8b6b3a 0%,#5e421a 50%,#3a2408 100%);
|
||
/* Cuisine-based */
|
||
--col-italienisch: linear-gradient(160deg,#c04545 0%,#7a1e1e 50%,#4a0f0f 100%);
|
||
--col-asiatisch: linear-gradient(160deg,#3a6e3a 0%,#1e4a1e 50%,#0e2e0e 100%);
|
||
--col-mexikanisch: linear-gradient(160deg,#d4923a 0%,#8b4e10 50%,#5a2e00 100%);
|
||
--col-indisch: linear-gradient(160deg,#c49010 0%,#8b5e00 50%,#5a3800 100%);
|
||
--col-mediterran: linear-gradient(160deg,#5b9fd4 0%,#1e5a8b 50%,#0a3456 100%);
|
||
|
||
*{box-sizing:border-box;margin:0;padding:0;}
|
||
body{
|
||
font-family:var(--fs);background:#dddcd7;color:var(--text);
|
||
padding:40px 24px 80px;line-height:1.4;
|
||
}
|
||
|
||
.eyebrow{font-family:var(--fs);font-size:11px;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin-bottom:6px;}
|
||
.pg-title{font-family:var(--fd);font-size:34px;font-weight:300;margin-bottom:6px;}
|
||
.pg-sub{font-family:var(--fs);font-size:14px;color:var(--muted);max-width:700px;line-height:1.65;margin-bottom:44px;}
|
||
|
||
.block{margin-bottom:60px;}
|
||
.bl-hd{display:flex;align-items:baseline;gap:10px;margin-bottom:14px;}
|
||
.bl-num{font-family:var(--fm);font-size:11px;background:var(--subtle);color:var(--muted);padding:3px 8px;border-radius:var(--r-sm);}
|
||
.bl-name{font-family:var(--fd);font-size:22px;font-weight:300;}
|
||
.bl-sub{font-family:var(--fs);font-size:12px;color:var(--muted);margin-left:auto;}
|
||
.note{font-family:var(--fs);font-size:12px;color:var(--muted);border-left:3px solid var(--border);padding:10px 14px;margin-top:16px;line-height:1.6;}
|
||
.note strong{color:var(--text);font-weight:500;}
|
||
|
||
/* ── Colour palette swatches ─────────────────────────────────── */
|
||
.swatch-grid{display:flex;flex-wrap:wrap;gap:8px;}
|
||
.swatch{width:88px;border-radius:var(--r-md);overflow:hidden;box-shadow:var(--sh-card);}
|
||
.swatch-color{height:52px;}
|
||
.swatch-label{font-family:var(--fs);font-size:10px;font-weight:500;color:var(--text);padding:5px 7px;background:var(--page);border-top:1px solid var(--border);}
|
||
.swatch-sub{font-family:var(--fs);font-size:9px;color:var(--muted);padding:0 7px 5px;}
|
||
|
||
/* ── Frame ───────────────────────────────────────────────────── */
|
||
.frame{display:flex;flex-direction:column;background:var(--page);border:1px solid var(--border);border-radius:var(--r-lg);overflow:hidden;box-shadow:var(--sh-raised);}
|
||
.tb{display:flex;align-items:center;gap:7px;padding:11px 18px;border-bottom:1px solid var(--border);background:var(--page);flex-shrink:0;}
|
||
.tb-h1{font-family:var(--fd);font-size:17px;font-weight:300;}
|
||
.tb-range{font-family:var(--fs);font-size:11px;color:var(--muted);}
|
||
.tb-arr{width:28px;height:28px;display:flex;align-items:center;justify-content:center;border:1px solid var(--border);border-radius:var(--r-md);font-size:13px;color:var(--muted);}
|
||
.tb-btn{height:28px;padding:0 10px;border:1px solid var(--border);border-radius:var(--r-md);font-family:var(--fs);font-size:11px;font-weight:500;letter-spacing:.04em;color:var(--text);background:var(--page);}
|
||
.tb-ml{margin-left:auto;}
|
||
.tb-pri{background:var(--gd);color:#fff;border:none;}
|
||
.body{display:flex;flex:1;overflow:hidden;}
|
||
|
||
/* Sidebar */
|
||
.sb{width:184px;flex-shrink:0;border-right:1px solid var(--border);background:var(--surface);padding:13px;display:flex;flex-direction:column;gap:13px;}
|
||
.sb-lbl{font-family:var(--fs);font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);margin-bottom:5px;}
|
||
.score-box{background:var(--yt);border:1px solid var(--yl);border-radius:var(--r-md);padding:10px;}
|
||
.sc-big{font-family:var(--fd);font-size:27px;font-weight:300;line-height:1;}
|
||
.sc-den{font-family:var(--fs);font-size:11px;color:var(--muted);}
|
||
.pbar{height:4px;border-radius:var(--r-full);overflow:hidden;margin-top:6px;}
|
||
.pb-y{background:var(--yl);} .pb-t{background:var(--border);}
|
||
.pb-fill{height:100%;border-radius:var(--r-full);}
|
||
.pb-fg-y{background:var(--y);} .pb-fg-g{background:var(--g);}
|
||
.sr{display:flex;align-items:center;gap:6px;margin-top:6px;}
|
||
.sr-l{font-family:var(--fs);font-size:10px;color:var(--muted);width:68px;flex-shrink:0;}
|
||
.sr-b{flex:1;height:3px;border-radius:var(--r-full);background:var(--border);overflow:hidden;}
|
||
.sr-f{height:100%;border-radius:var(--r-full);}
|
||
.sr-v{font-family:var(--fm);font-size:9px;color:var(--muted);width:18px;text-align:right;}
|
||
.w-item{font-family:var(--fs);font-size:10px;color:var(--yx);margin-top:4px;line-height:1.4;}
|
||
.dp{display:flex;gap:2px;margin-top:5px;}
|
||
.dp-s{flex:1;height:4px;border-radius:var(--r-full);}
|
||
.sb-link{font-family:var(--fs);font-size:10px;font-weight:500;color:var(--yx);display:block;margin-top:8px;}
|
||
|
||
/* Main */
|
||
.main{flex:1;overflow-y:auto;padding:12px;}
|
||
.grid7{display:grid;grid-template-columns:repeat(7,1fr);gap:7px;}
|
||
|
||
/* ═══════════════════════════════════════════════
|
||
CARD FLIP SYSTEM
|
||
Each tile is a .scene > .card > .front + .back
|
||
═══════════════════════════════════════════════ */
|
||
.scene{
|
||
border-radius:var(--r-lg);
|
||
/* Perspective for 3D depth */
|
||
perspective:900px;
|
||
cursor:pointer;
|
||
}
|
||
.card{
|
||
position:relative;
|
||
width:100%;height:100%;
|
||
transform-style:preserve-3d;
|
||
transition:transform .45s cubic-bezier(.4,0,.2,1);
|
||
border-radius:var(--r-lg);
|
||
}
|
||
.card.flipped{transform:rotateY(180deg);}
|
||
|
||
/* Both faces */
|
||
.card-front,
|
||
.card-back{
|
||
position:absolute;inset:0;
|
||
border-radius:var(--r-lg);
|
||
overflow:hidden;
|
||
backface-visibility:hidden;
|
||
-webkit-backface-visibility:hidden;
|
||
}
|
||
|
||
/* ── FRONT face: full-bleed image ─── */
|
||
.card-front{
|
||
background-size:cover;
|
||
background-position:center;
|
||
}
|
||
/* Gradient: dark top (header), clear middle, dark bottom (text) */
|
||
.front-overlay{
|
||
position:absolute;inset:0;
|
||
background:
|
||
linear-gradient(to bottom,
|
||
rgba(0,0,0,.38) 0%,
|
||
rgba(0,0,0,0) 28%,
|
||
rgba(0,0,0,0) 48%,
|
||
rgba(0,0,0,.62) 100%
|
||
);
|
||
border-radius:inherit;
|
||
}
|
||
.front-head{
|
||
position:absolute;top:0;left:0;right:0;
|
||
display:flex;align-items:center;justify-content:space-between;
|
||
padding:8px 9px;z-index:2;
|
||
}
|
||
.front-abbr{font-family:var(--fs);font-size:9px;text-transform:uppercase;letter-spacing:.06em;color:rgba(255,255,255,.85);font-weight:500;}
|
||
.front-badge{
|
||
width:20px;height:20px;border-radius:var(--r-full);
|
||
display:flex;align-items:center;justify-content:center;
|
||
font-family:var(--fs);font-size:10px;font-weight:500;
|
||
color:rgba(255,255,255,.9);background:rgba(255,255,255,.22);
|
||
}
|
||
.fb-today{background:var(--y) !important;color:#fff !important;}
|
||
.front-info{
|
||
position:absolute;bottom:0;left:0;right:0;
|
||
padding:8px 9px 10px;z-index:2;
|
||
}
|
||
.front-name{
|
||
font-family:var(--fd);font-size:13px;font-weight:300;
|
||
color:#fff;line-height:1.3;
|
||
text-shadow:0 1px 4px rgba(0,0,0,.5);
|
||
}
|
||
.front-meta{font-family:var(--fs);font-size:10px;color:rgba(255,255,255,.78);margin-top:2px;}
|
||
.front-tags{display:flex;gap:3px;flex-wrap:wrap;margin-top:5px;}
|
||
.ftag{
|
||
font-family:var(--fs);font-size:8px;font-weight:500;
|
||
padding:2px 5px;border-radius:2px;
|
||
background:rgba(255,255,255,.2);color:rgba(255,255,255,.92);
|
||
backdrop-filter:blur(2px);
|
||
}
|
||
|
||
/* State rings via box-shadow (no layout shift) */
|
||
.card-front.st-default{box-shadow:var(--sh-card);}
|
||
.card-front.st-today{box-shadow:0 0 0 2px var(--y), var(--sh-card);}
|
||
.card-front.st-sel{box-shadow:0 0 0 2px var(--g), var(--sh-raised);}
|
||
.card-back.st-today{box-shadow:0 0 0 2px var(--y), var(--sh-raised);}
|
||
.card-back.st-sel{box-shadow:0 0 0 2px var(--g), var(--sh-raised);}
|
||
|
||
/* ── BACK face: recipe detail ─── */
|
||
.card-back{
|
||
transform:rotateY(180deg);
|
||
background:var(--page);
|
||
display:flex;flex-direction:column;
|
||
padding:0;
|
||
}
|
||
|
||
/* Thin colour strip at top of back = recipe's colour accent */
|
||
.back-strip{height:5px;flex-shrink:0;border-radius:var(--r-lg) var(--r-lg) 0 0;}
|
||
|
||
.back-inner{
|
||
display:flex;flex-direction:column;
|
||
flex:1;padding:8px 9px 9px;overflow:hidden;
|
||
}
|
||
.back-head{
|
||
display:flex;align-items:center;justify-content:space-between;
|
||
margin-bottom:6px;flex-shrink:0;
|
||
}
|
||
.back-day{font-family:var(--fs);font-size:9px;font-weight:500;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);}
|
||
.back-close{
|
||
width:18px;height:18px;border-radius:var(--r-full);
|
||
display:flex;align-items:center;justify-content:center;
|
||
background:var(--subtle);font-size:11px;line-height:1;
|
||
color:var(--muted);cursor:pointer;flex-shrink:0;
|
||
border:none;font-family:var(--fs);
|
||
}
|
||
.back-close:hover{background:var(--border);}
|
||
.back-name{
|
||
font-family:var(--fd);font-size:15px;font-weight:300;
|
||
line-height:1.25;color:var(--text);
|
||
margin-bottom:3px;flex-shrink:0;
|
||
}
|
||
.back-meta{font-family:var(--fs);font-size:10px;color:var(--muted);margin-bottom:8px;flex-shrink:0;}
|
||
.back-ings{display:flex;flex-wrap:wrap;gap:3px;margin-bottom:8px;flex-shrink:0;}
|
||
.bing{
|
||
font-family:var(--fs);font-size:9px;
|
||
background:var(--surface);border:1px solid var(--border);
|
||
border-radius:var(--r-full);padding:2px 6px;color:var(--text);
|
||
}
|
||
.bing-s{background:var(--subtle);border-color:var(--subtle);color:var(--muted);}
|
||
.back-actions{display:flex;flex-direction:column;gap:4px;margin-top:auto;}
|
||
.bact{
|
||
display:block;width:100%;padding:6px 8px;
|
||
border-radius:var(--r-md);border:1px solid var(--border);
|
||
background:var(--page);font-family:var(--fs);
|
||
font-size:10px;font-weight:500;letter-spacing:.04em;
|
||
text-align:center;color:var(--text);cursor:pointer;
|
||
}
|
||
.bact-pri{background:var(--gd);color:#fff;border:none;}
|
||
.bact-err{color:var(--err);border-color:var(--err);background:transparent;margin-top:2px;}
|
||
|
||
/* Tile faded (non-selected state) */
|
||
.scene-faded{opacity:.38;pointer-events:none;}
|
||
|
||
/* ── EMPTY TILE (no flip needed) ─── */
|
||
.tile-empty{
|
||
border-radius:var(--r-lg);
|
||
border:1.5px dashed var(--border);
|
||
background:var(--surface);
|
||
display:flex;flex-direction:column;
|
||
overflow:hidden;box-shadow:var(--sh-card);
|
||
cursor:pointer;
|
||
}
|
||
.te-sel{border:2px dashed var(--g);background:rgba(232,245,234,.5);}
|
||
.te-faded{opacity:.22;pointer-events:none;}
|
||
.te-head{display:flex;align-items:center;justify-content:space-between;padding:7px 8px 0;flex-shrink:0;}
|
||
.te-abbr{font-family:var(--fs);font-size:9px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);}
|
||
.te-num{font-family:var(--fs);font-size:10px;font-weight:500;color:var(--muted);}
|
||
.te-cta{display:flex;flex-direction:column;align-items:center;padding:7px 6px 5px;gap:2px;flex-shrink:0;border-bottom:1px solid var(--border);}
|
||
.te-plus{font-size:17px;color:var(--border);}
|
||
.te-label{font-family:var(--fs);font-size:9px;color:var(--muted);}
|
||
.sug-list{display:flex;flex-direction:column;padding:5px 7px 5px;flex:1;overflow:hidden;}
|
||
.sug-hd{font-family:var(--fs);font-size:8px;font-weight:500;letter-spacing:.07em;text-transform:uppercase;color:var(--muted);padding:3px 0 4px;border-bottom:1px solid var(--subtle);margin-bottom:2px;}
|
||
.sug-row{display:flex;align-items:center;gap:4px;padding:5px 0;border-bottom:1px solid var(--subtle);cursor:pointer;}
|
||
.sug-row:last-of-type{border-bottom:none;}
|
||
.sug-name{font-family:var(--fd);font-size:11px;font-weight:300;color:var(--text);flex:1;line-height:1.2;}
|
||
.stag{font-family:var(--fs);font-size:8px;font-weight:500;padding:1px 4px;border-radius:2px;white-space:nowrap;flex-shrink:0;}
|
||
.st-g{background:var(--gt);color:var(--gd);}
|
||
.st-y{background:var(--yt);color:var(--yx);}
|
||
.sug-more{font-family:var(--fs);font-size:9px;font-weight:500;color:var(--yx);text-align:center;padding-top:4px;margin-top:auto;}
|
||
|
||
/* ── Image backgrounds ───────────────────────── */
|
||
.img-haehnchen{background:linear-gradient(160deg,#d4923a 0%,#a85e1a 50%,#7a3d0c 100%);}
|
||
.img-rind {background:linear-gradient(160deg,#c04545 0%,#8b2020 50%,#5a1010 100%);}
|
||
.img-stirfry {background:linear-gradient(160deg,#5fa85e 0%,#2e7031 50%,#1a4a1e 100%);}
|
||
.img-fisch {background:linear-gradient(160deg,#5b9fd4 0%,#2868a0 50%,#10406e 100%);}
|
||
.img-pizza {background:linear-gradient(160deg,#d4a832 0%,#a07010 50%,#6e4a00 100%);}
|
||
|
||
/* Accent strip matches image colours */
|
||
.strip-haehnchen{background:linear-gradient(90deg,#d4923a,#a85e1a);}
|
||
.strip-rind {background:linear-gradient(90deg,#c04545,#8b2020);}
|
||
.strip-stirfry {background:linear-gradient(90deg,#5fa85e,#2e7031);}
|
||
.strip-fisch {background:linear-gradient(90deg,#5b9fd4,#2868a0);}
|
||
.strip-pizza {background:linear-gradient(90deg,#d4a832,#a07010);}
|
||
|
||
/* ── Demo controls ───────────────────────────── */
|
||
.demo-hint{
|
||
font-family:var(--fs);font-size:11px;color:var(--muted);
|
||
text-align:center;margin-bottom:10px;
|
||
}
|
||
.demo-hint span{
|
||
background:var(--subtle);border-radius:var(--r-sm);
|
||
padding:2px 8px;font-weight:500;color:var(--text);
|
||
}
|
||
.specimen-row{display:flex;gap:14px;margin-bottom:8px;flex-wrap:wrap;align-items:flex-start;}
|
||
.specimen-wrap{display:flex;flex-direction:column;align-items:center;gap:6px;}
|
||
.specimen-label{font-family:var(--fs);font-size:10px;font-weight:500;letter-spacing:.07em;text-transform:uppercase;color:var(--muted);text-align:center;}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<p class="eyebrow">Mealplan · Planer · Flip Tiles</p>
|
||
<h1 class="pg-title">Kachel-Flip + Zutaten-Farben</h1>
|
||
<p class="pg-sub">
|
||
Klick auf eine gefüllte Kachel → sie dreht sich um. Auf der Rückseite: Rezeptname, Hauptzutaten, Aktionen.
|
||
Kein Expansion-Panel mehr. Leere Kacheln bleiben unverändert mit Inline-Vorschlägen.
|
||
</p>
|
||
|
||
|
||
<!-- ══════════════════════════════════════════════════════════════ -->
|
||
<!-- SEKTION 1: FARB-PALETTE -->
|
||
<!-- ══════════════════════════════════════════════════════════════ -->
|
||
<div class="block">
|
||
<div class="bl-hd">
|
||
<span class="bl-num">Palette</span>
|
||
<span class="bl-name">Farben nach Hauptzutat / Küchenstil</span>
|
||
<span class="bl-sub">Fallback wenn heroImageUrl fehlt</span>
|
||
</div>
|
||
|
||
<div class="swatch-grid">
|
||
<!-- Proteins -->
|
||
<div class="swatch"><div class="swatch-color img-haehnchen"></div><div class="swatch-label">Hähnchen</div><div class="swatch-sub">Protein</div></div>
|
||
<div class="swatch"><div class="swatch-color img-rind"></div><div class="swatch-label">Rind</div><div class="swatch-sub">Protein</div></div>
|
||
<div class="swatch"><div class="swatch-color img-fisch"></div><div class="swatch-label">Fisch</div><div class="swatch-sub">Protein</div></div>
|
||
<div class="swatch"><div class="swatch-color img-stirfry"></div><div class="swatch-label">Tofu</div><div class="swatch-sub">Protein</div></div>
|
||
<div class="swatch"><div class="swatch-color" style="background:linear-gradient(160deg,#7bc47b 0%,#3d8c3d 50%,#1e5a1e 100%);"></div><div class="swatch-label">vegetarisch</div><div class="swatch-sub">Protein</div></div>
|
||
<div class="swatch"><div class="swatch-color" style="background:linear-gradient(160deg,#d4785a 0%,#a04535 50%,#6e2418 100%);"></div><div class="swatch-label">Schwein</div><div class="swatch-sub">Protein</div></div>
|
||
<div class="swatch"><div class="swatch-color" style="background:linear-gradient(160deg,#9e6b3a 0%,#6b3f1a 50%,#3e2208 100%);"></div><div class="swatch-label">Lamm</div><div class="swatch-sub">Protein</div></div>
|
||
<div class="swatch"><div class="swatch-color" style="background:linear-gradient(160deg,#d4b832 0%,#a07010 50%,#6e4800 100%);"></div><div class="swatch-label">Ei</div><div class="swatch-sub">Protein</div></div>
|
||
<div class="swatch"><div class="swatch-color" style="background:linear-gradient(160deg,#8b6b3a 0%,#5e421a 50%,#3a2408 100%);"></div><div class="swatch-label">Hülsenfrüchte</div><div class="swatch-sub">Protein</div></div>
|
||
<!-- Cuisine overrides -->
|
||
<div class="swatch"><div class="swatch-color img-pizza"></div><div class="swatch-label">Italienisch</div><div class="swatch-sub">Küche</div></div>
|
||
<div class="swatch"><div class="swatch-color" style="background:linear-gradient(160deg,#3a6e3a 0%,#1e4a1e 50%,#0e2e0e 100%);"></div><div class="swatch-label">Asiatisch</div><div class="swatch-sub">Küche</div></div>
|
||
<div class="swatch"><div class="swatch-color" style="background:linear-gradient(160deg,#c49010 0%,#8b5e00 50%,#5a3800 100%);"></div><div class="swatch-label">Indisch</div><div class="swatch-sub">Küche</div></div>
|
||
<div class="swatch"><div class="swatch-color" style="background:linear-gradient(160deg,#c04545 0%,#7a1e1e 50%,#4a0f0f 100%);"></div><div class="swatch-label">Mexikanisch</div><div class="swatch-sub">Küche</div></div>
|
||
<div class="swatch"><div class="swatch-color" style="background:linear-gradient(160deg,#4a90b8 0%,#1e5a8b 50%,#0a3456 100%);"></div><div class="swatch-label">Mediterran</div><div class="swatch-sub">Küche</div></div>
|
||
</div>
|
||
|
||
<div class="note">
|
||
<strong>Priorität:</strong> Wenn <code>heroImageUrl</code> vorhanden → echtes Foto.
|
||
Sonst: Farbe nach erstem Protein-Tag (z.B. <code>tagType=protein</code>, <code>tagName=Hähnchen</code>).
|
||
Wenn kein Protein-Tag → Farbe nach Küchenstil-Tag (<code>tagType=cuisine</code>).
|
||
Fallback auf <code>--color-surface</code> neutral.
|
||
Die Farbwerte werden als CSS-Klassen gemappt: <code>protein-haehnchen</code>, <code>cuisine-asiatisch</code> etc.
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- ══════════════════════════════════════════════════════════════ -->
|
||
<!-- SEKTION 2: INTERACTIVE FLIP DEMO -->
|
||
<!-- ══════════════════════════════════════════════════════════════ -->
|
||
<div class="block">
|
||
<div class="bl-hd">
|
||
<span class="bl-num">Demo</span>
|
||
<span class="bl-name">Flip-Interaktion — zum Klicken</span>
|
||
<span class="bl-sub">Echte CSS-3D-Transition</span>
|
||
</div>
|
||
|
||
<p class="demo-hint">Klicke auf eine Kachel um sie umzudrehen. <span>×</span> auf der Rückseite klappt zurück.</p>
|
||
|
||
<div class="specimen-row">
|
||
|
||
<!-- Tile 1: Hähnchen-Curry (normal) -->
|
||
<div class="specimen-wrap">
|
||
<div class="specimen-label">Standard</div>
|
||
<div class="scene" style="width:150px;height:240px;" onclick="flip(this)">
|
||
<div class="card">
|
||
<div class="card-front img-haehnchen st-default">
|
||
<div class="front-overlay"></div>
|
||
<div class="front-head">
|
||
<span class="front-abbr">Mo</span>
|
||
<span class="front-badge">7</span>
|
||
</div>
|
||
<div class="front-info">
|
||
<div class="front-name">Hähnchen-Curry</div>
|
||
<div class="front-meta">35 Min · mittel</div>
|
||
<div class="front-tags">
|
||
<span class="ftag">Hähnchen</span>
|
||
<span class="ftag">4 Port.</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="card-back st-default">
|
||
<div class="back-strip strip-haehnchen"></div>
|
||
<div class="back-inner">
|
||
<div class="back-head">
|
||
<span class="back-day">Mo · 7. Apr</span>
|
||
<button class="back-close" onclick="unflip(event,this)">×</button>
|
||
</div>
|
||
<div class="back-name">Hähnchen-Curry</div>
|
||
<div class="back-meta">35 Min · mittel · 4 Port.</div>
|
||
<div class="back-ings">
|
||
<span class="bing">Hähnchen</span>
|
||
<span class="bing">Kokosmilch</span>
|
||
<span class="bing">Paprika</span>
|
||
<span class="bing">Spinat</span>
|
||
<span class="bing-s">Curry</span>
|
||
<span class="bing-s">Knoblauch</span>
|
||
</div>
|
||
<div class="back-actions">
|
||
<button class="bact bact-pri">Koch-Modus</button>
|
||
<button class="bact">Rezept ansehen</button>
|
||
<button class="bact">Gericht tauschen</button>
|
||
<button class="bact bact-err">Entfernen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tile 2: Pasta Bolognese (today) -->
|
||
<div class="specimen-wrap">
|
||
<div class="specimen-label">Heute</div>
|
||
<div class="scene" style="width:150px;height:240px;" onclick="flip(this)">
|
||
<div class="card">
|
||
<div class="card-front img-rind st-today">
|
||
<div class="front-overlay"></div>
|
||
<div class="front-head">
|
||
<span class="front-abbr">Di</span>
|
||
<span class="front-badge fb-today">8</span>
|
||
</div>
|
||
<div class="front-info">
|
||
<div class="front-name">Pasta Bolognese</div>
|
||
<div class="front-meta">45 Min · mittel</div>
|
||
<div class="front-tags">
|
||
<span class="ftag" style="background:rgba(242,193,46,.35);">Rind</span>
|
||
<span class="ftag" style="background:rgba(242,193,46,.35);">Heute</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="card-back st-today">
|
||
<div class="back-strip strip-rind"></div>
|
||
<div class="back-inner">
|
||
<div class="back-head">
|
||
<span class="back-day" style="color:var(--yx);">Di · Heute</span>
|
||
<button class="back-close" onclick="unflip(event,this)">×</button>
|
||
</div>
|
||
<div class="back-name">Pasta Bolognese</div>
|
||
<div class="back-meta">45 Min · mittel · 4 Port.</div>
|
||
<div class="back-ings">
|
||
<span class="bing">Rinderhack</span>
|
||
<span class="bing">Pasta</span>
|
||
<span class="bing">Tomaten</span>
|
||
<span class="bing">Zwiebeln</span>
|
||
<span class="bing-s">Olivenöl</span>
|
||
<span class="bing-s">Knoblauch</span>
|
||
</div>
|
||
<div class="back-actions">
|
||
<button class="bact bact-pri">Koch-Modus</button>
|
||
<button class="bact">Rezept ansehen</button>
|
||
<button class="bact">Gericht tauschen</button>
|
||
<button class="bact bact-err">Entfernen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Tile 3: Gemüse-Stir-fry (selected + flipped by default) -->
|
||
<div class="specimen-wrap">
|
||
<div class="specimen-label">Ausgewählt (bereits umgedreht)</div>
|
||
<div class="scene" style="width:150px;height:240px;" onclick="flip(this)">
|
||
<div class="card flipped">
|
||
<div class="card-front img-stirfry st-sel">
|
||
<div class="front-overlay"></div>
|
||
<div class="front-head">
|
||
<span class="front-abbr">Mi</span>
|
||
<span class="front-badge" style="background:var(--g);color:#fff;">9</span>
|
||
</div>
|
||
<div class="front-info">
|
||
<div class="front-name">Gemüse-Stir-fry</div>
|
||
<div class="front-meta">20 Min · einfach</div>
|
||
<div class="front-tags"><span class="ftag" style="background:rgba(61,140,74,.4);">Tofu</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="card-back st-sel">
|
||
<div class="back-strip strip-stirfry"></div>
|
||
<div class="back-inner">
|
||
<div class="back-head">
|
||
<span class="back-day" style="color:var(--gd);">Mi · 9. Apr</span>
|
||
<button class="back-close" onclick="unflip(event,this)">×</button>
|
||
</div>
|
||
<div class="back-name">Gemüse-Stir-fry</div>
|
||
<div class="back-meta">20 Min · einfach · 2 Port.</div>
|
||
<div class="back-ings">
|
||
<span class="bing">Tofu</span>
|
||
<span class="bing">Paprika</span>
|
||
<span class="bing">Brokkoli</span>
|
||
<span class="bing">Karotten</span>
|
||
<span class="bing-s">Sesamöl</span>
|
||
<span class="bing-s">Sojasauce</span>
|
||
</div>
|
||
<div class="back-actions">
|
||
<button class="bact bact-pri">Koch-Modus</button>
|
||
<button class="bact">Rezept ansehen</button>
|
||
<button class="bact">Gericht tauschen</button>
|
||
<button class="bact bact-err">Entfernen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Empty tile with suggestions -->
|
||
<div class="specimen-wrap">
|
||
<div class="specimen-label">Leer — kein Flip</div>
|
||
<div class="tile-empty" style="width:150px;height:240px;">
|
||
<div class="te-head">
|
||
<span class="te-abbr">Sa</span>
|
||
<span class="te-num">12</span>
|
||
</div>
|
||
<div class="te-cta">
|
||
<div class="te-plus">+</div>
|
||
<div class="te-label">Gericht wählen</div>
|
||
</div>
|
||
<div class="sug-list">
|
||
<div class="sug-hd">Vorschläge</div>
|
||
<div class="sug-row"><span class="sug-name">Ramen mit Ei</span><span class="stag st-g">Neues Protein</span></div>
|
||
<div class="sug-row"><span class="sug-name">Shakshuka</span><span class="stag st-g">Kein Overlap</span></div>
|
||
<div class="sug-row"><span class="sug-name">Tacos</span><span class="stag st-y">Aufwand: leicht</span></div>
|
||
<div class="sug-more">Alle Rezepte →</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div class="note">
|
||
<strong>Flip-Mechanik:</strong> CSS <code>transform:rotateY(180deg)</code> auf dem <code>.card</code> wrapper,
|
||
<code>backface-visibility:hidden</code> auf beiden Faces, <code>perspective:900px</code> auf der Scene.
|
||
Transition: <code>.45s cubic-bezier(.4,0,.2,1)</code> (Material-Easing — schnell herein, weich heraus).
|
||
Der <code>×</code> Button auf der Rückseite stoppt den Klick-Event mit <code>stopPropagation()</code>
|
||
und dreht die Karte zurück. Kein zusätzlicher State nötig — die Karte ist selbst das State-Element.
|
||
<br><br>
|
||
<strong>Farbstreifen</strong> oben auf der Rückseite = 5px Gradient, identisch mit der Front-Farbe.
|
||
Gibt visuelle Kontinuität zwischen Vorder- und Rückseite.
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<!-- ══════════════════════════════════════════════════════════════ -->
|
||
<!-- SEKTION 3: VOLLSTÄNDIGE SEITENANSICHT — Mi UMGEDREHT -->
|
||
<!-- ══════════════════════════════════════════════════════════════ -->
|
||
<div class="block">
|
||
<div class="bl-hd">
|
||
<span class="bl-num">Seite</span>
|
||
<span class="bl-name">Vollansicht — Mittwoch umgedreht</span>
|
||
<span class="bl-sub">Kein rechtes Panel. Kacheln bis zum Rand.</span>
|
||
</div>
|
||
|
||
<div class="frame" style="height:560px;">
|
||
<div class="tb">
|
||
<span class="tb-h1">Wochenplaner</span>
|
||
<span class="tb-range">7.–13. Apr</span>
|
||
<div class="tb-arr">‹</div><div class="tb-arr">›</div>
|
||
<button class="tb-btn tb-ml">Heute</button>
|
||
</div>
|
||
|
||
<div class="body">
|
||
<!-- Sidebar -->
|
||
<div class="sb">
|
||
<div class="score-box">
|
||
<div class="sb-lbl">Abwechslungs-Score</div>
|
||
<div style="display:flex;align-items:baseline;gap:4px;"><span class="sc-big">7.8</span><span class="sc-den">/10</span></div>
|
||
<div class="pbar pb-y"><div class="pb-fill pb-fg-y" style="width:78%;"></div></div>
|
||
<div class="sr"><span class="sr-l">Protein</span><div class="sr-b"><div class="sr-f" style="width:80%;background:var(--g);"></div></div><span class="sr-v">8.0</span></div>
|
||
<div class="sr"><span class="sr-l">Zutaten</span><div class="sr-b"><div class="sr-f" style="width:72%;background:var(--y);"></div></div><span class="sr-v">7.2</span></div>
|
||
<div class="sr"><span class="sr-l">Aufwand</span><div class="sr-b"><div class="sr-f" style="width:82%;background:var(--g);"></div></div><span class="sr-v">8.2</span></div>
|
||
<a class="sb-link">Variety-Analyse →</a>
|
||
</div>
|
||
<div>
|
||
<div class="sb-lbl">Überschneidungen</div>
|
||
<div class="w-item">⚠ Hähnchen an Mo + Do</div>
|
||
<div class="w-item">⚠ Tomaten an Di + Do</div>
|
||
</div>
|
||
<div>
|
||
<div class="sb-lbl">Geplant</div>
|
||
<div style="display:flex;align-items:baseline;gap:3px;"><span style="font-family:var(--fd);font-size:20px;font-weight:300;">5</span><span style="font-family:var(--fs);font-size:10px;color:var(--muted);">/ 7 Tage</span></div>
|
||
<div class="dp" style="margin-top:5px;">
|
||
<div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--g);"></div><div class="dp-s" style="background:var(--border);"></div><div class="dp-s" style="background:var(--border);"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- MAIN: grid fills full height, Mi is flipped -->
|
||
<div class="main">
|
||
<div class="grid7" style="height:100%;">
|
||
|
||
<!-- Mo: faded -->
|
||
<div class="scene scene-faded" style="height:100%;">
|
||
<div class="card">
|
||
<div class="card-front img-haehnchen st-default">
|
||
<div class="front-overlay"></div>
|
||
<div class="front-head"><span class="front-abbr">Mo</span><span class="front-badge">7</span></div>
|
||
<div class="front-info"><div class="front-name">Hähnchen-Curry</div><div class="front-meta">35 Min · mittel</div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Di: today, faded -->
|
||
<div class="scene scene-faded" style="height:100%;">
|
||
<div class="card">
|
||
<div class="card-front img-rind st-today">
|
||
<div class="front-overlay"></div>
|
||
<div class="front-head"><span class="front-abbr">Di</span><span class="front-badge fb-today">8</span></div>
|
||
<div class="front-info"><div class="front-name">Pasta Bolognese</div><div class="front-meta">45 Min · mittel</div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Mi: SELECTED + FLIPPED -->
|
||
<div class="scene" style="height:100%;" onclick="flip(this)">
|
||
<div class="card flipped">
|
||
<div class="card-front img-stirfry st-sel">
|
||
<div class="front-overlay"></div>
|
||
<div class="front-head">
|
||
<span class="front-abbr">Mi</span>
|
||
<span class="front-badge" style="background:var(--g);color:#fff;">9</span>
|
||
</div>
|
||
<div class="front-info">
|
||
<div class="front-name">Gemüse-Stir-fry</div>
|
||
<div class="front-meta">20 Min · einfach</div>
|
||
<div class="front-tags"><span class="ftag" style="background:rgba(61,140,74,.4);">Tofu</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="card-back st-sel">
|
||
<div class="back-strip strip-stirfry"></div>
|
||
<div class="back-inner">
|
||
<div class="back-head">
|
||
<span class="back-day" style="color:var(--gd);">Mi · 9. Apr</span>
|
||
<button class="back-close" onclick="unflip(event,this)">×</button>
|
||
</div>
|
||
<div class="back-name">Gemüse-Stir-fry</div>
|
||
<div class="back-meta">20 Min · einfach · 2 Port.</div>
|
||
<div class="back-ings">
|
||
<span class="bing">Tofu</span>
|
||
<span class="bing">Paprika</span>
|
||
<span class="bing">Brokkoli</span>
|
||
<span class="bing">Karotten</span>
|
||
<span class="bing">Ingwer</span>
|
||
<span class="bing-s">Sesamöl</span>
|
||
<span class="bing-s">Sojasauce</span>
|
||
</div>
|
||
<div class="back-actions">
|
||
<button class="bact bact-pri">Koch-Modus</button>
|
||
<button class="bact">Rezept ansehen</button>
|
||
<button class="bact">Gericht tauschen</button>
|
||
<button class="bact bact-err">Entfernen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Do: faded -->
|
||
<div class="scene scene-faded" style="height:100%;">
|
||
<div class="card">
|
||
<div class="card-front img-fisch st-default">
|
||
<div class="front-overlay"></div>
|
||
<div class="front-head"><span class="front-abbr">Do</span><span class="front-badge">10</span></div>
|
||
<div class="front-info"><div class="front-name">Lachs mit Kartoffeln</div><div class="front-meta">30 Min · einfach</div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Fr: faded -->
|
||
<div class="scene scene-faded" style="height:100%;">
|
||
<div class="card">
|
||
<div class="card-front img-pizza st-default">
|
||
<div class="front-overlay"></div>
|
||
<div class="front-head"><span class="front-abbr">Fr</span><span class="front-badge">11</span></div>
|
||
<div class="front-info"><div class="front-name">Pizza Margherita</div><div class="front-meta">50 Min · aufwändig</div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Sa: empty with suggestions -->
|
||
<div class="tile-empty te-faded" style="height:100%;">
|
||
<div class="te-head"><span class="te-abbr">Sa</span><span class="te-num">12</span></div>
|
||
<div class="te-cta"><div class="te-plus">+</div><div class="te-label">Gericht wählen</div></div>
|
||
<div class="sug-list">
|
||
<div class="sug-hd">Vorschläge</div>
|
||
<div class="sug-row"><span class="sug-name">Ramen mit Ei</span><span class="stag st-g">Neues Protein</span></div>
|
||
<div class="sug-row"><span class="sug-name">Shakshuka</span><span class="stag st-g">Kein Overlap</span></div>
|
||
<div class="sug-more">Alle Rezepte →</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- So: empty with suggestions -->
|
||
<div class="tile-empty te-faded" style="height:100%;">
|
||
<div class="te-head"><span class="te-abbr">So</span><span class="te-num">13</span></div>
|
||
<div class="te-cta"><div class="te-plus">+</div><div class="te-label">Gericht wählen</div></div>
|
||
<div class="sug-list">
|
||
<div class="sug-hd">Vorschläge</div>
|
||
<div class="sug-row"><span class="sug-name">Grünes Thai-Curry</span><span class="stag st-g">Neues Protein</span></div>
|
||
<div class="sug-row"><span class="sug-name">Tacos</span><span class="stag st-y">Aufwand: leicht</span></div>
|
||
<div class="sug-more">Alle Rezepte →</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="note">
|
||
<strong>Layout:</strong> Linke Sidebar (Variety-Score) bleibt. Kein rechtes Panel mehr.
|
||
Die Kacheln füllen den gesamten verbleibenden Platz (<code>flex:1</code>) — 7 gleich breite Spalten,
|
||
volle Höhe (<code>height:100%</code> auf Grid und Kacheln). Kein Layout-Shift, kein After-Scroll.
|
||
<br><br>
|
||
<strong>Dimm-Effekt:</strong> Beim Flip werden alle anderen Kacheln auf 38% gedimmt.
|
||
Kein neuer API-Aufruf nötig — reine CSS-Klasse per JS.
|
||
<br><br>
|
||
<strong>„Gericht tauschen":</strong> Öffnet den Rezept-Picker als Slide-in-Drawer von rechts
|
||
(kein persistentes Panel). Drawer schließt sich nach Auswahl oder Abbruch.
|
||
<br><br>
|
||
<strong>Leere Kacheln:</strong> Zeigen Inline-Vorschläge auch im gedimmten Zustand (wenn
|
||
eine andere Kachel geflippt ist). Kein Flip auf leeren Kacheln.
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function flip(scene) {
|
||
const card = scene.querySelector('.card');
|
||
const isFlipped = card.classList.toggle('flipped');
|
||
// Dim all other scenes in the same grid
|
||
const grid = scene.closest('.grid7');
|
||
if (!grid) return;
|
||
grid.querySelectorAll('.scene, .tile-empty').forEach(el => {
|
||
if (el === scene) return;
|
||
if (isFlipped) {
|
||
el.style.opacity = '0.38';
|
||
el.style.pointerEvents = 'none';
|
||
} else {
|
||
el.style.opacity = '';
|
||
el.style.pointerEvents = '';
|
||
}
|
||
});
|
||
}
|
||
|
||
function unflip(event, btn) {
|
||
event.stopPropagation();
|
||
const scene = btn.closest('.scene');
|
||
const card = scene.querySelector('.card');
|
||
card.classList.remove('flipped');
|
||
// Un-dim everything
|
||
const grid = scene.closest('.grid7');
|
||
if (!grid) return;
|
||
grid.querySelectorAll('.scene, .tile-empty').forEach(el => {
|
||
el.style.opacity = '';
|
||
el.style.pointerEvents = '';
|
||
});
|
||
}
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|