From 4baaf4bc43c49e9dac19c65a09f57fc716b016a9 Mon Sep 17 00:00:00 2001 From: Jacek Pyziak Date: Mon, 16 Feb 2026 23:05:31 +0100 Subject: [PATCH] first commit --- .vscode/ftp-kr.json | 17 ++ .vscode/sftp.json | 12 + index.html | 197 +++++++++++++ script.js | 490 +++++++++++++++++++++++++++++++ styles.css | 680 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1396 insertions(+) create mode 100644 .vscode/ftp-kr.json create mode 100644 .vscode/sftp.json create mode 100644 index.html create mode 100644 script.js create mode 100644 styles.css diff --git a/.vscode/ftp-kr.json b/.vscode/ftp-kr.json new file mode 100644 index 0000000..6a34263 --- /dev/null +++ b/.vscode/ftp-kr.json @@ -0,0 +1,17 @@ +{ + "host": "host117523.hostido.net.pl", + "username": "www@laitica.pagedev.pl", + "password": "5M5dnyGsBxHubZXD5bkt", + "remotePath": "/public_html", + "protocol": "ftp", + "port": 21, + "fileNameEncoding": "utf8", + "autoUpload": true, + "autoDelete": false, + "autoDownload": false, + "ignoreRemoteModification": true, + "ignore": [ + ".git", + "/.vscode" + ] +} \ No newline at end of file diff --git a/.vscode/sftp.json b/.vscode/sftp.json new file mode 100644 index 0000000..6784d55 --- /dev/null +++ b/.vscode/sftp.json @@ -0,0 +1,12 @@ +{ + "name": "host117523.hostido.net.pl", + "host": "host117523.hostido.net.pl", + "protocol": "ftp", + "port": 21, + "username": "www@laitica.pagedev.pl", + "password": "5M5dnyGsBxHubZXD5bkt", + "remotePath": "/public_html", + "uploadOnSave": false, + "useTempFile": false, + "openSsh": false +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..2af7ae7 --- /dev/null +++ b/index.html @@ -0,0 +1,197 @@ + + + + + + Laitica | Makieta konfiguratora zestawów szynowych + + + + + + +
+
+ +
+
+
LAITICA
+

Konfigurator zestawów szynowych

+

Makieta UX/UI inspirowana konfiguratorami rynkowymi. Dane produktowe i ceny są przykładowe.

+
+ +
+
+ + +
+
+

Wybierz system szynowy

+

Dobierz rodzaj zasilania i poziom zaawansowania instalacji.

+
+ + + +
+
+ +
+

Ustal kształt i wymiary

+

Wybierz geometrię układu i orientacyjną długość szyn.

+ +
+ + + + +
+ +
+ + +
+
+ +
+

Dopasuj wykończenie

+

Kolor szyny i barwa światła pod charakter wnętrza.

+ +
+
+

Kolor szyny

+
+ + + +
+
+ +
+

Temperatura barwowa

+
+ + + +
+
+
+
+ +
+

Wybierz oprawy

+

Przykładowa baza opraw wygenerowana losowo dla makiety.

+
+
+ +
+

Dodatki i akcesoria

+

Zaznacz elementy dodatkowe do instalacji i montażu.

+
+
+ +
+

Podsumowanie konfiguracji

+

Końcowy podgląd zestawu i orientacyjna wycena.

+
+
+
+ +
+ + +
+
+ + +
+
+ +
+ + + diff --git a/script.js b/script.js new file mode 100644 index 0000000..ce9a20c --- /dev/null +++ b/script.js @@ -0,0 +1,490 @@ +const stepCount = 6; + +const catalogs = { + systems: { + mono_230: { name: "System 1-fazowy 230V", base: 159, meter: 89 }, + tri_230: { name: "System 3-fazowy 230V", base: 249, meter: 129 }, + magnetic_48: { name: "System magnetyczny 48V", base: 399, meter: 179 } + }, + layouts: { + line: { name: "Układ liniowy", surcharge: 0 }, + l_shape: { name: "Układ L", surcharge: 59 }, + u_shape: { name: "Układ U", surcharge: 99 }, + rectangle: { name: "Układ prostokątny", surcharge: 149 } + }, + colors: { + black: { name: "Czarny mat", surcharge: 0, line: "#252627" }, + white: { name: "Biały mat", surcharge: 0, line: "#f7f6f8" }, + champagne: { name: "Champagne", surcharge: 40, line: "#d7bd8b" } + }, + temperatures: { + "3000": "3000K ciepła", + "4000": "4000K neutralna", + cct: "CCT regulowana" + } +}; + +const state = { + step: 1, + system: null, + layout: null, + trackLength: 4, + roomHeight: 2.8, + trackColor: null, + temperature: null, + fixtures: {}, + accessories: new Set() +}; + +const fixtureGrid = document.getElementById("fixtureGrid"); +const accessoryList = document.getElementById("accessoryList"); +const summaryList = document.getElementById("summaryList"); +const summaryTotal = document.getElementById("summaryTotal"); +const finalSummary = document.getElementById("finalSummary"); +const previewCanvas = document.getElementById("previewCanvas"); +const trackLengthInput = document.getElementById("trackLength"); +const trackLengthOut = document.getElementById("trackLengthOut"); +const roomHeightInput = document.getElementById("roomHeight"); +const roomHeightOut = document.getElementById("roomHeightOut"); +const prevBtn = document.getElementById("prevBtn"); +const nextBtn = document.getElementById("nextBtn"); +const toast = document.getElementById("toast"); + +const fixtures = buildFixtures(); +const accessories = buildAccessories(); + +init(); + +function init() { + renderFixtures(); + renderAccessories(); + bindBaseEvents(); + syncInputs(); + updateUI(); +} + +function buildFixtures() { + const names = [ + "Reflektor Punto", + "Spot Slim Tube", + "Lampa liniowa Aero", + "Reflektor Move Pro", + "Tubus Mono Flex", + "Panel Linear Edge", + "Oprawa Twist Mini" + ]; + + return names.slice(0, 6).map((name, i) => ({ + id: `fx_${i + 1}`, + code: `LT-FX-${1200 + i}`, + name, + price: randomInt(85, 279) + })); +} + +function buildAccessories() { + const names = [ + "Zasilacz końcowy", + "Łącznik prosty", + "Łącznik narożny L", + "Maskownica zasilania", + "Pilot CCT", + "Zawiesie sufitowe 1 m" + ]; + + return names.map((name, i) => ({ + id: `acc_${i + 1}`, + name, + price: randomInt(24, 119) + })); +} + +function bindBaseEvents() { + document.addEventListener("change", (event) => { + const target = event.target; + + if (target.name === "system") { + state.system = target.value; + } + + if (target.name === "layout") { + state.layout = target.value; + } + + if (target.name === "trackColor") { + state.trackColor = target.value; + } + + if (target.name === "temperature") { + state.temperature = target.value; + } + + if (target.matches("[data-accessory]")) { + if (target.checked) { + state.accessories.add(target.value); + } else { + state.accessories.delete(target.value); + } + } + + updateUI(); + }); + + fixtureGrid.addEventListener("click", (event) => { + const button = event.target.closest("button[data-fixture-id]"); + if (!button) { + return; + } + + const id = button.dataset.fixtureId; + const action = button.dataset.action; + const currentQty = state.fixtures[id] || 0; + const nextQty = action === "inc" ? currentQty + 1 : Math.max(0, currentQty - 1); + + state.fixtures[id] = nextQty; + updateUI(); + }); + + trackLengthInput.addEventListener("input", () => { + state.trackLength = Number(trackLengthInput.value); + syncInputs(); + updateUI(); + }); + + roomHeightInput.addEventListener("input", () => { + const clamped = Math.min(4.5, Math.max(2.2, Number(roomHeightInput.value || 2.8))); + state.roomHeight = Number(clamped.toFixed(1)); + syncInputs(); + }); + + prevBtn.addEventListener("click", () => { + if (state.step > 1) { + state.step -= 1; + updateUI(); + } + }); + + nextBtn.addEventListener("click", () => { + if (state.step < stepCount) { + const valid = validateCurrentStep(); + if (!valid.ok) { + showToast(valid.message); + return; + } + + state.step += 1; + updateUI(); + return; + } + + showToast("Makieta: zestaw został przykładowo dodany do koszyka."); + }); + + document.querySelectorAll("[data-goto-step]").forEach((button) => { + button.addEventListener("click", () => { + const goto = Number(button.dataset.gotoStep); + if (goto <= state.step || goto === state.step + 1) { + if (goto > state.step) { + const valid = validateCurrentStep(); + if (!valid.ok) { + showToast(valid.message); + return; + } + } + state.step = goto; + updateUI(); + } + }); + }); +} + +function renderFixtures() { + fixtureGrid.innerHTML = fixtures + .map( + (fixture) => ` +
+
${fixture.code}
+
${fixture.name}
+
+
${formatPLN(fixture.price)}
+
+ + ${state.fixtures[fixture.id] || 0} + +
+
+
+ ` + ) + .join(""); +} + +function renderAccessories() { + accessoryList.innerHTML = accessories + .map( + (item) => ` +
+ + ${formatPLN(item.price)} +
+ ` + ) + .join(""); +} + +function updateUI() { + updateStepPanels(); + updateStepButtons(); + updateActions(); + renderFixtures(); + refreshAccessoryChecks(); + renderSummary(); + renderFinalSummary(); + renderPreview(); +} + +function updateStepPanels() { + document.querySelectorAll(".step-panel").forEach((panel) => { + panel.classList.toggle("is-active", Number(panel.dataset.step) === state.step); + }); +} + +function updateStepButtons() { + document.querySelectorAll(".step-item").forEach((button) => { + const step = Number(button.dataset.gotoStep); + button.classList.toggle("is-active", step === state.step); + button.classList.toggle("is-done", step < state.step); + }); +} + +function updateActions() { + prevBtn.disabled = state.step === 1; + nextBtn.textContent = state.step === stepCount ? "Dodaj do koszyka" : "Dalej"; +} + +function renderSummary() { + const breakdown = getBreakdown(); + summaryList.innerHTML = breakdown.items + .map((item) => `
  • ${item.label}${formatPLN(item.value)}
  • `) + .join(""); + summaryTotal.textContent = formatPLN(breakdown.total); +} + +function renderFinalSummary() { + const breakdown = getBreakdown(); + finalSummary.innerHTML = ` + + `; +} + +function refreshAccessoryChecks() { + document.querySelectorAll("[data-accessory]").forEach((input) => { + input.checked = state.accessories.has(input.value); + }); +} + +function getBreakdown() { + const items = []; + let total = 0; + + if (state.system) { + const system = catalogs.systems[state.system]; + const value = system.base; + items.push({ label: system.name, value }); + total += value; + } + + if (state.layout) { + const layout = catalogs.layouts[state.layout]; + if (layout.surcharge > 0) { + items.push({ label: layout.name, value: layout.surcharge }); + total += layout.surcharge; + } + } + + if (state.system) { + const system = catalogs.systems[state.system]; + const trackValue = Math.round(state.trackLength * system.meter); + items.push({ label: `Szyny ${state.trackLength.toFixed(1)} m`, value: trackValue }); + total += trackValue; + } + + if (state.trackColor) { + const color = catalogs.colors[state.trackColor]; + if (color.surcharge > 0) { + items.push({ label: `Wykończenie ${color.name}`, value: color.surcharge }); + total += color.surcharge; + } + } + + fixtures.forEach((fixture) => { + const qty = state.fixtures[fixture.id] || 0; + if (qty > 0) { + const value = qty * fixture.price; + items.push({ label: `${fixture.name} x${qty}`, value }); + total += value; + } + }); + + accessories.forEach((acc) => { + if (state.accessories.has(acc.id)) { + items.push({ label: acc.name, value: acc.price }); + total += acc.price; + } + }); + + if (items.length === 0) { + items.push({ label: "Brak wybranych pozycji", value: 0 }); + } + + return { items, total }; +} + +function renderPreview() { + const colorToken = state.trackColor ? catalogs.colors[state.trackColor].line : "#f7f6f8"; + const spotCount = Math.max(1, Object.values(state.fixtures).reduce((sum, qty) => sum + qty, 0)); + const points = getPreviewPoints(state.layout || "line"); + + const circles = Array.from({ length: spotCount }, (_, i) => { + const point = points[i % points.length]; + const tone = getPreviewLightTone(state.temperature, i); + return ``; + }).join(""); + + const lines = getPreviewPath(state.layout || "line", colorToken); + + previewCanvas.innerHTML = ` + + `; +} + +function getPreviewPath(layout, color) { + const stroke = ``; + if (layout === "l_shape") { + return `${stroke}`; + } + if (layout === "u_shape") { + return `${stroke}`; + } + if (layout === "rectangle") { + return `${stroke}`; + } + return `${stroke}`; +} + +function getPreviewPoints(layout) { + if (layout === "l_shape") { + return [ + { x: 48, y: 54 }, + { x: 48, y: 82 }, + { x: 48, y: 112 }, + { x: 98, y: 130 }, + { x: 150, y: 130 }, + { x: 205, y: 130 }, + { x: 260, y: 130 } + ]; + } + if (layout === "u_shape") { + return [ + { x: 45, y: 55 }, + { x: 45, y: 100 }, + { x: 95, y: 130 }, + { x: 145, y: 130 }, + { x: 195, y: 130 }, + { x: 245, y: 130 }, + { x: 300, y: 102 }, + { x: 300, y: 58 } + ]; + } + if (layout === "rectangle") { + return [ + { x: 76, y: 40 }, + { x: 128, y: 40 }, + { x: 196, y: 40 }, + { x: 262, y: 40 }, + { x: 300, y: 76 }, + { x: 300, y: 114 }, + { x: 250, y: 130 }, + { x: 175, y: 130 }, + { x: 100, y: 130 }, + { x: 60, y: 96 } + ]; + } + return [ + { x: 64, y: 86 }, + { x: 104, y: 86 }, + { x: 146, y: 86 }, + { x: 188, y: 86 }, + { x: 230, y: 86 }, + { x: 272, y: 86 }, + { x: 312, y: 86 } + ]; +} + +function getPreviewLightTone(temperature, index) { + if (temperature === "3000") { + return { fill: "#ffb766", stroke: "#ffd4a2" }; + } + + if (temperature === "4000") { + return { fill: "#fff3d2", stroke: "#fff9ea" }; + } + + if (temperature === "cct") { + return index % 2 === 0 + ? { fill: "#ffbc77", stroke: "#ffe0b5" } + : { fill: "#c8e8ff", stroke: "#e9f6ff" }; + } + + return { fill: "#f7614d", stroke: "#ffd2cc" }; +} + +function validateCurrentStep() { + if (state.step === 1 && !state.system) { + return { ok: false, message: "Wybierz system szynowy, aby przejść dalej." }; + } + + if (state.step === 2 && !state.layout) { + return { ok: false, message: "Wybierz kształt konfiguracji." }; + } + + if (state.step === 3 && (!state.trackColor || !state.temperature)) { + return { ok: false, message: "Uzupełnij kolor szyny i temperaturę barwową." }; + } + + return { ok: true }; +} + +function syncInputs() { + trackLengthOut.textContent = state.trackLength.toFixed(1); + roomHeightInput.value = state.roomHeight.toFixed(1); + roomHeightOut.textContent = state.roomHeight.toFixed(1); +} + +function showToast(text) { + toast.textContent = text; + toast.classList.add("is-visible"); + clearTimeout(showToast.timer); + showToast.timer = setTimeout(() => { + toast.classList.remove("is-visible"); + }, 2100); +} + +function randomInt(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +function formatPLN(value) { + return `${value.toLocaleString("pl-PL")} zł`; +} diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..24bf161 --- /dev/null +++ b/styles.css @@ -0,0 +1,680 @@ +:root { + --brand-green: #108474; + --brand-accent: #f7614d; + --brand-text: #3c393a; + --brand-bg: #f7f6f8; + --brand-soft: #e8e7eb; + --brand-ink: #252627; + --brand-white: #ffffff; + --radius-lg: 22px; + --radius-md: 14px; + --shadow: 0 18px 50px rgba(60, 57, 58, 0.12); +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html, +body { + margin: 0; + min-height: 100%; + font-family: "Open Sans", sans-serif; + color: var(--brand-text); + background: linear-gradient(135deg, #fff 0%, var(--brand-bg) 48%, #edf5f5 100%); +} + +body { + position: relative; + overflow-x: hidden; +} + +.bg-shape { + position: fixed; + border-radius: 999px; + filter: blur(24px); + z-index: 0; + pointer-events: none; +} + +.bg-shape-a { + width: 420px; + height: 420px; + top: -120px; + right: -80px; + background: radial-gradient(circle at center, rgba(16, 132, 116, 0.28), rgba(16, 132, 116, 0)); +} + +.bg-shape-b { + width: 420px; + height: 420px; + bottom: -140px; + left: -90px; + background: radial-gradient(circle at center, rgba(247, 97, 77, 0.22), rgba(247, 97, 77, 0)); +} + +.shell { + position: relative; + z-index: 1; + max-width: 1260px; + margin: 0 auto; + padding: 28px 20px 42px; +} + +.hero { + padding: 12px 6px 24px; +} + +.brand { + display: inline-block; + padding: 6px 12px; + border-radius: 999px; + background: var(--brand-soft); + font-weight: 800; + letter-spacing: 0.08em; + font-size: 12px; +} + +.hero h1 { + margin: 12px 0 10px; + font-size: clamp(26px, 3.2vw, 46px); + line-height: 1.06; +} + +.hero p { + margin: 0; + max-width: 680px; + color: #616161; +} + +.layout { + display: grid; + grid-template-columns: 1.35fr 0.65fr; + gap: 20px; + align-items: start; +} + +.card { + background: rgba(255, 255, 255, 0.9); + backdrop-filter: blur(7px); + border: 1px solid rgba(37, 38, 39, 0.08); + border-radius: var(--radius-lg); + box-shadow: var(--shadow); +} + +.wizard { + padding: 18px; +} + +.steps { + display: grid; + grid-template-columns: repeat(6, 1fr); + gap: 8px; +} + +.step-item { + border: 0; + cursor: pointer; + background: var(--brand-soft); + color: #5e5b5c; + border-radius: 12px; + padding: 9px 8px; + font-size: 12px; + font-weight: 700; + display: flex; + flex-direction: column; + align-items: center; + gap: 5px; + transition: 0.24s ease; +} + +.step-item span { + width: 22px; + height: 22px; + border-radius: 50%; + background: rgba(255, 255, 255, 0.9); + display: grid; + place-items: center; + font-size: 11px; +} + +.step-item:hover { + transform: translateY(-1px); +} + +.step-item.is-active { + background: var(--brand-green); + color: #fff; +} + +.step-item.is-active span { + color: var(--brand-green); +} + +.step-item.is-done { + background: #d6efeb; + color: var(--brand-green); +} + +.step-panels { + margin-top: 16px; +} + +.step-panel { + display: none; + animation: panel-enter 0.28s ease; +} + +.step-panel.is-active { + display: block; +} + +@keyframes panel-enter { + from { + opacity: 0; + transform: translateY(8px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +h2 { + margin: 4px 0 8px; + font-size: clamp(21px, 2.2vw, 30px); +} + +h3 { + margin: 0 0 10px; + font-size: 14px; +} + +.muted { + margin: 0 0 14px; + color: #6b696a; + font-size: 14px; +} + +.option-grid { + display: grid; + gap: 10px; +} + +.option-grid.three { + grid-template-columns: repeat(3, minmax(0, 1fr)); +} + +.option-grid.four { + grid-template-columns: repeat(4, minmax(0, 1fr)); +} + +.option-card, +.layout-card { + position: relative; + display: grid; + align-content: start; + gap: 6px; + border: 1px solid rgba(37, 38, 39, 0.12); + border-radius: var(--radius-md); + background: #fff; + padding: 12px; + min-height: 122px; + cursor: pointer; + transition: 0.2s ease; +} + +.layout-card { + min-height: 116px; + justify-items: center; +} + +.option-card input, +.layout-card input { + position: absolute; + inset: 0; + opacity: 0; + pointer-events: none; +} + +.option-card strong, +.layout-card strong { + font-size: 14px; +} + +.option-card span { + font-size: 12px; + color: #666; +} + +.option-card em { + margin-top: auto; + font-style: normal; + font-weight: 800; + font-size: 13px; + color: var(--brand-green); +} + +.option-card.compact { + min-height: 72px; +} + +.finish-card { + min-height: 124px; + gap: 8px; +} + +.finish-swatch { + width: 30px; + height: 30px; + border-radius: 50%; + border: 2px solid rgba(37, 38, 39, 0.2); +} + +.finish-track { + display: block; + width: 100%; + height: 10px; + border-radius: 999px; + border: 1px solid rgba(37, 38, 39, 0.18); +} + +.swatch-black { + background: #252627; +} + +.swatch-white { + background: #f7f6f8; +} + +.swatch-champagne { + background: #d7bd8b; +} + +.temp-card { + min-height: 124px; + gap: 8px; + overflow: hidden; +} + +.temp-card .temp-glow { + display: block; + width: 100%; + height: 18px; + border-radius: 999px; + border: 1px solid rgba(37, 38, 39, 0.15); + animation: glow-pulse 2.2s ease-in-out infinite; +} + +.temp-card.temp-3000 .temp-glow { + background: linear-gradient(90deg, #ff9f45 0%, #ffd18c 100%); +} + +.temp-card.temp-4000 .temp-glow { + background: linear-gradient(90deg, #fff1c7 0%, #fff9e9 100%); +} + +.temp-card.temp-cct .temp-glow { + background: linear-gradient(90deg, #ffb66c 0%, #fff4d0 45%, #d2ecff 100%); +} + +@keyframes glow-pulse { + 0% { + filter: saturate(0.9); + } + 50% { + filter: saturate(1.15); + } + 100% { + filter: saturate(0.9); + } +} + +.shape { + width: 62px; + height: 38px; + border-radius: 10px; + border: 4px solid var(--brand-ink); +} + +.shape.line { + border-bottom: 0; + border-left: 0; + border-right: 0; + border-radius: 0; + height: 12px; + width: 70px; +} + +.shape.l-shape { + border-top: 0; + border-right: 0; + border-radius: 0 0 0 12px; +} + +.shape.u-shape { + border-top: 0; + border-radius: 0 0 12px 12px; +} + +.shape.rectangle { + border-radius: 8px; +} + +.option-card:has(input:checked), +.layout-card:has(input:checked) { + border-color: var(--brand-accent); + box-shadow: 0 0 0 3px rgba(247, 97, 77, 0.12); +} + +.finish-card:has(input:checked) .finish-swatch { + box-shadow: 0 0 0 4px rgba(247, 97, 77, 0.2); +} + +.finish-card:has(input:checked) .finish-track, +.temp-card:has(input:checked) .temp-glow { + box-shadow: 0 0 0 3px rgba(16, 132, 116, 0.14); +} + +.field-grid { + margin-top: 12px; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; +} + +.range-field { + border: 1px solid rgba(37, 38, 39, 0.12); + border-radius: var(--radius-md); + padding: 12px; + display: grid; + gap: 8px; + background: #fff; +} + +.range-field span { + font-size: 12px; + color: #6b696a; +} + +.range-field input[type="number"] { + width: 100%; + height: 40px; + border-radius: 10px; + border: 1px solid rgba(37, 38, 39, 0.2); + padding: 0 10px; + font-size: 14px; +} + +input[type="range"] { + width: 100%; + accent-color: var(--brand-green); +} + +.split { + display: grid; + gap: 12px; +} + +.product-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 10px; +} + +.product-card { + border-radius: 14px; + border: 1px solid rgba(37, 38, 39, 0.12); + background: #fff; + padding: 12px; + display: grid; + gap: 8px; +} + +.product-code { + font-size: 11px; + font-weight: 700; + letter-spacing: 0.03em; + color: var(--brand-green); +} + +.product-name { + min-height: 38px; + font-size: 13px; + font-weight: 700; +} + +.product-meta { + display: flex; + justify-content: space-between; + align-items: center; + gap: 8px; +} + +.price { + font-size: 13px; + font-weight: 800; +} + +.qty { + display: inline-flex; + align-items: center; + border: 1px solid rgba(37, 38, 39, 0.2); + border-radius: 999px; + overflow: hidden; +} + +.qty button { + width: 27px; + height: 26px; + border: 0; + background: #fff; + color: var(--brand-text); + cursor: pointer; + font-size: 16px; +} + +.qty span { + width: 34px; + text-align: center; + font-size: 13px; + font-weight: 700; +} + +.accessories { + display: grid; + gap: 8px; +} + +.accessory-item { + display: flex; + justify-content: space-between; + align-items: center; + border: 1px solid rgba(37, 38, 39, 0.11); + border-radius: 12px; + padding: 12px; + background: #fff; +} + +.accessory-item label { + display: inline-flex; + align-items: center; + gap: 10px; + font-size: 14px; + font-weight: 600; +} + +.accessory-item input { + accent-color: var(--brand-accent); +} + +.wizard-actions { + margin-top: 16px; + padding-top: 14px; + border-top: 1px solid rgba(37, 38, 39, 0.1); + display: flex; + justify-content: space-between; + gap: 10px; +} + +.btn { + border: 0; + border-radius: 999px; + min-height: 44px; + padding: 0 18px; + font-size: 14px; + font-weight: 800; + cursor: pointer; + transition: transform 0.2s ease; +} + +.btn:hover { + transform: translateY(-1px); +} + +.btn-primary { + background: var(--brand-accent); + color: #fff; +} + +.btn-secondary { + background: var(--brand-soft); + color: var(--brand-text); +} + +.summary { + position: sticky; + top: 16px; + padding: 18px; +} + +.preview { + border-radius: 14px; + min-height: 185px; + margin-bottom: 12px; + background: linear-gradient(160deg, #242526 0%, #3a3d3f 100%); + display: grid; + place-items: center; +} + +.summary-list { + list-style: none; + margin: 0; + padding: 0; + display: grid; + gap: 8px; +} + +.summary-list li { + display: flex; + justify-content: space-between; + gap: 12px; + border-bottom: 1px dashed rgba(37, 38, 39, 0.14); + padding-bottom: 7px; + font-size: 13px; +} + +.summary-total { + margin-top: 12px; + background: #fff; + border: 1px solid rgba(37, 38, 39, 0.12); + border-radius: 14px; + padding: 12px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.summary-total strong { + font-size: 25px; + color: var(--brand-green); +} + +.note { + margin: 10px 0 0; + color: #6b696a; + font-size: 12px; +} + +.final-summary { + border: 1px solid rgba(37, 38, 39, 0.12); + border-radius: 14px; + background: #fff; + padding: 12px; +} + +.final-summary ul { + margin: 0; + padding: 0; + list-style: none; + display: grid; + gap: 7px; +} + +.final-summary li { + display: flex; + justify-content: space-between; + gap: 10px; + font-size: 13px; +} + +.toast { + position: fixed; + left: 50%; + bottom: 18px; + transform: translateX(-50%) translateY(22px); + background: var(--brand-ink); + color: #fff; + border-radius: 999px; + padding: 12px 16px; + font-size: 13px; + opacity: 0; + transition: 0.24s ease; + pointer-events: none; + z-index: 5; +} + +.toast.is-visible { + opacity: 1; + transform: translateX(-50%) translateY(0); +} + +@media (max-width: 1120px) { + .layout { + grid-template-columns: 1fr; + } + + .summary { + position: static; + } + + .product-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (max-width: 780px) { + .wizard { + padding: 14px; + } + + .steps { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .option-grid.three, + .option-grid.four, + .field-grid { + grid-template-columns: 1fr; + } + + .product-grid { + grid-template-columns: 1fr; + } + + .step-item { + font-size: 11px; + } +}