{"id":2842,"date":"2025-12-23T15:11:21","date_gmt":"2025-12-23T14:11:21","guid":{"rendered":"https:\/\/greengardenbudapest.hu\/?page_id=2842"},"modified":"2026-01-15T21:18:24","modified_gmt":"2026-01-15T20:18:24","slug":"arkalkulator","status":"publish","type":"page","link":"https:\/\/greengardenbudapest.hu\/en\/arkalkulator\/","title":{"rendered":"Price calculator"},"content":{"rendered":"<div data-elementor-type=\"wp-page\" data-elementor-id=\"2842\" class=\"elementor elementor-2842\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-816056b e-con-full e-flex e-con e-parent\" data-id=\"816056b\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;video&quot;,&quot;background_video_link&quot;:&quot;https:\\\/\\\/greengardenbudapest.hu\\\/wp-content\\\/uploads\\\/2026\\\/01\\\/Semleges_hattervideo_kertepito_weboldalra-1.mp4&quot;,&quot;background_video_start&quot;:0,&quot;background_play_on_mobile&quot;:&quot;yes&quot;}\">\n\t\t<div class=\"elementor-background-video-container\">\n\t\t\t\t\t\t\t<video class=\"elementor-background-video-hosted\" role=\"presentation\" autoplay muted playsinline loop><\/video>\n\t\t\t\t\t<\/div>\t\t<div class=\"elementor-element elementor-element-4fb7f812 elementor-widget elementor-widget-heading\" data-id=\"4fb7f812\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h1 class=\"elementor-heading-title elementor-size-default\">Price calculator<\/h1>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1f0a2385 elementor-icon-list--layout-inline elementor-list-item-link-full_width elementor-widget elementor-widget-icon-list\" data-id=\"1f0a2385\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-list.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<ul class=\"elementor-icon-list-items elementor-inline-items\">\n\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"#\">\n\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">Home<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-icon\">\n\t\t\t\t\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-angle-right\" viewbox=\"0 0 256 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z\"><\/path><\/svg>\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">Price calculator<\/span>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t<\/ul>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-54ac7bb9 e-flex e-con-boxed e-con e-parent\" data-id=\"54ac7bb9\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;shape_divider_top&quot;:&quot;mountains&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-shape elementor-shape-top\" aria-hidden=\"true\" data-negative=\"false\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewbox=\"0 0 1000 100\" preserveaspectratio=\"none\">\n\t<path class=\"elementor-shape-fill\" opacity=\"0.33\" d=\"M473,67.3c-203.9,88.3-263.1-34-320.3,0C66,119.1,0,59.7,0,59.7V0h1000v59.7 c0,0-62.1,26.1-94.9,29.3c-32.8,3.3-62.8-12.3-75.8-22.1C806,49.6,745.3,8.7,694.9,4.7S492.4,59,473,67.3z\"\/>\n\t<path class=\"elementor-shape-fill\" opacity=\"0.66\" d=\"M734,67.3c-45.5,0-77.2-23.2-129.1-39.1c-28.6-8.7-150.3-10.1-254,39.1 s-91.7-34.4-149.2,0C115.7,118.3,0,39.8,0,39.8V0h1000v36.5c0,0-28.2-18.5-92.1-18.5C810.2,18.1,775.7,67.3,734,67.3z\"\/>\n\t<path class=\"elementor-shape-fill\" d=\"M766.1,28.9c-200-57.5-266,65.5-395.1,19.5C242,1.8,242,5.4,184.8,20.6C128,35.8,132.3,44.9,89.9,52.5C28.6,63.7,0,0,0,0 h1000c0,0-9.9,40.9-83.6,48.1S829.6,47,766.1,28.9z\"\/>\n<\/svg>\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-2d9ec9a4 e-con-full e-flex e-con e-child\" data-id=\"2d9ec9a4\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-14f36d11 elementor-widget__width-auto elementor-widget elementor-widget-image\" data-id=\"14f36d11\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" src=\"https:\/\/greengardenbudapest.hu\/wp-content\/uploads\/elementor\/thumbs\/cropped-cropped-greengardenbudapest.logo_-r4rzse2yum3nzstabm0k6miyc0p0lngbuedh4v98j8.png\" title=\"greengardenbudapest.logo\" alt=\"greengardenbudapest.logo\" loading=\"lazy\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-75f4e80b elementor-widget elementor-widget-heading\" data-id=\"75f4e80b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">Green Garden Budapest<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-595ecf15 elementor-widget elementor-widget-heading\" data-id=\"595ecf15\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h3 class=\"elementor-heading-title elementor-size-default\">Below you will find our latest in-house price calculator, which will also include other landscaping work from spring onwards.<\/h3>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-92e7bac e-con-full e-flex e-con e-parent\" data-id=\"92e7bac\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-5071f0d elementor-widget elementor-widget-html\" data-id=\"5071f0d\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"hu\" data-theme=\"light\">\r\n<head>\r\n<meta charset=\"UTF-8\">\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n<title>T\u00e9rk\u0151 \u00c1rkalkul\u00e1tor - Dark Mode<\/title>\r\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Poppins:wght@300;400;500;600;700&display=swap\" rel=\"stylesheet\">\r\n<style>\r\n    :root {\r\n        --bg-body: #f4f6f8;\r\n        --text-dark: #1a1a1a;\r\n        --text-light: #6c757d;\r\n        --primary: #2ecc71;\r\n        --primary-rgb: 46, 204, 113; \/* RGB \u00e9rt\u00e9k az \u00fcveg hat\u00e1shoz *\/\r\n        --primary-hover: #27ae60;\r\n        --card-bg: #ffffff;\r\n        --border-radius: 16px;\r\n        --shadow: 0 4px 20px rgba(0,0,0,0.08);\r\n        --input-bg: #f8f9fa;\r\n        --input-border: #e1e4e8;\r\n        --toggle-bg: #cfd8dc;\r\n        --info-bg: #e3f2fd;\r\n        --info-text: #0d47a1;\r\n        --info-border: #bbdefb;\r\n        --warning-bg: #fff3cd;\r\n        --warning-text: #856404;\r\n        --warning-border: #ffeeba;\r\n    }\r\n\r\n    \/* S\u00f6t\u00e9t m\u00f3d v\u00e1ltoz\u00f3k *\/\r\n    [data-theme=\"dark\"] {\r\n        --bg-body: #121212;\r\n        --text-dark: #e0e0e0;\r\n        --text-light: #a0a0a0;\r\n        --primary: #2ecc71; \r\n        --primary-rgb: 46, 204, 113;\r\n        --primary-hover: #27ae60;\r\n        --card-bg: #1e1e1e;\r\n        --shadow: 0 4px 20px rgba(0,0,0,0.4);\r\n        --input-bg: #2c2c2c;\r\n        --input-border: #444;\r\n        --toggle-bg: #4a4a4a;\r\n        --info-bg: #1a2733;\r\n        --info-text: #90caf9;\r\n        --info-border: #2c3e50;\r\n        --warning-bg: #3e3726;\r\n        --warning-text: #ffecb5;\r\n        --warning-border: #584e32;\r\n    }\r\n\r\n    body { \r\n        font-family: 'Poppins', sans-serif; \r\n        background-color: var(--bg-body); \r\n        color: var(--text-dark); \r\n        margin: 0; \r\n        padding: 0; \r\n        line-height: 1.6; \r\n        transition: background 0.3s, color 0.3s; \r\n    }\r\n    \r\n    \/* Layout Grid *\/\r\n    .app-container { \r\n        width: 100%;           \r\n        max-width: 100%;       \r\n        box-sizing: border-box; \r\n        padding: 20px;         \r\n        margin: 0 auto; \r\n        display: grid;\r\n        grid-template-columns: 2fr 1fr; \/* 2\/3 tartalom, 1\/3 sidebar *\/\r\n        gap: 30px;\r\n        align-items: start;\r\n    }\r\n\r\n    \/* Header & Theme Toggle *\/\r\n    .header-full { grid-column: 1 \/ -1; margin-bottom: 30px; text-align: left; position: relative; }\r\n    .header-full h1 { font-size: 2.2rem; font-weight: 800; color: var(--text-dark); margin: 0; letter-spacing: -0.5px; }\r\n    .header-full span { color: var(--primary); }\r\n    .header-subtitle { color: var(--text-light); font-size: 1rem; margin-top: 8px; max-width: 700px; }\r\n\r\n    .theme-toggle-btn {\r\n        position: absolute; top: 0; right: 0;\r\n        background: var(--card-bg); border: 1px solid var(--input-border);\r\n        color: var(--text-dark); padding: 10px; border-radius: 50%;\r\n        cursor: pointer; box-shadow: var(--shadow); transition: 0.3s;\r\n        width: 45px; height: 45px; display: flex; align-items: center; justify-content: center; font-size: 1.2rem;\r\n    }\r\n    .theme-toggle-btn:hover { transform: scale(1.1); }\r\n\r\n    \/* Cards *\/\r\n    .card {\r\n        background: var(--card-bg);\r\n        border-radius: var(--border-radius);\r\n        padding: 30px;\r\n        box-shadow: var(--shadow);\r\n        margin-bottom: 30px;\r\n        border: 1px solid rgba(0,0,0,0.02);\r\n        position: relative;\r\n        transition: background 0.3s;\r\n    }\r\n\r\n    \/* Step Indicators *\/\r\n    .step-badge {\r\n        position: absolute;\r\n        top: -15px;\r\n        left: 30px;\r\n        background: var(--primary);\r\n        color: white;\r\n        width: 40px;\r\n        height: 40px;\r\n        border-radius: 50%;\r\n        display: flex;\r\n        align-items: center;\r\n        justify-content: center;\r\n        font-weight: 700;\r\n        font-size: 1.2rem;\r\n        box-shadow: 0 5px 15px rgba(46, 204, 113, 0.4);\r\n        z-index: 2;\r\n    }\r\n\r\n    h2 { margin-top: 15px; font-size: 1.3rem; font-weight: 700; margin-bottom: 25px; color: var(--text-dark); }\r\n    \r\n    \/* Visual Selectors *\/\r\n    .visual-selector { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 15px; margin-bottom: 25px; }\r\n    .selector-item { position: relative; }\r\n    .selector-item input[type=\"radio\"] { position: absolute; opacity: 0; width: 0; height: 0; }\r\n    .selector-card {\r\n        background: var(--input-bg);\r\n        border-radius: 12px;\r\n        padding: 20px 10px;\r\n        text-align: center;\r\n        cursor: pointer;\r\n        transition: all 0.2s ease;\r\n        border: 2px solid transparent;\r\n        height: 100%;\r\n        display: flex;\r\n        flex-direction: column;\r\n        justify-content: center;\r\n        align-items: center;\r\n        box-sizing: border-box;\r\n    }\r\n    .selector-card svg { width: 32px; height: 32px; margin-bottom: 10px; fill: var(--text-light); transition: 0.2s; }\r\n    .selector-card span { font-weight: 600; color: var(--text-dark); font-size: 0.85rem; }\r\n    \r\n    .selector-item input:checked + .selector-card {\r\n        background: rgba(46, 204, 113, 0.1);\r\n        border-color: var(--primary);\r\n        transform: translateY(-2px);\r\n    }\r\n    .selector-item input:checked + .selector-card svg { fill: var(--primary); }\r\n    \r\n    \/* Inputs & Forms *\/\r\n    label { display: block; margin-bottom: 8px; font-weight: 500; font-size: 0.9rem; color: var(--text-dark); opacity: 0.9; }\r\n    input[type=\"number\"], input[type=\"text\"], input[type=\"email\"], select {\r\n        width: 100%; padding: 12px 15px;\r\n        background: var(--input-bg);\r\n        border: 1px solid var(--input-border);\r\n        border-radius: 10px;\r\n        font-family: 'Poppins', sans-serif;\r\n        font-size: 0.95rem;\r\n        color: var(--text-dark);\r\n        box-sizing: border-box;\r\n        transition: 0.2s;\r\n    }\r\n    input:focus, select:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(46, 204, 113, 0.1); }\r\n    \r\n    .input-row { display: flex; gap: 20px; flex-wrap: wrap; } \r\n    .input-col { flex: 1; min-width: 200px; }\r\n    .form-group { margin-bottom: 20px; }\r\n\r\n    \/* Slider *\/\r\n    input[type=\"range\"] {\r\n        -webkit-appearance: none; width: 100%; height: 6px; background: var(--input-border); border-radius: 5px; margin: 20px 0;\r\n    }\r\n    input[type=\"range\"]::-webkit-slider-thumb {\r\n        -webkit-appearance: none; width: 24px; height: 24px; border-radius: 50%; background: var(--primary); cursor: pointer; box-shadow: 0 2px 6px rgba(0,0,0,0.2); transition: transform 0.1s; border: 2px solid #fff;\r\n    }\r\n    input[type=\"range\"]::-webkit-slider-thumb:hover { transform: scale(1.1); }\r\n\r\n    \/* Canvas Area *\/\r\n    .canvas-wrapper { \r\n        background: #2c3e50; \r\n        border-radius: 12px; \r\n        overflow: hidden; \r\n        box-shadow: inset 0 0 20px rgba(0,0,0,0.3);\r\n        margin-top: 15px;\r\n        position: relative;\r\n        height: 350px;\r\n        border: 1px solid #34495e;\r\n    }\r\n    canvas { display: block; width: 100%; height: 100%; cursor: crosshair; }\r\n    \r\n    \/* Checkbox \/ Toggle *\/\r\n    .checkbox-row {\r\n        display: flex; justify-content: space-between; align-items: center;\r\n        background: var(--input-bg); border: 1px solid transparent; padding: 15px; border-radius: 12px;\r\n        margin-bottom: 12px; cursor: pointer; transition: 0.2s;\r\n    }\r\n    .checkbox-row:hover { border-color: var(--input-border); box-shadow: 0 2px 8px rgba(0,0,0,0.05); }\r\n    .checkbox-row input[type=\"checkbox\"] { display: none; }\r\n    \r\n    .toggle-switch {\r\n        width: 46px; height: 24px; background: var(--toggle-bg); border-radius: 50px; position: relative; transition: 0.3s; flex-shrink: 0;\r\n    }\r\n    .toggle-switch::after {\r\n        content: ''; position: absolute; top: 2px; left: 2px; width: 20px; height: 20px; background: white; border-radius: 50%; transition: 0.3s; box-shadow: 0 1px 3px rgba(0,0,0,0.2);\r\n    }\r\n    .checkbox-row input:checked + div span + .toggle-switch,\r\n    .checkbox-row input:checked ~ .toggle-switch { background: var(--primary); }\r\n    .checkbox-row input:checked ~ .toggle-switch::after { transform: translateX(22px); }\r\n\r\n    \/* Sidebar \/ Result Box *\/\r\n    .sidebar { position: sticky; top: 20px; }\r\n    .result-card {\r\n        background: var(--card-bg); border-radius: var(--border-radius); box-shadow: var(--shadow); padding: 30px;\r\n        text-align: left; border: 1px solid rgba(0,0,0,0.02);\r\n    }\r\n    .price-tag {\r\n        font-size: 2rem; font-weight: 800; color: var(--primary); margin: 15px 0;\r\n        background: rgba(46, 204, 113, 0.1); padding: 15px; border-radius: 12px; text-align: center;\r\n        letter-spacing: -0.5px; border: 1px solid rgba(46, 204, 113, 0.2);\r\n    }\r\n    .sidebar h3 { margin: 0; font-size: 1.2rem; color: var(--text-dark); display: inline-block;}\r\n    \r\n    .summary-list { list-style: none; padding: 0; margin: 0 0 20px 0; font-size: 0.9rem; color: var(--text-light); }\r\n    .summary-list li { display: flex; justify-content: space-between; margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px dashed var(--input-border); }\r\n    .summary-list li strong { color: var(--text-dark); }\r\n\r\n    \/* --- LIQUID GLASS GOMB ST\u00cdLUSOK (Apple Vision Style) --- *\/\r\n    .btn {\r\n        position: relative;\r\n        display: block; width: 100%; padding: 16px; \r\n        border-radius: 50px; \/* Pirula forma *\/\r\n        font-weight: 600; font-size: 1rem; cursor: pointer; text-align: center; text-transform: uppercase; letter-spacing: 1px;\r\n        border: 1px solid rgba(255,255,255,0.2);\r\n        outline: none; overflow: hidden;\r\n        backdrop-filter: blur(10px);\r\n        -webkit-backdrop-filter: blur(10px);\r\n        transition: all 0.4s cubic-bezier(0.25, 0.8, 0.25, 1);\r\n        z-index: 1;\r\n    }\r\n\r\n    \/* F\u00e9nycs\u00edk anim\u00e1ci\u00f3 *\/\r\n    .btn::before {\r\n        content: ''; position: absolute; top: 0; left: -100%; width: 100%; height: 100%;\r\n        background: linear-gradient(to right, transparent, rgba(255, 255, 255, 0.3), transparent);\r\n        transform: skewX(-25deg); transition: 0.5s; pointer-events: none; z-index: -1;\r\n    }\r\n    .btn:hover::before { left: 150%; transition: 0.7s ease-in-out; }\r\n\r\n    \/* Kalkul\u00e1ci\u00f3 gomb (S\u00f6t\u00e9t \u00fcveg) *\/\r\n    .btn-calc {\r\n        background: rgba(26, 26, 26, 0.85); \/* S\u00f6t\u00e9t \u00e1ttetsz\u0151 *\/\r\n        color: white;\r\n        box-shadow: \r\n            0 10px 20px rgba(0,0,0,0.15),\r\n            inset 0 1px 0 rgba(255,255,255,0.3),\r\n            inset 0 -2px 0 rgba(0,0,0,0.2);\r\n        flex: 1;\r\n    }\r\n    .btn-calc:hover {\r\n        transform: translateY(-3px) scale(1.02);\r\n        background: rgba(26, 26, 26, 0.95);\r\n        box-shadow: 0 15px 30px rgba(0,0,0,0.25), inset 0 1px 0 rgba(255,255,255,0.4);\r\n    }\r\n\r\n    \/* Ment\u00e9s gomb (Z\u00f6ld \u00fcveg - Eredeti sz\u00edn megtartva) *\/\r\n    .btn-save {\r\n        background: rgba(46, 204, 113, 0.85); \/* Primary sz\u00edn \u00e1ttetsz\u0151en *\/\r\n        color: white;\r\n        box-shadow: \r\n            0 10px 25px rgba(46, 204, 113, 0.3),\r\n            inset 0 1px 0 rgba(255,255,255,0.4),\r\n            inset 0 -2px 0 rgba(0,0,0,0.1);\r\n        flex: 1;\r\n    }\r\n    .btn-save:hover {\r\n        transform: translateY(-3px) scale(1.02);\r\n        background: rgba(46, 204, 113, 0.95);\r\n        box-shadow: 0 15px 35px rgba(46, 204, 113, 0.4), inset 0 1px 0 rgba(255,255,255,0.5);\r\n    }\r\n    .btn-save:disabled {\r\n        background: rgba(189, 195, 199, 0.8);\r\n        box-shadow: none; cursor: not-allowed; transform: none;\r\n    }\r\n\r\n    \/* Gomb kont\u00e9ner *\/\r\n    .action-buttons { display: flex; gap: 10px; margin-bottom: 12px; }\r\n\r\n    \/* Egy\u00e9b gombok (m\u00e1sodlagos) *\/\r\n    .btn-secondary { background: var(--input-bg); border: 1px solid var(--input-border); color: var(--text-dark); border-radius: 8px; padding: 8px 15px; font-size: 0.85rem; width: auto; display: inline-block; margin-right: 5px; text-transform: none;}\r\n    .btn-secondary:hover { background: var(--card-bg); border-color: var(--text-light); }\r\n    .btn-danger { background: rgba(231, 76, 60, 0.1); border: 1px solid rgba(231, 76, 60, 0.3); color: #c53030; border-radius: 8px; padding: 8px 15px; font-size: 0.85rem; width: auto; display: inline-block; text-transform: none;}\r\n    .btn-danger:hover { background: rgba(231, 76, 60, 0.2); }\r\n\r\n    .help-icon { background: rgba(33, 150, 243, 0.1); color: #2196F3; width: 20px; height: 20px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-size: 0.75rem; cursor: pointer; margin-left: 5px; vertical-align: middle;}\r\n\r\n    \/* Utility *\/\r\n    .hidden { display: none !important; }\r\n    .mt-2 { margin-top: 20px; }\r\n    \r\n    .toolbar { background: var(--card-bg); padding: 10px; border-radius: 8px; margin-top: 10px; display: flex; gap: 10px; align-items: center; box-shadow: 0 2px 10px rgba(0,0,0,0.05); flex-wrap: wrap; }\r\n\r\n    \/* Disclaimer *\/\r\n    .disclaimer-small { font-size: 0.75rem; color: var(--text-light); text-align: center; margin-top: 15px; line-height: 1.4; }\r\n    \r\n    \/* Warning Box *\/\r\n    .warning-box {\r\n        background: var(--warning-bg); border: 1px solid var(--warning-border); color: var(--warning-text);\r\n        padding: 10px; border-radius: 8px; font-size: 0.8rem; margin-bottom: 15px; text-align: center;\r\n        line-height: 1.3;\r\n    }\r\n\r\n    \/* Info Link *\/\r\n    .info-link {\r\n        font-size: 0.85rem; color: var(--info-text); text-decoration: none; display: inline-flex; align-items: center; gap: 5px; cursor: pointer;\r\n        background: var(--info-bg); padding: 5px 10px; border-radius: 20px; border: 1px solid var(--info-border);\r\n    }\r\n    .info-link:hover { background: #d0e7fb; }\r\n    \r\n    \/* Extra inf\u00f3 box st\u00edlus *\/\r\n    .info-note {\r\n        font-size: 0.85rem; \r\n        color: #0c5460; \r\n        background: #d1ecf1; \r\n        padding: 10px; \r\n        border-radius: 8px; \r\n        margin-top: 10px; \r\n        border: 1px solid #bee5eb;\r\n    }\r\n    \r\n    \/* Sikeres ment\u00e9s box st\u00edlus *\/\r\n    .success-info-box {\r\n        font-size: 0.85rem; color: #155724; background: #d4edda; \r\n        padding: 15px; border-radius: 8px; border: 1px solid #c3e6cb;\r\n        margin-top: 15px; margin-bottom: 10px;\r\n        text-align: left;\r\n    }\r\n\r\n    \/* Mobile \/ Responsive *\/\r\n    @media (max-width: 992px) {\r\n        .app-container { grid-template-columns: 1fr; gap: 20px; }\r\n        .sidebar { position: static; order: 1; }\r\n        .header-full { padding-right: 60px; } \/* Gomb hely\u00e9nek biztos\u00edt\u00e1sa *\/\r\n        .header-full h1 { font-size: 1.8rem; }\r\n        .card { padding: 20px; }\r\n        .visual-selector { grid-template-columns: 1fr 1fr; }\r\n    }\r\n<\/style>\r\n<\/head>\r\n<body>\r\n\r\n<div class=\"app-container\">\r\n    \r\n    <div class=\"header-full\">\r\n        <h1>Paving stone <span>Price calculator<\/span><\/h1>\r\n        <div class=\"header-subtitle\">Plan your costs in advance! Enter the dimensions, select the materials, and get an instant estimate.<\/div>\r\n        \r\n        <button class=\"theme-toggle-btn\" onclick=\"toggleTheme()\" title=\"Dark\/Light mode\">\r\n            <span id=\"themeIcon\">\u2600\ufe0f<\/span>\r\n        <\/button>\r\n    <\/div>\r\n\r\n    <div class=\"main-content\">\r\n        \r\n        <div class=\"card\">\r\n            <div class=\"step-badge\">1<\/div>\r\n            <h2>Specify area<\/h2>\r\n            \r\n            <div class=\"visual-selector radio-group\">\r\n                <label class=\"selector-item\">\r\n                    <input type=\"radio\" name=\"drawMode\" value=\"rect\" checked onchange=\"setMode('rect')\">\r\n                    <div class=\"selector-card\">\r\n                        <svg viewbox=\"0 0 24 24\"><path d=\"M4 6v12h16V6H4zm18-2v16H2V4h20z\"\/><\/svg>\r\n                        <span>Rectangle (m)<\/span>\r\n                    <\/div>\r\n                <\/label>\r\n                <label class=\"selector-item\">\r\n                    <input type=\"radio\" name=\"drawMode\" value=\"area\" onchange=\"setMode('area')\">\r\n                    <div class=\"selector-card\">\r\n                        <svg viewbox=\"0 0 24 24\"><path d=\"M4 4h16v16H4V4zm2 2v12h12V6H6z\"\/><path d=\"M9 9h6v6H9z\" opacity=\".3\"\/><\/svg>\r\n                        <span>Area (m\u00b2)<\/span>\r\n                    <\/div>\r\n                <\/label>\r\n                <label class=\"selector-item\">\r\n                    <input type=\"radio\" name=\"drawMode\" value=\"poly\" onchange=\"setMode('poly')\">\r\n                    <div class=\"selector-card\">\r\n                        <svg viewbox=\"0 0 24 24\"><path d=\"M17 19.3l-10-2.3L4.7 9l5.5-5.5 8.7 1.8 1.9 9.3z\" stroke=\"currentColor\" fill=\"none\" stroke-width=\"2\"\/><\/svg>\r\n                        <span>Freehand drawing<\/span>\r\n                    <\/div>\r\n                <\/label>\r\n            <\/div>\r\n\r\n            <div id=\"inputsRect\" class=\"input-row form-group\">\r\n                <div class=\"input-col\"><label>Width (meters)<\/label><input type=\"number\" id=\"inRectW\" placeholder=\"e.g. 5\" min=\"1\"><\/div>\r\n                <div class=\"input-col\"><label>Length (meters)<\/label><input type=\"number\" id=\"inRectH\" placeholder=\"e.g. 10\" min=\"1\"><\/div>\r\n            <\/div>\r\n            <div id=\"inputsArea\" class=\"form-group hidden\">\r\n                <label>Total area (m\u00b2)<\/label><input type=\"number\" id=\"inAreaTotal\" placeholder=\"e.g. 50\" min=\"1\">\r\n            <\/div>\r\n            <div id=\"inputsPoly\" class=\"form-group hidden\">\r\n                <label>Canvas size \/ view width (m):<\/label>\r\n                <input type=\"number\" id=\"inPolyMaxW\" value=\"30\" min=\"5\" onchange=\"updateScaleFromInput()\">\r\n            <\/div>\r\n            \r\n            <button id=\"btnDrawSimple\" class=\"btn btn-secondary\" style=\"width:100%; border-radius:10px; margin-top:10px;\" onclick=\"drawSimpleShape()\">\r\n                \u27f3 Updating\/drawing floor plans\r\n            <\/button>\r\n        <\/div>\r\n\r\n        <div class=\"card\" id=\"visualPanel\">\r\n            <div class=\"step-badge\">2<\/div>\r\n            <h2>Materials and Conditions<\/h2>\r\n            \r\n            <input type=\"hidden\" id=\"visualWorkType\" value=\"paving\">\r\n\r\n            <div class=\"form-group\" style=\"background:var(--input-bg); padding:20px; border-radius:12px; border:1px solid var(--input-border); margin-bottom:20px;\">\r\n                <label style=\"margin-bottom:15px; font-weight:700;\">Local conditions (for information purposes only):<\/label>\r\n                <div class=\"input-row\">\r\n                    <div class=\"input-col\">\r\n                        <label>Soil type<\/label>\r\n                        <select id=\"soilType\">\r\n                            <option value=\"normal\">Average \/ Black soil<\/option>\r\n                            <option value=\"sandy\">Gay<\/option>\r\n                            <option value=\"clay\">Clayey \/ Hard<\/option>\r\n                            <option value=\"rocky\">K\u00f6ves \/ Sittes<\/option>\r\n                        <\/select>\r\n                    <\/div>\r\n                    <div class=\"input-col\">\r\n                        <label>Terrain conditions<\/label>\r\n                        <select id=\"terrainType\">\r\n                            <option value=\"flat\">Flat area<\/option>\r\n                            <option value=\"slight_slope\">Slightly sloping<\/option>\r\n                            <option value=\"steep\">Steep \/ Terraced<\/option>\r\n                        <\/select>\r\n                    <\/div>\r\n                <\/div>\r\n            <\/div>\r\n            <div id=\"pavingOptions\">\r\n                <div class=\"form-group\" style=\"background:var(--input-bg); padding:20px; border-radius:12px; border:1px solid var(--input-border);\">\r\n                    <div style=\"display:flex; justify-content:space-between; align-items:center; margin-bottom:10px;\">\r\n                        <label style=\"margin:0; font-weight:600;\">Paving stone quality<\/label>\r\n                        <span id=\"stonePriceDisplay\" style=\"color:var(--primary); font-weight:700;\">Average (~$2.50\/m\u00b2)<\/span>\r\n                    <\/div>\r\n                    <input type=\"range\" id=\"stoneQuality\" min=\"1\" max=\"3\" step=\"1\" value=\"2\" oninput=\"updateStoneLabel()\">\r\n                    <div style=\"display:flex; justify-content:space-between; font-size:0.8rem; color:var(--text-light);\">\r\n                        <span>Base<\/span>\r\n                        <span>Premium<\/span>\r\n                    <\/div>\r\n                <\/div>\r\n\r\n                <div class=\"input-row form-group\">\r\n                    <div class=\"input-col\">\r\n                        <label>Paving stone Size<\/label>\r\n                        <select id=\"pavingSize\" onchange=\"updatePavingSettings()\">\r\n                            <option value=\"small\">Small (Cobblestone)<\/option>\r\n                            <option value=\"medium\" selected>Medium (Standard)<\/option>\r\n                            <option value=\"large\">Large (Floor covering)<\/option>\r\n                            <option value=\"mixed\">Mixed (Combined)<\/option>\r\n                        <\/select>\r\n                    <\/div>\r\n                    <div class=\"input-col\">\r\n                        <label>Deposit Sample<\/label>\r\n                        <select id=\"pavingPattern\" onchange=\"updatePavingSettings()\">\r\n                            <option value=\"sym\">Symmetrical<\/option>\r\n                            <option value=\"asym\">Asymmetrical<\/option>\r\n                        <\/select>\r\n                    <\/div>\r\n                <\/div>\r\n                \r\n                <div class=\"form-group\">\r\n                    <label>Type of foundation <span class=\"help-icon\" onclick=\"toggleBaseInfo()\" title=\"Info\">?<\/span><\/label>\r\n                    <div id=\"baseInfoBox\" class=\"hidden\" style=\"font-size:0.85rem; color:#0c5460; background:#d1ecf1; padding:10px; border-radius:8px; margin-bottom:10px;\">\r\n                        <strong>Tip:<\/strong> Gravel is sufficient for sidewalks\/terraces. We recommend concrete for parking spaces.\r\n                    <\/div>\r\n                    <select id=\"pavingBase\">\r\n                        <option value=\"gravel\">0-20 Powdered gravel bedding (budget-friendly)<\/option>\r\n                        <option value=\"concrete\">Load-bearing concrete (recommended for parking spaces)<\/option>\r\n                    <\/select>\r\n                    \r\n                    <div class=\"info-note\">\r\n                        <strong>\ud83d\udca1 Important information:<\/strong> If, for example, you would like to have paving stones made from crushed stone AND a separate concrete driveway, please prepare <strong>two separate calculations<\/strong> (one with powdered glass, one with concrete). We will see that they belong to one customer!\r\n                    <\/div>\r\n                <\/div>\r\n            <\/div>\r\n\r\n            <label style=\"margin-top:25px; font-weight:600;\">Area preview:<\/label>\r\n            <div id=\"polyInstruction\" class=\"hidden\" style=\"font-size:0.85rem; color:var(--primary); margin-bottom:5px;\">\r\n                <i style=\"font-style:normal\">\u270e<\/i> Click to place corners, double-click to close!\r\n            <\/div>\r\n            \r\n            <div class=\"canvas-wrapper\">\r\n                <canvas id=\"plotCanvas\"><\/canvas>\r\n            <\/div>\r\n\r\n            <div id=\"polyToolbar\" class=\"toolbar hidden\">\r\n                 <label style=\"font-size:0.8rem; display:flex; align-items:center; gap:5px; cursor:pointer; color:var(--text-dark);\">\r\n                    <input type=\"checkbox\" id=\"chkShowLengths\" checked onchange=\"requestRender()\"> Dimensions\r\n                 <\/label>\r\n                 <div style=\"flex:1\"><\/div>\r\n                 <button class=\"btn btn-secondary\" onclick=\"undoPoint()\">Back<\/button>\r\n                 <button class=\"btn btn-secondary\" style=\"background:rgba(33, 150, 243, 0.1); color:#2196F3; border-color:rgba(33, 150, 243, 0.3);\" onclick=\"closePolygon()\">Closing<\/button>\r\n                 <button class=\"btn btn-danger\" onclick=\"resetPoly()\">Delete<\/button>\r\n            <\/div>\r\n             <div id=\"multiPolyStats\" class=\"hidden\" style=\"margin-top: 5px; font-size: 0.85rem; color: var(--text-light); text-align:right;\">\r\n                Recorded: <span id=\"polyCount\" style=\"font-weight:bold;\">0<\/span> pcs (<span id=\"polyAreaTotal\">0<\/span> m\u00b2)\r\n            <\/div>\r\n            <div id=\"visualMsg\" style=\"color:#c53030; display:none; margin-top:5px; font-size:0.9rem; font-weight:500;\"><\/div>\r\n        <\/div>\r\n\r\n        <div class=\"card\">\r\n            <div class=\"step-badge\">3<\/div>\r\n            <h2>Extras<\/h2>\r\n            \r\n            <div class=\"checkbox-group\">\r\n                <label class=\"checkbox-row\">\r\n                    <div style=\"flex:1; display: flex; flex-direction: column;\">\r\n                        <span style=\"font-weight:600; color:var(--text-dark);\">Edging<\/span>\r\n                        <span style=\"font-size:0.85rem; color:var(--text-light);\">Stabilizing paving stones<\/span>\r\n                    <\/div>\r\n                    <input type=\"checkbox\" id=\"extraEdging\" onchange=\"toggleEdgingInput()\" checked> \r\n                    <div class=\"toggle-switch\"><\/div>\r\n                <\/label>\r\n                \r\n                <div id=\"edgingInputContainer\" style=\"padding:15px; background:var(--input-bg); border-radius:10px; margin-top:-5px; margin-bottom:15px; border:1px solid var(--input-border);\">\r\n                    <label style=\"font-size:0.85rem;\">Circumference (meters):<\/label>\r\n                    <div style=\"display:flex; gap:10px;\">\r\n                        <input type=\"number\" id=\"edgingLength\" placeholder=\"m\">\r\n                        <span style=\"align-self:center; font-size:0.8rem; color:var(--text-light); white-space:nowrap;\">(Auto calculated)<\/span>\r\n                    <\/div>\r\n                <\/div>\r\n            <\/div>\r\n        <\/div>\r\n\r\n    <\/div>\r\n\r\n    <div class=\"sidebar\" id=\"calcPanel\">\r\n        <div class=\"result-card\">\r\n            <div style=\"display:flex; justify-content:space-between; align-items:center; margin-bottom:20px;\">\r\n                <h3>Cost estimate<\/h3>\r\n                <a onclick=\"openHelp()\" class=\"info-link\">\u2139\ufe0f<\/a>\r\n            <\/div>\r\n            \r\n            <input type=\"number\" id=\"calcArea\" class=\"hidden\"> \r\n            <select id=\"calcWorkType\" class=\"hidden\"><option value=\"paving\" selected>Paving<\/option><\/select>\r\n\r\n            <div class=\"form-group mt-2\">\r\n                <label>Name (required) <span style=\"color:red\">*<\/span><\/label>\r\n                <input type=\"text\" id=\"clientName\" placeholder=\"e.g. J\u00e1nos Kov\u00e1cs\">\r\n            <\/div>\r\n            <div class=\"form-group\">\r\n                <label>Email address (required) <span style=\"color:red\">*<\/span><\/label>\r\n                <input type=\"email\" id=\"clientEmail\" placeholder=\"e.g. kovacs@gmail.com\">\r\n            <\/div>\r\n\r\n            <div class=\"action-buttons\">\r\n                <button id=\"btnDoCalc\" class=\"btn btn-calc\" onclick=\"performCalculationAndShow()\">Calculation<\/button>\r\n                <button id=\"btnSaveQuote\" class=\"btn btn-save hidden\" onclick=\"saveToFirebase()\">Save<\/button>\r\n                <button id=\"btnNewCalc\" class=\"btn btn-secondary hidden\" onclick=\"resetCalculator()\">Again<\/button>\r\n            <\/div>\r\n\r\n            <div id=\"preCalcMessage\" style=\"text-align:center; color:var(--text-light); margin: 20px 0;\">\r\n                <div style=\"font-size:1.5rem; margin-bottom:5px; opacity:0.3;\">\ud83e\uddee<\/div>\r\n                Click on the calculation button for the price\r\n            <\/div>\r\n\r\n            <div id=\"calcResult\" class=\"hidden\">\r\n                 <div class=\"warning-box\">\r\n                     <strong>Attention!<\/strong><br>The price shown here is an indicative estimate., <strong>does not constitute an offer<\/strong>.\r\n                 <\/div>\r\n\r\n                 <ul class=\"summary-list\">\r\n                    <li><span>Offer ID:<\/span> <span id=\"quoteIdDisplay\" style=\"font-family:monospace; color:var(--primary); font-weight:bold;\">---<\/span><\/li>\r\n                 <\/ul>\r\n                 \r\n                 <div class=\"form-group\">\r\n                     <label style=\"font-size:0.85rem; color:var(--text-light); text-align:center;\">Estimated cost:<\/label>\r\n                     <div id=\"priceRangeDisplay\" class=\"price-tag\">0 Ft<\/div>\r\n                     <div id=\"calcDetails\" style=\"font-size:0.85rem; color:var(--text-light); margin-bottom:15px; text-align:center; padding:10px; background:var(--input-bg); border-radius:8px;\"><\/div>\r\n                     \r\n                     <div class=\"info-note\" style=\"border-color:#ffeeba; background:#fff3cd; color:#856404; font-size:0.8rem; text-align:left;\">\r\n                        <strong>\ud83d\udee0\ufe0f Important:<\/strong> The price <strong>contains<\/strong> the foundation. <br>\r\n                        Breaking up and removing existing concrete or rubble is included in the price. <strong>Does NOT include<\/strong>, This service is available at an additional cost.\r\n                     <\/div>\r\n                 <\/div>\r\n\r\n                 <div class=\"success-info-box\">\r\n                    <strong>What happens after the backup?<\/strong><br>\r\n                    If the above <strong>Save<\/strong> button, we will automatically send you the calculation by email. <br><br>\r\n                    We will contact you shortly by email to clarify - you just need to enter the details above. <strong>Offer ID<\/strong>-you must refer to!\r\n                 <\/div>\r\n\r\n                 <div style=\"font-size:0.7rem; color:var(--text-light); margin-top:8px; line-height:1.3; text-align:center;\">\r\n                    By clicking the \"Save\" button, you expressly consent to the storage of your data (name, email address) in our system and to us contacting you by email or telephone for marketing purposes.\r\n                 <\/div>\r\n            <\/div>\r\n\r\n            <div id=\"saveFeedback\" style=\"font-size:0.85rem; margin-top:10px; text-align:center; font-weight:500;\"><\/div>\r\n        <\/div>\r\n        \r\n        <div style=\"text-align:center; margin-top:20px; color:var(--text-light); font-size:0.8rem;\">\r\n            <span style=\"color:var(--primary);\">\u2714<\/span> Guarantee of quality\r\n        <\/div>\r\n    <\/div>\r\n    \r\n    <div style=\"grid-column: 1 \/ -1; text-align: center; margin-top: 30px; font-size: 0.8rem; color: var(--text-light); border-top: 1px solid var(--input-border); padding-top: 20px;\">\r\n        \u00a9 Green Garden Budapest - 2023 property\r\n    <\/div>\r\n\r\n<\/div>\r\n\r\n<div id=\"helpModal\" style=\"display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.6); z-index:9999; justify-content:center; align-items:center; backdrop-filter:blur(3px);\" onclick=\"closeHelpOnOutside(event)\">\r\n    <div style=\"background:var(--card-bg); padding:30px; border-radius:16px; max-width:600px; width:90%; position:relative; box-shadow:0 20px 40px rgba(0,0,0,0.2); max-height: 90vh; overflow-y: auto;\">\r\n        <span onclick=\"closeHelp()\" style=\"position:absolute; top:15px; right:20px; font-size:1.5rem; cursor:pointer; color:var(--text-light);\">\u00d7<\/span>\r\n        <h2 style=\"color:var(--primary); margin-top:0;\">How does it work?<\/h2>\r\n        \r\n        <ol style=\"padding-left: 20px; color: var(--text-dark); line-height: 1.8;\">\r\n            <li><strong>Specify area:<\/strong> Select the shape (rectangle or freehand) and enter the dimensions, or draw the area.<\/li>\r\n            <li><strong>Selection of materials:<\/strong> Specify the type of soil, terrain conditions, and select the quality of the paving stones.<\/li>\r\n            <li><strong>Multiple surfaces?<\/strong> If you would like smooth paving and a concrete driveway in separate sections, please prepare two separate calculations!<\/li>\r\n            <li><strong>Extras:<\/strong> Check this box if you need edging.<\/li>\r\n            <li><strong>Data:<\/strong> Please enter your name and email address for the calculation.<\/li>\r\n            <li><strong>Calculation:<\/strong> Press the \"Calculate\" button to view the estimated price.<\/li>\r\n            <li><strong>Save:<\/strong> If you would like to send us your request, click on the \"Save\" button that appears. Our system will send you a confirmation email.<\/li>\r\n        <\/ol>\r\n\r\n        <div style=\"background: #fff3cd; color: #856404; padding: 15px; border-radius: 8px; margin-top: 20px; font-size: 0.9rem; border: 1px solid #ffeeba;\">\r\n            <strong>\u26a0\ufe0f Important information:<\/strong><br>\r\n            The amount calculated by the calculator is only a preliminary estimate, which <strong>This does NOT constitute an official offer.<\/strong>. In all cases, an on-site survey is required for final pricing, where we will specify the technical details.\r\n        <\/div>\r\n        \r\n        <div style=\"margin-top: 15px; font-size: 0.8rem; color: var(--text-light);\">\r\n            Data processing: By clicking the \"Save\" button, you consent to the processing of your data for marketing purposes.\r\n        <\/div>\r\n        \r\n        <div style=\"text-align: center; margin-top: 20px;\">\r\n            <button class=\"btn btn-secondary\" onclick=\"closeHelp()\">Close<\/button>\r\n        <\/div>\r\n    <\/div>\r\n<\/div>\r\n\r\n<script type=\"module\">\r\n  import { initializeApp } from \"https:\/\/www.gstatic.com\/firebasejs\/12.7.0\/firebase-app.js\";\r\n  import { getFirestore, collection, addDoc, doc, updateDoc } from \"https:\/\/www.gstatic.com\/firebasejs\/12.7.0\/firebase-firestore.js\";\r\n\r\n  const firebaseConfig = {\r\n    apiKey: \"AIzaSyDieI7TtKzzxVbA3kmWpclVuIy-XR4Vjbc\",\r\n    authDomain: \"arkalkulator-1d837.firebaseapp.com\",\r\n    projectId: \"arkalkulator-1d837\",\r\n    storageBucket: \"arkalkulator-1d837.firebasestorage.app\",\r\n    messagingSenderId: \"196082219880\",\r\n    appId: \"1:196082219880:web:55bb1a30bb98cf22dd74dd\",\r\n    measurementId: \"G-GTCSZ27WL8\"\r\n  };\r\n\r\n  const app = initializeApp(firebaseConfig);\r\n  const db = getFirestore(app);\r\n\r\n  \/\/ --- \u00daJ KONFIGUR\u00c1CI\u00d3 A S\u00c1VOS \u00c1RAZ\u00c1SSAL ---\r\n  const CONFIG = {\r\n    padding: 40, rulerColor: '#666', lineColor: '#fff',\r\n    tiers: {\r\n        gravel: [\r\n            { max: 10, price: 387500 },\r\n            { max: 20, price: 482000 },\r\n            { max: 30, price: 667000 },\r\n            { max: 40, price: 909500 },\r\n            { max: 50, price: 1026500 },\r\n            { max: 60, price: 1273500 },\r\n            { max: 70, price: 1461500 },\r\n            { max: 80, price: 1684000 },\r\n            { max: 90, price: 2031000 },\r\n            { max: 100, price: 2240500 },\r\n            { max: 110, price: 2485000 },\r\n            { max: 120, price: 2717500 },\r\n            { max: 130, price: 3014500 },\r\n            { max: 140, price: 3339500 },\r\n            { max: 150, price: 3504000 }\r\n        ],\r\n        concrete: [\r\n            { max: 10, price: 423500 },\r\n            { max: 20, price: 542000 },\r\n            { max: 30, price: 763000 },\r\n            { max: 40, price: 1029500 },\r\n            { max: 50, price: 1182500 },\r\n            { max: 60, price: 1453500 },\r\n            { max: 70, price: 1677500 },\r\n            { max: 80, price: 1924000 },\r\n            { max: 90, price: 2307000 },\r\n            { max: 100, price: 2540500 },\r\n            { max: 110, price: 2821000 },\r\n            { max: 120, price: 3077500 },\r\n            { max: 130, price: 3410500 },\r\n            { max: 140, price: 3759500 },\r\n            { max: 150, price: 3960000 }\r\n        ]\r\n    },\r\n    prices: { \r\n        edgingLowQty: 7500, \/\/ \u00c1r, ha 10m alatt van\r\n        edgingHighQty: 6500 \/\/ \u00c1r, ha 10m felett van\r\n    }\r\n  };\r\n\r\n  const STATE = {\r\n    mode: 'rect', points: [], finishedPolygons: [], \r\n    pxPerMeter: 10, mouseX: 0, mouseY: 0, pavingCache: null, pavingSettings: { size: 'medium', pattern: 'sym' },\r\n    lastCalculatedData: null,\r\n    currentDocId: null \r\n  };\r\n\r\n  const canvas = document.getElementById('plotCanvas');\r\n  const ctx = canvas.getContext('2d');\r\n\r\n  \/\/ --- S\u00d6T\u00c9T M\u00d3D LOGIKA ---\r\n  window.toggleTheme = function() {\r\n      const html = document.documentElement;\r\n      const current = html.getAttribute('data-theme');\r\n      const icon = document.getElementById('themeIcon');\r\n      \r\n      if (current === 'light') {\r\n          html.setAttribute('data-theme', 'dark');\r\n          icon.innerText = '\ud83c\udf19';\r\n      } else {\r\n          html.setAttribute('data-theme', 'light');\r\n          icon.innerText = '\u2600\ufe0f';\r\n      }\r\n      requestRender();\r\n  }\r\n\r\n  \/\/ --- KALKUL\u00c1CI\u00d3 \u00c9S AUTOMATIKUS MENT\u00c9S ---\r\n  window.performCalculationAndShow = async function() {\r\n      syncAreaToCalculator(); \r\n      syncPerimeter();\r\n      \r\n      const name = document.getElementById('clientName').value;\r\n      const email = document.getElementById('clientEmail').value;\r\n      \r\n      if (!name || name.trim() === \"\") {\r\n          alert(\"A kalkul\u00e1ci\u00f3hoz k\u00e9rj\u00fck, adja meg a nev\u00e9t!\");\r\n          document.getElementById('clientName').focus();\r\n          return;\r\n      }\r\n      if (!email || !email.includes('@')) {\r\n          alert(\"A kalkul\u00e1ci\u00f3hoz k\u00e9rj\u00fck, adjon meg egy \u00e9rv\u00e9nyes email c\u00edmet!\");\r\n          document.getElementById('clientEmail').focus();\r\n          return;\r\n      }\r\n\r\n      window.performCalculation();\r\n      \r\n      const area = parseFloat(document.getElementById('calcArea').value);\r\n      if(area > 0) {\r\n        \/\/ Enn\u00e9l a pontn\u00e1l elt\u00fcntetj\u00fck az utas\u00edt\u00e1st (\"Kattints a kalkul\u00e1ci\u00f3 gombra\")\r\n        document.getElementById('preCalcMessage').classList.add('hidden');\r\n        \r\n        \/\/ Gombok kezel\u00e9se: Kalkul\u00e1ci\u00f3 elt\u0171nik, Ment\u00e9s \u00e9s \u00dajra megjelenik\r\n        document.getElementById('btnDoCalc').classList.add('hidden');\r\n        \r\n        \/\/ Csak akkor ment\u00fcnk automat\u00e1n \u00e9s mutatunk gombokat, ha nincs t\u00fall\u00e9pve a limit\r\n        if(area <= 150) {\r\n             document.getElementById('btnSaveQuote').classList.remove('hidden');\r\n             document.getElementById('btnNewCalc').classList.remove('hidden');\r\n             await backgroundSave(); \r\n        } else {\r\n             \/\/ Ha t\u00fal nagy, csak az \"\u00dajra\" gomb kell, hogy visszal\u00e9phessen\r\n             document.getElementById('btnNewCalc').classList.remove('hidden');\r\n        }\r\n      } else {\r\n        alert(\"K\u00e9rj\u00fck adja meg a m\u00e9reteket az 1. pontban!\");\r\n      }\r\n  }\r\n\r\n  \/\/ --- \u00daJRA (RESET) FUNKCI\u00d3 ---\r\n  window.resetCalculator = function() {\r\n      \/\/ 1. Reset UI elemek\r\n      document.getElementById('calcResult').classList.add('hidden');\r\n      document.getElementById('preCalcMessage').classList.remove('hidden');\r\n      \r\n      \/\/ Gombok vissza\u00e1ll\u00edt\u00e1sa\r\n      document.getElementById('btnDoCalc').classList.remove('hidden');\r\n      document.getElementById('btnSaveQuote').classList.add('hidden');\r\n      document.getElementById('btnNewCalc').classList.add('hidden');\r\n      \r\n      document.getElementById('saveFeedback').innerText = \"\";\r\n      document.getElementById('btnSaveQuote').disabled = false;\r\n      document.getElementById('btnSaveQuote').innerText = \"Ment\u00e9s\";\r\n\r\n      \/\/ 2. Inputok t\u00f6rl\u00e9se\r\n      document.getElementById('clientName').value = \"\";\r\n      document.getElementById('clientEmail').value = \"\";\r\n      document.getElementById('inRectW').value = \"\";\r\n      document.getElementById('inRectH').value = \"\";\r\n      document.getElementById('inAreaTotal').value = \"\";\r\n      document.getElementById('calcArea').value = \"\";\r\n      document.getElementById('edgingLength').value = \"\";\r\n      \r\n      \/\/ 3. Dropdown\/Slider vissza\u00e1ll\u00edt\u00e1s\r\n      document.getElementById('stoneQuality').value = 2; window.updateStoneLabel();\r\n      document.getElementById('pavingBase').value = 'gravel';\r\n      document.getElementById('soilType').selectedIndex = 0;\r\n      document.getElementById('terrainType').selectedIndex = 0;\r\n      document.getElementById('extraEdging').checked = true; window.toggleEdgingInput(); \/\/ Alapb\u00f3l bepip\u00e1lva\r\n\r\n      \/\/ 4. Bels\u0151 \u00e1llapot t\u00f6rl\u00e9se\r\n      STATE.points = [];\r\n      STATE.finishedPolygons = [];\r\n      STATE.lastCalculatedData = null;\r\n      STATE.currentDocId = null; \/\/ Fontos: \u00faj ID gener\u00e1l\u00f3djon k\u00f6vi ment\u00e9skor\r\n      document.getElementById('polyCount').innerText = \"0\";\r\n      document.getElementById('polyAreaTotal').innerText = \"0\";\r\n\r\n      \/\/ 5. Canvas t\u00f6rl\u00e9se\r\n      const ctx = canvas.getContext('2d');\r\n      ctx.clearRect(0, 0, canvas.width, canvas.height);\r\n      window.requestRender();\r\n      \r\n      \/\/ Scroll vissza az elej\u00e9re (opcion\u00e1lis, de hasznos)\r\n      window.scrollTo({ top: 0, behavior: 'smooth' });\r\n  }\r\n\r\n  \/\/ --- H\u00c1TT\u00c9R MENT\u00c9S F\u00dcGGV\u00c9NY ---\r\n  async function backgroundSave() {\r\n    const nameInput = document.getElementById('clientName');\r\n    const emailInput = document.getElementById('clientEmail');\r\n    \r\n    STATE.lastCalculatedData.nev = nameInput.value;\r\n    STATE.lastCalculatedData.email = emailInput.value;\r\n    STATE.lastCalculatedData.kep = canvas.toDataURL(\"image\/png\");\r\n\r\n    if (!STATE.currentDocId) {\r\n        STATE.lastCalculatedData.status = \"kalkulacio_csak\"; \r\n        STATE.lastCalculatedData.kiemelt = false; \r\n        \r\n        try {\r\n            const docRef = await addDoc(collection(db, \"ajanlatok\"), STATE.lastCalculatedData);\r\n            STATE.currentDocId = docRef.id;\r\n            console.log(\"V\u00e1zlat mentve: \", docRef.id);\r\n        } catch (e) {\r\n            console.error(\"Hiba a h\u00e1tt\u00e9r ment\u00e9sn\u00e9l:\", e);\r\n        }\r\n    } else {\r\n        try {\r\n             const docRef = doc(db, \"ajanlatok\", STATE.currentDocId);\r\n             await updateDoc(docRef, STATE.lastCalculatedData);\r\n             console.log(\"V\u00e1zlat friss\u00edtve\");\r\n        } catch(e) { console.error(e); }\r\n    }\r\n  }\r\n\r\n  window.updateStoneLabel = function() {\r\n      const val = document.getElementById('stoneQuality').value;\r\n      const label = document.getElementById('stonePriceDisplay');\r\n      if(val == \"1\") label.innerHTML = 'Alap (~4500 Ft\/m\u00b2)';\r\n      else if(val == \"2\") label.innerHTML = '\u00c1tlagos (~7000 Ft\/m\u00b2)';\r\n      else if(val == \"3\") label.innerHTML = 'Pr\u00e9mium (~10000 Ft\/m\u00b2)';\r\n      \r\n      STATE.pavingCache = null; \r\n      requestRender();\r\n  }\r\n\r\n  window.toggleEdgingInput = function() {\r\n      const chk = document.getElementById('extraEdging');\r\n      const container = document.getElementById('edgingInputContainer');\r\n      if(chk.checked) {\r\n          container.classList.remove('hidden');\r\n          if(!document.getElementById('edgingLength').value) syncPerimeter();\r\n      } else {\r\n          container.classList.add('hidden');\r\n      }\r\n  }\r\n\r\n  function calculatePerimeter(points) {\r\n      if (points.length < 2) return 0;\r\n      let p = 0;\r\n      for (let i = 0; i < points.length - 1; i++) {\r\n          p += distM(points[i], points[i+1]);\r\n      }\r\n      p += distM(points[points.length-1], points[0]);\r\n      return p;\r\n  }\r\n\r\n  function syncPerimeter() {\r\n      let p = 0;\r\n      if (STATE.mode === 'rect') {\r\n         const w = parseFloat(document.getElementById('inRectW').value)||0;\r\n         const h = parseFloat(document.getElementById('inRectH').value)||0;\r\n         if(w && h) p = 2 * (w + h);\r\n      }\r\n      else if (STATE.mode === 'poly') {\r\n         STATE.finishedPolygons.forEach(poly => {\r\n             p += calculatePerimeter(poly);\r\n         });\r\n      }\r\n      else if (STATE.mode === 'area') {\r\n         const a = parseFloat(document.getElementById('inAreaTotal').value)||0;\r\n         if(a) p = 4 * Math.sqrt(a);\r\n      }\r\n\r\n      if(p > 0) {\r\n          document.getElementById('edgingLength').value = Math.round(p * 10) \/ 10;\r\n      }\r\n  }\r\n\r\n  window.toggleBaseInfo = function() {\r\n      const box = document.getElementById('baseInfoBox');\r\n      box.classList.toggle('hidden');\r\n  }\r\n\r\n  window.openHelp = function() { document.getElementById('helpModal').style.display = 'flex'; }\r\n  window.closeHelp = function() { document.getElementById('helpModal').style.display = 'none'; }\r\n  window.closeHelpOnOutside = function(e) { if(e.target.id === 'helpModal') window.closeHelp(); }\r\n\r\n  window.setMode = function(mode) {\r\n    STATE.mode = mode;\r\n    document.getElementById('inputsRect').classList.toggle('hidden', mode !== 'rect');\r\n    document.getElementById('inputsArea').classList.toggle('hidden', mode !== 'area');\r\n    document.getElementById('inputsPoly').classList.toggle('hidden', mode !== 'poly');\r\n    document.getElementById('polyToolbar').classList.toggle('hidden', mode !== 'poly');\r\n    document.getElementById('polyInstruction').classList.toggle('hidden', mode !== 'poly');\r\n    document.getElementById('multiPolyStats').classList.toggle('hidden', mode !== 'poly');\r\n    document.getElementById('btnDrawSimple').classList.toggle('hidden', mode === 'poly');\r\n    \r\n    STATE.points = []; \r\n    STATE.finishedPolygons = [];\r\n    STATE.pavingCache = null;\r\n    document.getElementById('polyCount').innerText = \"0\";\r\n    document.getElementById('polyAreaTotal').innerText = \"0\";\r\n    document.getElementById('calcArea').value = \"\";\r\n\r\n    ctx.clearRect(0,0,canvas.width, canvas.height);\r\n    if(mode === 'poly') window.updateScaleFromInput();\r\n    window.requestRender();\r\n  }\r\n\r\n  window.updatePavingSettings = function() {\r\n    STATE.pavingSettings.size = document.getElementById('pavingSize').value;\r\n    STATE.pavingSettings.pattern = document.getElementById('pavingPattern').value;\r\n    STATE.pavingCache = null;\r\n    window.requestRender();\r\n  }\r\n\r\n  window.drawSimpleShape = function() {\r\n    let w = 0, h = 0;\r\n    const msg = document.getElementById('visualMsg'); msg.style.display = 'none';\r\n    if (STATE.mode === 'rect') {\r\n        w = parseFloat(document.getElementById('inRectW').value);\r\n        h = parseFloat(document.getElementById('inRectH').value);\r\n    } else if (STATE.mode === 'area') {\r\n        const a = parseFloat(document.getElementById('inAreaTotal').value);\r\n        if (a > 0) { w = Math.sqrt(a); h = w; }\r\n    }\r\n    if (!w || !h || w<=0 || h<=0) { msg.textContent = \"K\u00e9rlek adj meg \u00e9rv\u00e9nyes sz\u00e1mokat!\"; msg.style.display = 'block'; return; }\r\n    \r\n    const maxDimM = Math.max(w, h);\r\n    const usablePx = Math.min(canvas.width, canvas.height) - (CONFIG.padding * 2);\r\n    STATE.pxPerMeter = usablePx \/ maxDimM;\r\n    const startX = (canvas.width \/ STATE.pxPerMeter - w) \/ 2;\r\n    const startY = (canvas.height \/ STATE.pxPerMeter - h) \/ 2;\r\n    STATE.finishedPolygons = [[{x: startX, y: startY}, {x: startX + w, y: startY}, {x: startX + w, y: startY + h}, {x: startX, y: startY + h}]];\r\n    STATE.points = [];\r\n    STATE.pavingCache = null;\r\n    window.requestRender(); \r\n    syncAreaToCalculator();\r\n    syncPerimeter(); \r\n  }\r\n\r\n  window.updateScaleFromInput = function() {\r\n    const maxWInput = parseFloat(document.getElementById('inPolyMaxW').value);\r\n    const maxW = (maxWInput && maxWInput > 0) ? maxWInput : 30;\r\n    STATE.pxPerMeter = (canvas.width - CONFIG.padding * 2) \/ maxW;\r\n    window.requestRender();\r\n  }\r\n\r\n  window.undoPoint = function() { \r\n      if (STATE.mode === 'poly') {\r\n          if (STATE.points.length > 0) { \r\n              STATE.points.pop(); \r\n          } \r\n          else if (STATE.finishedPolygons.length > 0) {\r\n              STATE.points = STATE.finishedPolygons.pop();\r\n              STATE.pavingCache = null; \r\n              syncAreaToCalculator();\r\n              syncPerimeter();\r\n          }\r\n          window.requestRender(); \r\n      } \r\n  }\r\n  \r\n  window.closePolygon = function() { \r\n    if (STATE.mode === 'poly' && STATE.points.length >= 3) { \r\n        STATE.finishedPolygons.push([...STATE.points]);\r\n        STATE.points = []; \r\n        STATE.pavingCache = null; \r\n        \r\n        window.requestRender(); \r\n        syncAreaToCalculator(); \r\n        syncPerimeter(); \r\n    } \r\n  }\r\n  \r\n  window.resetPoly = function() { \r\n      STATE.points = []; \r\n      STATE.finishedPolygons = []; \r\n      STATE.pavingCache = null; \r\n      window.requestRender(); \r\n      document.getElementById('calcArea').value = \"\"; \r\n      document.getElementById('edgingLength').value = \"\"; \r\n      document.getElementById('polyCount').innerText = \"0\";\r\n      document.getElementById('polyAreaTotal').innerText = \"0\";\r\n  }\r\n\r\n  window.requestRender = function() { window.requestAnimationFrame(render); }\r\n\r\n  \/\/ --- \u00c1TDOLGOZOTT KALKUL\u00c1CI\u00d3S F\u00dcGGV\u00c9NY ---\r\n  window.performCalculation = function() {\r\n    const name = document.getElementById('clientName').value;\r\n    const email = document.getElementById('clientEmail').value; \r\n    \r\n    const area = parseFloat(document.getElementById('calcArea').value);\r\n    \r\n    if (!area || area <= 0) return;\r\n\r\n    \/\/ --- 150m2 LIMIT ELLEN\u0150RZ\u00c9SE ---\r\n    if (area > 150) {\r\n        document.getElementById('calcResult').classList.remove('hidden'); \/\/ FONTOS: Megjelen\u00edtj\u00fck a dobozt!\r\n        document.getElementById('quoteIdDisplay').innerText = \"---\";\r\n        document.getElementById('priceRangeDisplay').innerText = \"Egyedi aj\u00e1nlat sz\u00fcks\u00e9ges\";\r\n        document.getElementById('calcDetails').innerHTML = `\r\n            Ter\u00fclet: ${area} m\u00b2<br>\r\n            <div style=\"margin-top:10px; color:#c53030; font-weight:500;\">\r\n                A ter\u00fclet nagys\u00e1ga miatt (150 m\u00b2 felett) ezt a munk\u00e1t csak szem\u00e9lyes felm\u00e9r\u00e9s ut\u00e1n v\u00e1llaljuk.\r\n            <\/div>\r\n            <div style=\"margin-top:15px;\">\r\n                Egyeztet\u00e9s\u00e9rt h\u00edvjon minket:<br>\r\n                <a href=\"tel:+36301446577\" style=\"display:inline-block; margin-top:5px; background:var(--primary); color:white; padding:10px 20px; border-radius:20px; text-decoration:none; font-weight:600; box-shadow:0 4px 6px rgba(0,0,0,0.1);\">\r\n                    \ud83d\udcde +36 30 144 6577\r\n                <\/a>\r\n            <\/div>\r\n        `;\r\n        \r\n        \/\/ Ment\u00e9s gomb elrejt\u00e9se, mivel nincs \u00e1r\r\n        document.getElementById('btnSaveQuote').classList.add('hidden');\r\n        document.getElementById('saveFeedback').innerText = \"\";\r\n        return;\r\n    }\r\n\r\n    const soilType = document.getElementById('soilType');\r\n    const terrainType = document.getElementById('terrainType');\r\n    const soilText = soilType.options[soilType.selectedIndex].text;\r\n    const terrainText = terrainType.options[terrainType.selectedIndex].text;\r\n\r\n    const extrasList = [];\r\n    const stoneVal = document.getElementById('stoneQuality').value;\r\n    \r\n    \/\/ T\u00e9rk\u0151 anyagk\u00f6lts\u00e9g (ez j\u00f6n r\u00e1 pluszban a s\u00e1vos \u00e1rra)\r\n    let stonePricePerSqm = 7000; \r\n    let stoneName = \"\u00c1tlagos\";\r\n    if(stoneVal == \"1\") { stonePricePerSqm = 4500; stoneName = \"Alap\"; }\r\n    if(stoneVal == \"3\") { stonePricePerSqm = 10000; stoneName = \"Pr\u00e9mium\"; }\r\n\r\n    \/\/ Alap t\u00edpusa (Pormurva vagy Beton)\r\n    const baseType = document.getElementById('pavingBase').value; \/\/ 'gravel' vagy 'concrete'\r\n    let displayWorkSuffix = \"\";\r\n    \r\n    if (baseType === 'concrete') {\r\n        displayWorkSuffix = ` (Beton alap, ${stoneName} k\u0151)`;\r\n    } else {\r\n        displayWorkSuffix = ` (Pormurva alap, ${stoneName} k\u0151)`;\r\n    }\r\n\r\n    \/\/ --- S\u00c1VOS \u00c1R KIKERES\u00c9SE ---\r\n    let constructionBasePrice = 0;\r\n    const selectedTiers = CONFIG.tiers[baseType];\r\n    \r\n    \/\/ Megkeress\u00fck a megfelel\u0151 s\u00e1vot\r\n    let matchedTier = null;\r\n    for (let tier of selectedTiers) {\r\n        if (area <= tier.max) {\r\n            matchedTier = tier;\r\n            break;\r\n        }\r\n    }\r\n    \r\n    if (matchedTier) {\r\n        constructionBasePrice = matchedTier.price;\r\n    } else {\r\n        \/\/ Ez elvileg nem fut le a fenti >150 ellen\u0151rz\u00e9s miatt, de biztons\u00e1gb\u00f3l:\r\n        const lastTier = selectedTiers[selectedTiers.length - 1];\r\n        const perSqmPrice = lastTier.price \/ lastTier.max; \r\n        constructionBasePrice = Math.round(area * perSqmPrice);\r\n    }\r\n\r\n    \/\/ --- V\u00c9GLEGES \u00c1R \u00d6SSZE\u00c1LL\u00cdT\u00c1SA ---\r\n    \/\/ 1. Alap \u00e9p\u00edt\u00e9si k\u00f6lts\u00e9g (s\u00e1vos \u00e1r)\r\n    let totalCalculated = constructionBasePrice;\r\n\r\n    \/\/ 2. T\u00e9rk\u0151 anyagk\u00f6lts\u00e9g hozz\u00e1ad\u00e1sa (a s\u00e1vos \u00e1r nem tartalmazza)\r\n    totalCalculated += (area * stonePricePerSqm);\r\n\r\n    \/\/ 3. Szeg\u00e9lyez\u00e9s hozz\u00e1ad\u00e1sa\r\n    if (document.getElementById('extraEdging').checked) {\r\n        const len = parseFloat(document.getElementById('edgingLength').value);\r\n        if(!len || len <= 0) {\r\n            alert(\"A szeg\u00e9lyez\u00e9s be van pip\u00e1lva, de nincs megadva hossz!\");\r\n            return;\r\n        }\r\n        \r\n        let edgingPrice = 0;\r\n        if(len <= 10) {\r\n            edgingPrice = len * CONFIG.prices.edgingLowQty; \/\/ 7500 Ft\r\n        } else {\r\n            edgingPrice = len * CONFIG.prices.edgingHighQty; \/\/ 6500 Ft\r\n        }\r\n        \r\n        totalCalculated += edgingPrice;\r\n        extrasList.push(`Szeg\u00e9lyez\u00e9s (${len} m)`);\r\n    }\r\n\r\n    \/\/ --- CSAK EGY V\u00c9GLEGES \u00d6SSZEG (nincs intervallum) ---\r\n    const finalPrice = Math.round(totalCalculated);\r\n    \r\n    const quoteId = \"AJ-\" + Date.now().toString().slice(-6) + Math.floor(Math.random() * 99);\r\n    const formatter = new Intl.NumberFormat('hu-HU', { style: 'currency', currency: 'HUF', maximumFractionDigits: 0 });\r\n    \r\n    const displayWorkType = 'T\u00e9rk\u00f6vez\u00e9s' + displayWorkSuffix;\r\n\r\n    document.getElementById('quoteIdDisplay').innerText = quoteId;\r\n    document.getElementById('priceRangeDisplay').innerText = formatter.format(finalPrice);\r\n    document.getElementById('calcDetails').innerHTML = `Ter\u00fclet: ${area} m\u00b2<br>${displayWorkType}`;\r\n    document.getElementById('calcResult').classList.remove('hidden'); \/\/ Biztos ami biztos\r\n    \r\n    STATE.lastCalculatedData = {\r\n        azonosito: quoteId,\r\n        nev: name,\r\n        email: email, \r\n        datum: new Date().toISOString(),\r\n        terulet: area,\r\n        munkaTipus: displayWorkType,\r\n        talaj: soilText,\r\n        terep: terrainText,\r\n        extrak: extrasList,\r\n        becsultAr: finalPrice,\r\n        becsultArFormazott: formatter.format(finalPrice)\r\n    };\r\n  }\r\n\r\n  \/\/ --- V\u00c9GLEGES MENT\u00c9S \u00c9S EMAIL K\u00dcLD\u00c9S ---\r\n  window.saveToFirebase = async function() {\r\n    if (!STATE.lastCalculatedData) { alert(\"El\u0151bb v\u00e9gezzen kalkul\u00e1ci\u00f3t!\"); return; }\r\n    \r\n    STATE.lastCalculatedData.status = \"uj_ugyfel\";\r\n    STATE.lastCalculatedData.kiemelt = true; \/\/ Piros lesz az adminban!\r\n\r\n    const btn = document.getElementById('btnSaveQuote');\r\n    const feedback = document.getElementById('saveFeedback');\r\n    \r\n    btn.disabled = true;\r\n    btn.innerText = \"K\u00fcld\u00e9s...\";\r\n\r\n    try {\r\n        if (STATE.currentDocId) {\r\n            const docRef = doc(db, \"ajanlatok\", STATE.currentDocId);\r\n            await updateDoc(docRef, {\r\n                status: \"uj_ugyfel\",\r\n                kiemelt: true,\r\n                nev: document.getElementById('clientName').value, \r\n                email: document.getElementById('clientEmail').value\r\n            });\r\n        } else {\r\n            \/\/ Fallback, ha valami\u00e9rt nem volt v\u00e1zlat\r\n            const docRef = await addDoc(collection(db, \"ajanlatok\"), STATE.lastCalculatedData);\r\n            STATE.currentDocId = docRef.id;\r\n        }\r\n\r\n        const emailContent = `\r\n            <h2>Kedves ${STATE.lastCalculatedData.nev}!<\/h2>\r\n            <p>K\u00f6sz\u00f6nj\u00fck \u00e9rdekl\u0151d\u00e9s\u00e9t a Green Garden Budapest szolg\u00e1ltat\u00e1sai ir\u00e1nt.<\/p>\r\n            <p>Az \u00d6n \u00e1ltal k\u00e9sz\u00edtett el\u0151zetes kalkul\u00e1ci\u00f3 adatai:<\/p>\r\n            <ul>\r\n                <li><strong>Azonos\u00edt\u00f3:<\/strong> ${STATE.lastCalculatedData.azonosito}<\/li>\r\n                <li><strong>Kalkul\u00e1lt ter\u00fclet:<\/strong> ${STATE.lastCalculatedData.terulet} m\u00b2<\/li>\r\n                <li><strong>Munkat\u00edpus:<\/strong> ${STATE.lastCalculatedData.munkaTipus}<\/li>\r\n                <li><strong>Helysz\u00edni adotts\u00e1gok:<\/strong> ${STATE.lastCalculatedData.talaj}, ${STATE.lastCalculatedData.terep}<\/li>\r\n                <li><strong>V\u00e1lasztott extr\u00e1k:<\/strong> ${STATE.lastCalculatedData.extrak.length > 0 ? STATE.lastCalculatedData.extrak.join(', ') : 'Nincs'}<\/li>\r\n                <li><strong>Becs\u00fclt \u00e1r:<\/strong> ${STATE.lastCalculatedData.becsultArFormazott}<\/li>\r\n            <\/ul>\r\n            <p><strong>Megjegyz\u00e9s a munk\u00e1latokr\u00f3l:<\/strong><br>\r\n            Az \u00e1r tartalmazza a f\u00f6ldmunk\u00e1t. A megl\u00e9v\u0151 beton felt\u00f6r\u00e9s\u00e9t \u00e9s elsz\u00e1ll\u00edt\u00e1s\u00e1t nem tartalmazza, ez minden esetben fel\u00e1r ellen\u00e9ben t\u00f6rt\u00e9nik.<\/p>\r\n            <p><strong>\u26a0\ufe0f Fontos:<\/strong> Ez az email nem min\u0151s\u00fcl hivatalos aj\u00e1nlatt\u00e9telnek. Munkat\u00e1rsunk hamarosan felveszi \u00d6nnel a kapcsolatot a pontos r\u00e9szletek egyeztet\u00e9se v\u00e9gett.<\/p>\r\n            <br>\r\n            <p>\u00dcdv\u00f6zlettel,<br>Green Garden Budapest Csapata \ud83c\udf3f<\/p>\r\n        `;\r\n\r\n        await addDoc(collection(db, \"mail\"), {\r\n            to: [STATE.lastCalculatedData.email],\r\n            message: {\r\n                subject: `\u00c1raj\u00e1nlat Kalkul\u00e1ci\u00f3: ${STATE.lastCalculatedData.azonosito}`,\r\n                html: emailContent\r\n            }\r\n        });\r\n\r\n        btn.innerText = \"\u2713 Elk\u00fcldve\";\r\n        btn.style.background = \"#27ae60\";\r\n        feedback.innerText = \"Sikeres ment\u00e9s! Koll\u00e9g\u00e1ink keresni fogj\u00e1k.\";\r\n        feedback.style.color = \"#27ae60\";\r\n\r\n    } catch (e) {\r\n        console.error(\"Hiba: \", e);\r\n        alert(\"Hiba t\u00f6rt\u00e9nt. K\u00e9rj\u00fck pr\u00f3b\u00e1lja \u00fajra k\u00e9s\u0151bb.\");\r\n        btn.disabled = false;\r\n        btn.innerText = \"\u00dajrapr\u00f3b\u00e1l\u00e1s\";\r\n    }\r\n  }\r\n\r\n  function syncAreaToCalculator() {\r\n    let area = 0;\r\n    if (STATE.mode === 'rect') { area = (parseFloat(document.getElementById('inRectW').value)||0) * (parseFloat(document.getElementById('inRectH').value)||0); }\r\n    else if (STATE.mode === 'area') { area = parseFloat(document.getElementById('inAreaTotal').value)||0; }\r\n    else if (STATE.mode === 'poly') { \r\n        STATE.finishedPolygons.forEach(poly => {\r\n            area += calculatePolygonArea(poly);\r\n        });\r\n    }\r\n\r\n    if (area > 0) {\r\n        const roundedArea = Math.round(area * 100) \/ 100;\r\n        document.getElementById('calcArea').value = roundedArea;\r\n        document.getElementById('polyCount').innerText = STATE.finishedPolygons.length;\r\n        document.getElementById('polyAreaTotal').innerText = roundedArea;\r\n    }\r\n  }\r\n  \r\n  function calculatePolygonArea(points) {\r\n    if (points.length < 3) return 0; let area = 0;\r\n    for (let i = 0; i < points.length; i++) {\r\n        let j = (i + 1) % points.length; area += points[i].x * points[j].y; area -= points[j].x * points[i].y;\r\n    } return Math.abs(area \/ 2);\r\n  }\r\n\r\n  function render() {\r\n    ctx.fillStyle = '#2c3e50'; \r\n    ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n    drawGridAndRulers();\r\n    \r\n    if (STATE.finishedPolygons.length > 0) {\r\n        ctx.save();\r\n        ctx.beginPath();\r\n        STATE.finishedPolygons.forEach(poly => {\r\n             const p0 = mToPx(poly[0]); \r\n             ctx.moveTo(p0.x, p0.y);\r\n             for (let i = 1; i < poly.length; i++) { const p = mToPx(poly[i]); ctx.lineTo(p.x, p.y); }\r\n             ctx.closePath();\r\n        });\r\n        ctx.clip(); \r\n        drawWorkTexture(); \r\n        ctx.restore();\r\n\r\n        STATE.finishedPolygons.forEach(poly => {\r\n            ctx.beginPath();\r\n            const p0 = mToPx(poly[0]); ctx.moveTo(p0.x, p0.y);\r\n            for (let i = 1; i < poly.length; i++) { const p = mToPx(poly[i]); ctx.lineTo(p.x, p.y); }\r\n            ctx.closePath();\r\n            ctx.strokeStyle = CONFIG.lineColor; ctx.lineWidth = 2; ctx.stroke();\r\n            \r\n            ctx.fillStyle = '#fff'; \r\n            poly.forEach(pt => { const px = mToPx(pt); ctx.beginPath(); ctx.arc(px.x, px.y, 3, 0, Math.PI*2); ctx.fill(); });\r\n        });\r\n    }\r\n\r\n    if (STATE.points.length > 0) {\r\n        ctx.beginPath();\r\n        const p0 = mToPx(STATE.points[0]); ctx.moveTo(p0.x, p0.y);\r\n        for (let i = 1; i < STATE.points.length; i++) { const p = mToPx(STATE.points[i]); ctx.lineTo(p.x, p.y); }\r\n        ctx.lineTo(STATE.mouseX, STATE.mouseY);\r\n        ctx.strokeStyle = '#f1c40f'; ctx.lineWidth = 1; ctx.stroke();\r\n        \r\n        ctx.fillStyle = '#f1c40f'; \r\n        STATE.points.forEach(pt => { const px = mToPx(pt); ctx.beginPath(); ctx.arc(px.x, px.y, 3, 0, Math.PI*2); ctx.fill(); });\r\n    }\r\n\r\n    if (document.getElementById('chkShowLengths').checked || STATE.mode !== 'poly') drawDimensions();\r\n  }\r\n  \r\n  function drawGridAndRulers(){\r\n      const w=canvas.width,h=canvas.height,ppm=STATE.pxPerMeter,pad=CONFIG.padding;\r\n      ctx.strokeStyle='#34495e'; \r\n      ctx.lineWidth=1;\r\n      ctx.beginPath();\r\n      ctx.fillStyle='#95a5a6';\r\n      ctx.font='10px sans-serif';\r\n      ctx.textAlign='center';\r\n      const maxM_X=(w-pad)\/ppm,maxM_Y=(h-pad)\/ppm;\r\n      for(let m=0;m<=maxM_X;m++){\r\n          const x=pad+m*ppm,isMajor=(m%5===0),tickH=isMajor?10:5;\r\n          ctx.moveTo(x,0);ctx.lineTo(x,tickH);\r\n          if(isMajor){ctx.fillText(m,x,tickH+10);ctx.moveTo(x,pad);ctx.lineTo(x,h)}\r\n      }\r\n      for(let m=0;m<=maxM_Y;m++){\r\n          const y=pad+m*ppm,isMajor=(m%5===0),tickW=isMajor?10:5;\r\n          ctx.moveTo(0,y);ctx.lineTo(tickW,y);\r\n          if(isMajor){ctx.fillText(m,tickW+12,y+3);ctx.moveTo(pad,y);ctx.lineTo(w,y)}\r\n      }\r\n      ctx.stroke();\r\n  }\r\n  \r\n  function drawWorkTexture(){\r\n      if(STATE.pavingCache){ctx.drawImage(STATE.pavingCache,0,0);return}\r\n      const o=document.createElement('canvas');o.width=canvas.width;o.height=canvas.height;drawPavingPattern(o.getContext('2d'),canvas.width,canvas.height);STATE.pavingCache=o;ctx.drawImage(o,0,0);\r\n  }\r\n  \r\n  function drawPavingPattern(t,w,h){\r\n      const quality = document.getElementById('stoneQuality').value;\r\n      const qVal = parseInt(quality);\r\n      let palette = [];\r\n      let baseColor = '';\r\n\r\n      if (qVal === 1) { \r\n          baseColor = '#7f8c8d';\r\n          palette = ['#bdc3c7', '#95a5a6', '#7f8c8d', '#ecf0f1'];\r\n      } else if (qVal === 2) { \r\n          baseColor = '#8d6e63'; \r\n          palette = ['#d7ccc8', '#a1887f', '#bcaaa4', '#8d6e63']; \r\n      } else { \r\n          baseColor = '#455a64';\r\n          palette = ['#cfd8dc', '#b0bec5', '#90a4ae', '#78909c'];\r\n      }\r\n      \r\n      t.fillStyle = baseColor;\r\n      t.fillRect(0, 0, w, h);\r\n\r\n      const s = STATE.pavingSettings.size;\r\n      const p = STATE.pavingSettings.pattern;\r\n      const gc = () => palette[Math.floor(Math.random() * palette.length)];\r\n\r\n      let b = 25; if (s === 'small') b = 15; if (s === 'large') b = 45;\r\n      const g = 2; \r\n\r\n      const drawStone = (ctx, x, y, width, height) => {\r\n          ctx.fillStyle = gc();\r\n          ctx.fillRect(x, y, width, height);\r\n          ctx.strokeStyle = 'rgba(0,0,0,0.1)'; ctx.strokeRect(x,y,width,height);\r\n      };\r\n\r\n      if (s === 'mixed') {\r\n          const c = 40;\r\n          for (let y = 0; y < h; y += c) for (let x = 0; x < w; x += c) {\r\n              const type = Math.random();\r\n              if (type < .4) { drawStone(t, x, y, c - g, c - g); } \r\n              else if (type < .7) { drawStone(t, x, y, c - g, c \/ 2 - g); drawStone(t, x, y + c \/ 2, c - g, c \/ 2 - g); } \r\n              else { drawStone(t, x, y, c \/ 2 - g, c - g); drawStone(t, x + c \/ 2, y, c \/ 2 - g, c - g); }\r\n          }\r\n      } else {\r\n          for (let y = 0; y < h; y += b) for (let x = 0; x < w; x += b) {\r\n              let dx = x; if (p === 'asym' && Math.floor(y \/ b) % 2 !== 0) dx -= b \/ 2;\r\n              drawStone(t, dx, y, b - g, b - g);\r\n          }\r\n      }\r\n  }\r\n  \r\n  function drawDimensions(){\r\n      ctx.font='12px sans-serif';ctx.textAlign='center';ctx.textBaseline='middle';\r\n      const used=[];\r\n      STATE.finishedPolygons.forEach(poly => {\r\n           for(let i=0;i<poly.length;i++) {\r\n               drawEdgeLabel(poly[i], poly[(i+1)%poly.length], used);\r\n           }\r\n      });\r\n      const l = STATE.points.length;\r\n      if (l > 0) {\r\n          for(let i=0;i<l-1;i++) {\r\n              drawEdgeLabel(STATE.points[i], STATE.points[i+1], used);\r\n          }\r\n          const lp=mToPx(STATE.points[l-1]); const mp={x:STATE.mouseX,y:STATE.mouseY};\r\n          const d=Math.sqrt(Math.pow((mp.x-lp.x)\/STATE.pxPerMeter,2)+Math.pow((mp.y-lp.y)\/STATE.pxPerMeter,2));\r\n          const t=d.toFixed(2)+'m'; \r\n          ctx.fillStyle='rgba(241, 196, 15, 0.9)'; ctx.fillText(t, (lp.x+mp.x)\/2, (lp.y+mp.y)\/2 - 10);\r\n      }\r\n  }\r\n\r\n  function drawEdgeLabel(pt1, pt2, used) {\r\n      const p1 = mToPx(pt1); const p2 = mToPx(pt2);\r\n      const len = distM(pt1, pt2);\r\n      const t=len.toFixed(2)+'m'; const m=ctx.measureText(t); const w=m.width+8, h=20;\r\n      const mx=(p1.x+p2.x)\/2; const my=(p1.y+p2.y)\/2;\r\n      let pl=false; let bx=mx, by=my;\r\n      const dx=p2.x-p1.x, dy=p2.y-p1.y; const ln=Math.sqrt(dx*dx+dy*dy);\r\n      const nx=-dy\/ln, ny=dx\/ln; const os=[0,15,-15,25,-25];\r\n      for(let o of os){ const cx=mx+nx*o, cy=my+ny*o; const r={x:cx-w\/2,y:cy-h\/2,w:w,h:h}; if(!checkCollision(r,used)){bx=cx;by=cy;used.push(r);pl=true;break} }\r\n      if(!pl)used.push({x:mx-w\/2,y:my-h\/2,w:w,h:h});\r\n      \r\n      ctx.fillStyle='rgba(255,255,255,0.9)';ctx.beginPath();ctx.roundRect(bx-w\/2,by-h\/2,w,h,4);ctx.fill();\r\n      ctx.fillStyle='#000';ctx.fillText(t,bx,by)\r\n  }\r\n  \r\n  function checkCollision(r1,rs){for(let r2 of rs)if(r1.x<r2.x+r2.w&&r1.x+r1.w>r2.x&&r1.y<r2.y+r2.h&&r1.h+r1.y>r2.y)return true;return false}\r\n  function mToPx(pt){return{x:CONFIG.padding+pt.x*STATE.pxPerMeter,y:CONFIG.padding+pt.y*STATE.pxPerMeter}}\r\n  function distM(p1,p2){return Math.sqrt(Math.pow(p2.x-p1.x,2)+Math.pow(p2.y-p1.y,2))}\r\n\r\n  window.onload = function() {\r\n    const wrapper = document.querySelector('.canvas-wrapper');\r\n    canvas.width = wrapper.clientWidth; canvas.height = wrapper.clientHeight;\r\n    window.addEventListener('resize', ()=>{canvas.width=wrapper.clientWidth;canvas.height=wrapper.clientHeight;if(STATE.mode==='poly')window.updateScaleFromInput();window.requestRender()});\r\n    canvas.addEventListener('mousedown', (e)=>{if(STATE.mode!=='poly')return;const r=canvas.getBoundingClientRect();STATE.points.push({x:(e.clientX-r.left-CONFIG.padding)\/STATE.pxPerMeter,y:(e.clientY-r.top-CONFIG.padding)\/STATE.pxPerMeter});window.requestRender()});\r\n    canvas.addEventListener('mousemove', (e)=>{if(STATE.mode==='poly'){const r=canvas.getBoundingClientRect();STATE.mouseX=e.clientX-r.left;STATE.mouseY=e.clientY-r.top;window.requestRender()}});\r\n    canvas.addEventListener('dblclick', window.closePolygon);\r\n    window.setMode('rect'); window.updateScaleFromInput();\r\n  }\r\n<\/script>\r\n<\/body>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>Price calculator Home Price calculator Green Garden Budapest Below you will find our latest in-house price calculator, which will also include other landscaping work from spring onwards. Paving stone price calculator \u2013 Dark Mode Paving stone price calculator Plan your costs in advance! Enter the dimensions, select the materials, and get an instant estimate. \u2600\ufe0f 1 Enter area Rectangle (m) Area (m\u00b2) Freehand drawing Width [\u2026]<\/p>","protected":false},"author":4,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"footnotes":""},"class_list":["post-2842","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/greengardenbudapest.hu\/en\/wp-json\/wp\/v2\/pages\/2842","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/greengardenbudapest.hu\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/greengardenbudapest.hu\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/greengardenbudapest.hu\/en\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/greengardenbudapest.hu\/en\/wp-json\/wp\/v2\/comments?post=2842"}],"version-history":[{"count":86,"href":"https:\/\/greengardenbudapest.hu\/en\/wp-json\/wp\/v2\/pages\/2842\/revisions"}],"predecessor-version":[{"id":2956,"href":"https:\/\/greengardenbudapest.hu\/en\/wp-json\/wp\/v2\/pages\/2842\/revisions\/2956"}],"wp:attachment":[{"href":"https:\/\/greengardenbudapest.hu\/en\/wp-json\/wp\/v2\/media?parent=2842"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}