Files
pizza-dummy/index.html
Basilosaurusrex 7a0f2778f5 product placement
2026-03-24 09:53:02 +01:00

1006 lines
27 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Pizza</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Outfit:wght@300;500;600&display=swap" rel="stylesheet" />
<style>
:root {
--bg: #1a1510;
--paper: #f4ede4;
--accent: #c45c26;
--muted: #8a7f72;
}
*, *::before, *::after {
box-sizing: border-box;
}
html, body {
margin: 0;
min-height: 100%;
height: 100%;
background: var(--bg);
color: var(--paper);
font-family: "Outfit", system-ui, sans-serif;
}
body.preview-open {
overflow: hidden;
}
.page {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
}
.pizza-row {
flex: 1 1 50%;
min-height: 0;
width: 100%;
display: flex;
flex-direction: row;
align-items: stretch;
border-bottom: 1px solid rgba(244, 237, 228, 0.08);
}
.pizza-row:last-child {
border-bottom: none;
}
.pizza-row--image-right .text-col {
order: 1;
}
.pizza-row--image-right .img-col {
order: 2;
}
.pizza-row--image-left .text-col {
order: 2;
}
.pizza-row--image-left .img-col {
order: 1;
}
.text-col,
.img-col {
flex: 1 1 50%;
min-width: 0;
min-height: 0;
display: flex;
align-items: center;
padding: clamp(1rem, 3vw, 2.5rem);
}
.text-col {
flex-direction: column;
justify-content: center;
align-items: flex-start;
background: linear-gradient(135deg, rgba(26, 21, 16, 0.97) 0%, #231c15 100%);
}
.pizza-row--image-right .text-col {
padding-right: clamp(0.75rem, 2vw, 1.5rem);
}
.pizza-row--image-left .text-col {
padding-left: clamp(0.75rem, 2vw, 1.5rem);
}
.img-col {
position: relative;
background: radial-gradient(ellipse 80% 70% at 50% 50%, #2a2219 0%, var(--bg) 75%);
}
.pizza-row--image-right .img-col {
justify-content: flex-end;
}
.pizza-row--image-left .img-col {
justify-content: flex-start;
}
.img-col--clickable {
cursor: pointer;
}
.img-col--clickable:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 4px;
}
.pizza-frame {
position: relative;
width: min(100%, 55vh);
height: min(100%, 55vh);
max-width: 100%;
max-height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.pizza-frame img {
width: 100%;
height: 100%;
object-fit: contain;
display: block;
animation: pizza-spin 48s linear infinite;
will-change: transform;
filter: drop-shadow(0 12px 28px rgba(0, 0, 0, 0.45));
pointer-events: none;
}
.pizza-frame:hover img {
animation-play-state: paused;
}
@keyframes pizza-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
h1 {
font-family: "Bebas Neue", Impact, sans-serif;
font-size: clamp(2.5rem, 8vw, 5rem);
line-height: 0.95;
letter-spacing: 0.02em;
margin: 0 0 0.5rem;
color: var(--paper);
}
.subtitle {
font-size: clamp(0.85rem, 1.8vw, 1rem);
font-weight: 500;
color: var(--accent);
text-transform: uppercase;
letter-spacing: 0.18em;
margin-bottom: 1rem;
}
.details {
font-weight: 300;
font-size: clamp(0.9rem, 1.6vw, 1.05rem);
line-height: 1.55;
color: var(--muted);
max-width: 28em;
}
.details strong {
color: var(--paper);
font-weight: 500;
}
.price {
margin-top: 1.25rem;
font-size: clamp(1.1rem, 2vw, 1.35rem);
font-weight: 600;
color: var(--paper);
}
/* ——— Preview ——— */
.preview {
position: fixed;
inset: 0;
z-index: 100;
display: none;
flex-direction: column;
background: var(--bg);
padding: clamp(0.75rem, 2vw, 1.5rem);
}
.preview.is-visible {
display: flex;
}
.preview__grid {
flex: 1;
min-height: 0;
display: grid;
grid-template-columns: minmax(9rem, 0.85fr) minmax(0, 3.2fr) minmax(9rem, 0.85fr);
grid-template-rows: 1fr auto;
grid-template-areas:
"left center right"
"left bottom bottom";
gap: clamp(0.5rem, 2vw, 1.25rem);
align-items: start;
}
@media (max-width: 900px) {
.preview__grid {
grid-template-columns: 1fr;
grid-template-rows: auto auto 1fr auto;
grid-template-areas:
"left"
"center"
"right"
"bottom";
}
.preview-left {
padding-top: 2.5rem;
}
}
.preview-left {
grid-area: left;
padding-right: 0.5rem;
}
.preview-center {
grid-area: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 0;
position: relative;
}
.preview-right {
grid-area: right;
justify-self: end;
text-align: right;
width: 100%;
max-width: 16rem;
}
.preview-bottom {
grid-area: bottom;
justify-self: end;
align-self: end;
display: flex;
align-items: center;
gap: 0.75rem;
flex-wrap: wrap;
justify-content: flex-end;
padding-top: 0.5rem;
}
.preview__back {
position: absolute;
top: clamp(0.5rem, 2vw, 1rem);
left: clamp(0.5rem, 2vw, 1rem);
z-index: 2;
background: rgba(26, 21, 16, 0.85);
border: 1px solid rgba(244, 237, 228, 0.2);
color: var(--paper);
font-family: inherit;
font-size: 0.9rem;
padding: 0.45rem 0.85rem;
border-radius: 6px;
cursor: pointer;
}
.preview__back:hover {
border-color: var(--accent);
color: var(--accent);
}
.preview-name {
font-family: "Bebas Neue", Impact, sans-serif;
font-size: clamp(2rem, 5vw, 3.5rem);
line-height: 1;
margin: 0 0 1rem;
color: var(--paper);
}
.preview-label {
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--accent);
margin-bottom: 0.5rem;
}
.ingredient-list {
list-style: none;
margin: 0;
padding: 0;
}
.ingredient-list li {
font-size: clamp(0.9rem, 1.4vw, 1rem);
font-weight: 300;
color: var(--muted);
padding: 0.35rem 0;
border-bottom: 1px solid rgba(244, 237, 228, 0.08);
}
.ingredient-list li:last-child {
border-bottom: none;
}
.macro-list {
list-style: none;
margin: 0;
padding: 0;
}
.macro-list li {
font-size: clamp(0.85rem, 1.3vw, 0.95rem);
padding: 0.4rem 0;
color: var(--muted);
border-bottom: 1px solid rgba(244, 237, 228, 0.08);
}
.macro-list li strong {
display: block;
color: var(--paper);
font-weight: 500;
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.08em;
margin-bottom: 0.15rem;
}
.carousel-wrap {
position: relative;
width: 100%;
max-width: min(92vmin, 760px);
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.carousel-stage {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
.carousel-layer {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
will-change: transform;
}
.carousel-layer img {
width: 100%;
height: 100%;
object-fit: contain;
filter: drop-shadow(0 16px 40px rgba(0, 0, 0, 0.5));
}
.carousel-btn {
position: fixed;
top: 50%;
transform: translateY(-50%);
width: 48px;
height: 48px;
border-radius: 50%;
border: 1px solid rgba(244, 237, 228, 0.25);
background: rgba(26, 21, 16, 0.85);
color: var(--paper);
font-size: 1.35rem;
line-height: 1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
z-index: 110;
}
.carousel-btn:hover {
border-color: var(--accent);
color: var(--accent);
}
.carousel-btn--prev {
left: env(safe-area-inset-left, 0);
right: auto;
}
.carousel-btn--next {
right: env(safe-area-inset-right, 0);
left: auto;
}
.preview-timer {
width: 100%;
max-width: min(92vmin, 760px);
margin-top: 0.75rem;
}
.preview-timer[hidden] {
display: none !important;
}
.preview-timer__label {
font-size: 0.72rem;
letter-spacing: 0.06em;
text-transform: uppercase;
color: var(--muted);
margin-bottom: 0.4rem;
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 0.5rem;
}
.preview-timer__sec {
font-variant-numeric: tabular-nums;
color: var(--paper);
font-weight: 500;
}
.preview-timer__track {
height: 8px;
border-radius: 999px;
background: rgba(244, 237, 228, 0.1);
overflow: hidden;
border: 1px solid rgba(244, 237, 228, 0.12);
}
.preview-timer__fill {
height: 100%;
width: 0%;
border-radius: inherit;
background: linear-gradient(90deg, #8b3d18, var(--accent));
box-shadow: 0 0 12px rgba(196, 92, 38, 0.35);
}
.cart-combo {
display: inline-flex;
align-items: stretch;
border: 1px solid rgba(244, 237, 228, 0.22);
border-radius: 10px;
overflow: hidden;
background: rgba(35, 28, 21, 0.85);
}
.cart-combo__qty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0.25rem 0.35rem;
border-right: 1px solid rgba(244, 237, 228, 0.15);
min-width: 3.25rem;
}
.qty-arrow {
width: 100%;
border: none;
background: transparent;
color: var(--paper);
font-size: 0.7rem;
line-height: 1;
padding: 0.2rem 0.5rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.qty-arrow:hover:not(:disabled) {
color: var(--accent);
}
.qty-arrow:disabled {
opacity: 0.35;
cursor: not-allowed;
}
.qty-value {
font-weight: 600;
font-size: 1.15rem;
line-height: 1.2;
padding: 0.15rem 0;
min-height: 1.5rem;
display: flex;
align-items: center;
justify-content: center;
}
.btn-cart {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.65rem 1.15rem;
border: none;
border-radius: 0;
background: var(--accent);
color: var(--bg);
font-family: inherit;
font-weight: 600;
font-size: 0.95rem;
cursor: pointer;
}
.btn-cart:hover {
filter: brightness(1.08);
}
.btn-cart svg {
width: 1.1em;
height: 1.1em;
}
.preview-hint {
font-size: 0.75rem;
color: var(--muted);
margin-top: 0.75rem;
text-align: center;
}
</style>
</head>
<body>
<main class="page" id="home">
<section class="pizza-row pizza-row--image-right" aria-label="Pizza Margherita">
<div class="text-col">
<p class="subtitle">Klassiker</p>
<h1>Margherita</h1>
<p class="details">
<strong>Tomate, Mozzarella, Basilikum.</strong> Unser Teig über Nacht, Ofen aus Stein.
Sanft, säuerlich, klar — wie Neapel, nur auf deinem Bildschirm.
</p>
<p class="price">ab 9,50 €</p>
</div>
<div
class="img-col img-col--clickable"
role="button"
tabindex="0"
data-pizza-index="0"
aria-label="Margherita Vorschau öffnen"
>
<div class="pizza-frame">
<img src="magarita.png" alt="" width="800" height="800" />
</div>
</div>
</section>
<section class="pizza-row pizza-row--image-left" aria-label="Pizza Salami">
<div
class="img-col img-col--clickable"
role="button"
tabindex="0"
data-pizza-index="1"
aria-label="Salami Vorschau öffnen"
>
<div class="pizza-frame">
<img src="salami.png" alt="" width="800" height="800" />
</div>
</div>
<div class="text-col">
<p class="subtitle">Beliebt</p>
<h1>Salami</h1>
<p class="details">
<strong>Tomate, Mozzarella, luftgetrocknete Salami.</strong> Würzig, saftig, mit leichtem
Paprika-Touch. Für alle, die es etwas kräftiger mögen.
</p>
<p class="price">ab 11,00 €</p>
</div>
</section>
</main>
<div
class="preview"
id="preview"
role="dialog"
aria-modal="true"
aria-labelledby="preview-title"
hidden
>
<button type="button" class="preview__back" id="preview-close">← Zurück</button>
<div class="preview__grid">
<div class="preview-left">
<p class="preview-label">Pizza</p>
<h2 class="preview-name" id="preview-title">Margherita</h2>
<p class="preview-label">Zutaten</p>
<ul class="ingredient-list" id="preview-ingredients"></ul>
</div>
<div class="preview-center">
<div class="carousel-wrap">
<button type="button" class="carousel-btn carousel-btn--prev" id="carousel-prev" aria-label="Vorheriges Bild"></button>
<div class="carousel-stage" id="carousel-stage">
<div class="carousel-layer" id="carousel-layer-a">
<img src="" alt="" width="800" height="800" />
</div>
<div class="carousel-layer" id="carousel-layer-b">
<img src="" alt="" width="800" height="800" />
</div>
</div>
<button type="button" class="carousel-btn carousel-btn--next" id="carousel-next" aria-label="Nächstes Bild"></button>
</div>
<div
class="preview-timer"
id="preview-timer"
role="timer"
aria-label="Zeit bis zum nächsten Bildwechsel"
hidden
>
<div class="preview-timer__label">
<span>Nächster Wechsel</span>
<span class="preview-timer__sec" id="preview-timer-sec" aria-hidden="true">5 s</span>
</div>
<div class="preview-timer__track">
<div class="preview-timer__fill" id="preview-timer-fill"></div>
</div>
</div>
<p class="preview-hint">Pfeile: andere Pizza · Zurück: Übersicht</p>
</div>
<div class="preview-right">
<p class="preview-label">Nährwerte (pro Pizza)</p>
<ul class="macro-list" id="preview-macros"></ul>
</div>
<div class="preview-bottom">
<div class="cart-combo" role="group" aria-label="Menge und Warenkorb">
<div class="cart-combo__qty">
<button type="button" class="qty-arrow" id="qty-up" aria-label="Menge erhöhen"></button>
<span class="qty-value" id="qty-num">1</span>
<button type="button" class="qty-arrow" id="qty-down" aria-label="Menge verringern"></button>
</div>
<button type="button" class="btn-cart" id="btn-add-cart">
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49A1.003 1.003 0 0 0 20 4H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"/>
</svg>
In den Warenkorb
</button>
</div>
</div>
</div>
</div>
<script>
(function () {
const IMAGE_SWAP_MS = 5000;
const PREVIEW_SLIDE_MS = 650;
const pizzas = [
{
name: "Margherita",
image: "magarita.png",
imageCut: "magaritta angeschnitten.png",
ingredients: [
"Tomatensauce San Marzano",
"Fior di Latte Mozzarella",
"Frisches Basilikum",
"Olivenöl extra vergine",
"Hefeteig 48h",
],
macros: [
{ label: "Energie", value: "724 kcal" },
{ label: "Fett", value: "26 g" },
{ label: "davon gesättigt", value: "11 g" },
{ label: "Kohlenhydrate", value: "84 g" },
{ label: "Eiweiß", value: "28 g" },
{ label: "Salz", value: "2,1 g" },
],
},
{
name: "Salami",
image: "salami.png",
imageCut: "salami angeschnitten.png",
ingredients: [
"Tomatensauce",
"Mozzarella",
"Luftgetrocknete Salami",
"Oregano",
"Olivenöl",
"Hefeteig 48h",
],
macros: [
{ label: "Energie", value: "812 kcal" },
{ label: "Fett", value: "34 g" },
{ label: "davon gesättigt", value: "14 g" },
{ label: "Kohlenhydrate", value: "82 g" },
{ label: "Eiweiß", value: "32 g" },
{ label: "Salz", value: "2,8 g" },
],
},
];
let currentIndex = 0;
let quantity = 1;
let previewImageTimer = null;
let previewSwapGen = 0;
let previewPhaseFull = true;
let previewNextFromBottom = true;
let previewTimerRaf = null;
function encodeAssetPath(path) {
return path.split("/").map(encodeURIComponent).join("/");
}
function clearPreviewImageTimer() {
if (previewImageTimer !== null) {
clearTimeout(previewImageTimer);
previewImageTimer = null;
}
stopTimerSlider();
}
function stopTimerSlider() {
if (previewTimerRaf !== null) {
cancelAnimationFrame(previewTimerRaf);
previewTimerRaf = null;
}
var fill = document.getElementById("preview-timer-fill");
if (fill) fill.style.width = "0%";
}
function startTimerSlider(expectedGen) {
stopTimerSlider();
var fill = document.getElementById("preview-timer-fill");
var secEl = document.getElementById("preview-timer-sec");
if (!fill) return;
var start = performance.now();
function tick(now) {
if (expectedGen !== previewSwapGen) return;
var elapsed = now - start;
var p = Math.min(100, (elapsed / IMAGE_SWAP_MS) * 100);
fill.style.width = p + "%";
if (secEl) {
var left = Math.max(0, IMAGE_SWAP_MS - elapsed);
var s = Math.ceil(left / 1000);
if (s <= 0) s = 0;
secEl.textContent = s + " s";
}
if (p >= 100) {
previewTimerRaf = null;
return;
}
previewTimerRaf = requestAnimationFrame(tick);
}
previewTimerRaf = requestAnimationFrame(tick);
}
const preview = document.getElementById("preview");
const previewTimerEl = document.getElementById("preview-timer");
const previewTitle = document.getElementById("preview-title");
const previewIngredients = document.getElementById("preview-ingredients");
const previewMacros = document.getElementById("preview-macros");
const carouselLayerA = document.getElementById("carousel-layer-a");
const carouselLayerB = document.getElementById("carousel-layer-b");
const carouselImgA = carouselLayerA.querySelector("img");
const carouselImgB = carouselLayerB.querySelector("img");
const btnPrev = document.getElementById("carousel-prev");
const btnNext = document.getElementById("carousel-next");
const btnClose = document.getElementById("preview-close");
const qtyNum = document.getElementById("qty-num");
const qtyUp = document.getElementById("qty-up");
const qtyDown = document.getElementById("qty-down");
const btnAddCart = document.getElementById("btn-add-cart");
function resetPreviewLayers() {
[carouselLayerA, carouselLayerB].forEach(function (layer) {
layer.style.transition = "none";
layer.style.transform = "";
layer.style.zIndex = "";
});
}
function setupPreviewLoop() {
clearPreviewImageTimer();
previewSwapGen++;
const gen = previewSwapGen;
const p = pizzas[currentIndex];
previewPhaseFull = true;
previewNextFromBottom = true;
resetPreviewLayers();
carouselImgA.alt = "Pizza " + p.name;
carouselImgB.alt = "Pizza " + p.name;
if (!p.imageCut) {
if (previewTimerEl) previewTimerEl.hidden = true;
carouselImgA.src = encodeAssetPath(p.image);
carouselLayerA.style.transform = "translateY(0)";
carouselLayerA.style.zIndex = "2";
carouselImgB.removeAttribute("src");
carouselLayerB.style.transform = "translateY(110%)";
carouselLayerB.style.zIndex = "1";
return;
}
if (previewTimerEl) previewTimerEl.hidden = false;
carouselImgA.src = encodeAssetPath(p.image);
carouselImgB.src = encodeAssetPath(p.imageCut);
carouselLayerA.style.transform = "translateY(0)";
carouselLayerA.style.zIndex = "2";
carouselLayerB.style.transform = "translateY(110%)";
carouselLayerB.style.zIndex = "1";
previewImageTimer = setTimeout(function () {
runPreviewImageSwap(gen);
}, IMAGE_SWAP_MS);
startTimerSlider(gen);
}
function runPreviewImageSwap(expectedGen) {
if (expectedGen !== previewSwapGen) return;
const p = pizzas[currentIndex];
if (!p || !p.imageCut) return;
stopTimerSlider();
var outgoing =
carouselLayerA.style.zIndex === "2" ? carouselLayerA : carouselLayerB;
var incoming =
outgoing === carouselLayerA ? carouselLayerB : carouselLayerA;
var outgoingImg = outgoing.querySelector("img");
var incomingImg = incoming.querySelector("img");
var nextFull = !previewPhaseFull;
var nextPath = nextFull ? p.image : p.imageCut;
incomingImg.src = encodeAssetPath(nextPath);
incomingImg.alt = "Pizza " + p.name;
var fromBottom = previewNextFromBottom;
previewNextFromBottom = !previewNextFromBottom;
incoming.style.transition = "none";
outgoing.style.transition = "none";
incoming.style.transform = fromBottom
? "translateY(110%)"
: "translateY(-110%)";
outgoing.style.transform = "translateY(0)";
incoming.style.zIndex = "2";
outgoing.style.zIndex = "1";
outgoing.offsetHeight;
var ease = "cubic-bezier(0.4, 0, 0.2, 1)";
incoming.style.transition =
"transform " + PREVIEW_SLIDE_MS / 1000 + "s " + ease;
outgoing.style.transition =
"transform " + PREVIEW_SLIDE_MS / 1000 + "s " + ease;
function onEnd(ev) {
if (ev.propertyName !== "transform") return;
if (expectedGen !== previewSwapGen) return;
incoming.removeEventListener("transitionend", onEnd);
previewPhaseFull = nextFull;
outgoing.style.transition = "none";
outgoing.style.transform = "translateY(110%)";
outgoing.style.zIndex = "1";
incoming.style.zIndex = "2";
previewImageTimer = setTimeout(function () {
runPreviewImageSwap(expectedGen);
}, IMAGE_SWAP_MS);
startTimerSlider(expectedGen);
}
incoming.addEventListener("transitionend", onEnd);
requestAnimationFrame(function () {
requestAnimationFrame(function () {
if (expectedGen !== previewSwapGen) return;
incoming.style.transform = "translateY(0)";
outgoing.style.transform = "translateY(110%)";
});
});
}
function renderPizza() {
const p = pizzas[currentIndex];
previewTitle.textContent = p.name;
previewIngredients.innerHTML = p.ingredients
.map(function (ing) {
return "<li>" + ing + "</li>";
})
.join("");
previewMacros.innerHTML = p.macros
.map(function (m) {
return "<li><strong>" + m.label + "</strong>" + m.value + "</li>";
})
.join("");
setupPreviewLoop();
}
function openPreview(index) {
currentIndex = Math.max(0, Math.min(pizzas.length - 1, index));
quantity = 1;
qtyNum.textContent = String(quantity);
updateQtyButtons();
renderPizza();
preview.hidden = false;
preview.classList.add("is-visible");
document.body.classList.add("preview-open");
btnClose.focus();
}
function closePreview() {
clearPreviewImageTimer();
if (previewTimerEl) previewTimerEl.hidden = true;
previewSwapGen++;
resetPreviewLayers();
preview.classList.remove("is-visible");
preview.hidden = true;
document.body.classList.remove("preview-open");
}
function updateQtyButtons() {
qtyDown.disabled = quantity <= 1;
qtyUp.disabled = quantity >= 99;
}
document.querySelectorAll(".img-col--clickable").forEach(function (el) {
el.addEventListener("click", function () {
const idx = parseInt(el.getAttribute("data-pizza-index"), 10);
openPreview(idx);
});
el.addEventListener("keydown", function (e) {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
const idx = parseInt(el.getAttribute("data-pizza-index"), 10);
openPreview(idx);
}
});
});
btnPrev.addEventListener("click", function () {
currentIndex = (currentIndex - 1 + pizzas.length) % pizzas.length;
renderPizza();
});
btnNext.addEventListener("click", function () {
currentIndex = (currentIndex + 1) % pizzas.length;
renderPizza();
});
btnClose.addEventListener("click", closePreview);
document.addEventListener("keydown", function (e) {
if (!preview.classList.contains("is-visible")) return;
if (e.key === "Escape") closePreview();
});
qtyUp.addEventListener("click", function () {
if (quantity < 99) {
quantity++;
qtyNum.textContent = String(quantity);
updateQtyButtons();
}
});
qtyDown.addEventListener("click", function () {
if (quantity > 1) {
quantity--;
qtyNum.textContent = String(quantity);
updateQtyButtons();
}
});
btnAddCart.addEventListener("click", function () {
const p = pizzas[currentIndex];
alert(
p.name +
" × " +
quantity +
" — (Demo: hier käme der echte Warenkorb.)"
);
});
})();
</script>
</body>
</html>