{
  "model": "gemini-3.1-pro-preview",
  "endpoint": "v1beta/models/gemini-3.1-pro-preview:generateContent",
  "body": {
    "systemInstruction": {
      "parts": [
        {
          "text": "You are an expert mobile landing-page designer and frontend implementer. Treat supplied source documents as source material. Follow the exact current task brief and return a complete actual HTML implementation with all finalized Hungarian copy, media refs, frontend behavior, and no unsupported claims."
        }
      ]
    },
    "contents": [
      {
        "role": "user",
        "parts": [
          {
            "text": "Create one complete polished standalone HTML landing page now. This is real production authoring, not a snippet or JSON plan. Return only <!doctype html> through </html>, no markdown fence. You are Gemini3.1Pro authoring the complete first implementation. We may then integrate or fix it locally, preserving your generation receipt.\n\nAudience: Hungarian adults who want practical, natural, easier-to-follow speech. All customer copy must be natural Hungarian, no em dash and no semicolon in rendered customer text. Established Komplex visual identity MUST be preserved. It is not an aesthetic tournament. Use the provided real logo and, only where specified, actual Rita photo. Do not fake Rita with illustrations.\n\nOutput includes full inline CSS and necessary inline JS. No framework/build requirement, no backend, API, auth, email, Stripe integration, security layer or external form submission. No tracking. All main CTA links use the EXACT provided destination. Use semantic HTML and data-template-layout=\"Sx\" on EVERY mapped section including header/footer. Preserve the actual supplied layout anatomy for the assigned S layouts: an adaptation may change neutral colours, scales and mobile behavior, but it must retain the recognizable composition, not turn everything into identical cards. Every section has a distinct reader job. NO placeholders and no fabricated testimonials/proof/guarantees. No unsupported ratings, counts of cases, years of experience, fake urgency or therapeutic claims. Do not create additional customer claims.\n\nMOBILE ONLY: customer page max-width:430px; margin:auto; valid at360/390/430 CSS px. No desktop customer design. Main body text >=17px, generous line-height, h1 about32–36px balanced, paragraph measure appropriate for the mobile column. Strong focus rings, all relevant buttons >=48px height, native labelled radio controls and expandable details, no horizontal page overflow, no clipping long Hungarian words. Page can be long because it contains full useful copy, but it must have clean section rhythm and simple navigation. Sticky controls must never cover content. No decorative kicker/eyebrow above headings. Native buttons/links say what happens. Use Quicksand body and Nunito Sans headings via supplied actual font-face URLs. No emoji icon stand-ins. Use simple authored consistent SVG icons if needed. Pink/orange/blue brand accents with legible dark text. Preserve organic source image style and compact8px buttons. No gradient text, no unnecessary blur or glass, no repeating background grids. Defaults fully visible, optional reveal disabled for reduced motion.\n\nALL PROVIDED COPY below is finalized pre-generation copy. Preserve the title, every paragraph, every list item/module name/day range/note without removing or summarizing it. The brief's full text belongs on the page, in reading order. Structural labels such as layout IDs/angle/testing hypothesis belong in DOM attributes or comments, never on the customer screen. A/B angle is not customer text. Section titles can be exact h1/h2/h3. S1 is a compact honest demo statement, not a giant hero. S2 is logo+compact jump navigation. A main CTA must appear in first viewport and repeat at appropriate points, ALWAYS matching provided destination. The CTA can include note as normal readable text. All sample/proposed states remain honest.\n\nMedia references: use src=\"../assets/landing/landing-01.png\" etc with actual index specified by each section. All assigned media must be visibly used. The seven media are generated illustrations, not participant results. Use object-fit:contain and natural ratio, never stretch or crop essential infographic text. Real logo/portrait is remote verified incumbent media. Do not invent extra imageURLs or fallback illustrations. All images alt use an honest description of their illustrative role. Do not claim that they depict the exact user's anatomy or personal outcome. Gallery images can open into a native dialog full readable preview, close control, Escape and focus restore. Galleries are touch-scrollable with working previous/next buttons and no autoplay. S17 topic cards are explicitly NOT testimonials. S22 scope cards are NOT guarantees. S27 content-strip is NOT certificates.\n\nFor sections with choices: implement labelled radio options. Selecting shows the chosen context and the provided summary, saves only under localStorage key 'kl-landing-'+pageID, restores on reload, announces the local saved status, and gives remove/reset. Say no data is sent. Native radio selections must be distinguishable from empty. No inference or diagnosis from choice. Maintain the exact CTA destination without silently changing variant. For expandable FAQs/modules all text is present in DOM, labels visible, first module can start open. Mobile nav must link to provided real anchors. Footer has link ../index.html labelled 'A teljes bemutató', and links to counterpart variant only for reviewer using a compact clearly labelled 'Másik oldalváltozat' line after customer footer. This page IS a frontend review prototype so a compact review link is acceptable.\n\nExact finalized common truth and tokens:\n{\n  \"brand\": \"Komplex Logopédia\",\n  \"logo\": \"https://cdn.prod.website-files.com/670786dbc9081bdd565d8269/67975fd0d0779b2f916fd821_da534f0d86b3659208073fbf705d036c_new-logo.avif\",\n  \"rita_photo\": \"https://cdn.prod.website-files.com/670786dbc9081bdd565d8269/68bacbde6c31fb17408b8d03_rita04.avif\",\n  \"tokens\": {\n    \"blue\": \"#008AE6\",\n    \"pink\": \"#e14f9b\",\n    \"orange\": \"#fea500\",\n    \"ink\": \"#17394a\",\n    \"paper\": \"#ffffff\",\n    \"pale_blue\": \"#eef8ff\",\n    \"pale_pink\": \"#fff2f7\",\n    \"body\": \"Quicksand\",\n    \"heading\": \"Nunito Sans\",\n    \"button_radius\": \"8px\",\n    \"button_min_height\": \"48px\"\n  },\n  \"truth\": \"Frontend bemutató. Nem történik feltöltés, jelentkezés vagy fizetés.\",\n  \"price\": \"24 900 Ft\",\n  \"pilot\": \"Javasolt első csoport: 12 résztvevő. Az ár, az indulás és a helyek száma egyeztetés alatt áll.\",\n  \"offer\": \"14 nap gyakorlás, napi videós feladat és napi személyes visszajelzés Ritától, majd online konzultáció.\",\n  \"duration\": \"Az első öt témánál körülbelül 20 percet, a 11–14. napi összetett feladatoknál körülbelül 30 percet szánj egy gyakorlásra. A videó és a napló további időt igényelhet.\",\n  \"schedule\": \"A napi felület Rita hat eredeti modulját bontja 14 napra. Ez a napi beosztás és a mindennapos visszajelzés a pilot javasolt formája.\",\n  \"module_titles\": [\n    [\n      \"1–2. nap\",\n      \"A légzés\",\n      \"Megfigyeled és gyakorolod, hogyan használod a levegőt beszéd közben.\"\n    ],\n    [\n      \"3–4. nap\",\n      \"Milyen ügyes a nyelved és az ajkaid?\",\n      \"Tükör előtt gyakorolsz, és a pontosabb artikulációhoz szükséges mozgásokra figyelsz.\"\n    ],\n    [\n      \"5–6. nap\",\n      \"Hangadás és rezonancia\",\n      \"Hangzókkal és szótagokkal figyeled a könnyed hangadást és a rezonanciát.\"\n    ],\n    [\n      \"7–8. nap\",\n      \"A beszéd és a ritmus\",\n      \"Szavakkal és versekkel dolgozol a hosszú és rövid szótagokon.\"\n    ],\n    [\n      \"9–10. nap\",\n      \"Komplex légzőgyakorlatok\",\n      \"Összekapcsolod a levegőbeosztást, a hangadást és a mozgást.\"\n    ],\n    [\n      \"11–14. nap\",\n      \"Integráció\",\n      \"Az addig gyakorolt elemeket közös beszédfeladatokban használod.\"\n    ]\n  ]\n}\n\nExact page copy, sections, layout IDs and destinations:\n{\n  \"offer\": \"free\",\n  \"angle\": \"Bizonytalanság a gyakorlási fókuszról → saját helyzet kiválasztása → személyes támpont\",\n  \"title\": \"Ingyenes visszajelzés, hogy tudd, mire figyelj\",\n  \"cta\": \"Kérem a személyes visszajelzést\",\n  \"destination\": \"../flow/free-upload.html?variant=free-b\",\n  \"sections\": [\n    {\n      \"layout\": \"S1\",\n      \"title\": \"A visszajelzés útját mutatjuk meg\",\n      \"paragraphs\": [\n        \"Frontend bemutató. A videóválasztás helyben történik, valódi visszajelzést most nem küldünk.\"\n      ],\n      \"items\": [],\n      \"media\": []\n    },\n    {\n      \"layout\": \"S2\",\n      \"title\": \"Komplex Logopédia\",\n      \"paragraphs\": [],\n      \"items\": [],\n      \"media\": [],\n      \"nav\": [\n        [\n          \"Kiindulópont\",\n          \"#helyzet\"\n        ],\n        [\n          \"Visszajelzés\",\n          \"#visszajelzes\"\n        ],\n        [\n          \"Kérdések\",\n          \"#kerdesek\"\n        ]\n      ]\n    },\n    {\n      \"layout\": \"S3\",\n      \"title\": \"Szeretnél érthetőbben beszélni, de nem tudod, mire figyelj?\",\n      \"paragraphs\": [\n        \"Egy rövid, spontán videó alapján személyes visszajelzést kapsz a beszédedről. Így konkrét szempontból indulhatsz, amikor legközelebb gyakorolsz.\",\n        \"Ez az ingyenes első lépés felnőtteknek szól. Nem kell előre eldöntened, hogy szeretnél-e programhoz csatlakozni.\"\n      ],\n      \"items\": [],\n      \"media\": [\n        2\n      ],\n      \"secondary\": \"Megnézem a visszajelzés menetét\",\n      \"secondary_href\": \"#visszajelzes\"\n    },\n    {\n      \"layout\": \"S5\",\n      \"title\": \"Melyik helyzetben szeretnél könnyebben megszólalni?\",\n      \"paragraphs\": [\n        \"Válassz egy ismerős helyzetet. A választás segít megfogalmazni, miért kéred a visszajelzést. Nem értékeljük és nem küldjük el.\"\n      ],\n      \"items\": [],\n      \"media\": [],\n      \"choices\": [\n        \"Hétköznapi beszélgetésben\",\n        \"Telefonon vagy online\",\n        \"Munkahelyi megszólalásnál\",\n        \"Felvételen vagy felolvasásnál\"\n      ],\n      \"choice_prompt\": \"A kiválasztott helyzet\",\n      \"choice_summary\": \"A videón beszélj természetesen. A választott helyzetet a valódi visszajelzésnél külön is jelezheted.\",\n      \"anchor\": \"helyzet\"\n    },\n    {\n      \"layout\": \"S7\",\n      \"title\": \"A saját felvételedből indulunk ki\",\n      \"paragraphs\": [\n        \"Amikor visszahallgatod magad, több mindent észrevehetsz. Mégis nehéz lehet eldöntened, mi okozza azt, amit hallasz, és mire fordítsd a figyelmedet.\",\n        \"Rita személyes visszajelzése ebben adhat külső nézőpontot. A látott videón megfigyelt jelenséget és egy következő gyakorlási szempontot kapcsol össze.\"\n      ],\n      \"items\": [\n        [\n          \"Előbb videó\",\n          \"Spontán beszéd, világos felvétel, szemmagasságban lévő kamera.\"\n        ],\n        [\n          \"Utána visszajelzés\",\n          \"Konkrét szempont a felvételről, nem általános beszédtippek listája.\"\n        ],\n        [\n          \"Végül döntés\",\n          \"Te mérlegeled, hogyan folytatod.\"\n        ]\n      ],\n      \"media\": [\n        1,\n        3\n      ],\n      \"anchor\": \"visszajelzes\"\n    },\n    {\n      \"layout\": \"S24\",\n      \"title\": \"Másra jó visszahallgatni, és másra külső nézőpontot kérni\",\n      \"paragraphs\": [],\n      \"items\": [\n        [\n          \"Ha magad hallgatod vissza\",\n          \"Felfigyelsz egy szóra, tempóra vagy érzésre. Önállóan megfigyelheted, mikor fordul elő.\"\n        ],\n        [\n          \"Ha személyes visszajelzést kérsz\",\n          \"Rita a felvételen látott beszédtechnikai szempontot fogalmazza meg, és segít kijelölni, mire figyelj következőként.\"\n        ]\n      ],\n      \"media\": [],\n      \"comparison\": true\n    },\n    {\n      \"layout\": \"S17\",\n      \"title\": \"Ilyen szempontok kerülhetnek elő\",\n      \"paragraphs\": [\n        \"Az alábbiak témák, nem résztvevői vélemények és nem a te videód értékelése. A valódi visszajelzés abból indul ki, ami a felvételén megfigyelhető.\"\n      ],\n      \"items\": [\n        [\n          \"Levegőbeosztás\",\n          \"Hol tudod könnyedén végigmondani a mondatot, és hol van szükség szünetre?\"\n        ],\n        [\n          \"Artikuláció\",\n          \"Mennyire követhetők a hangzók és a szóvégek a felvételen?\"\n        ],\n        [\n          \"Ritmus\",\n          \"Hogyan váltakoznak a rövid és hosszú szótagok, és mennyire követhető a tempó?\"\n        ]\n      ],\n      \"media\": [],\n      \"slider\": true\n    },\n    {\n      \"layout\": \"S9\",\n      \"title\": \"Nem előadást kérünk, hanem egy természetes megszólalást\",\n      \"paragraphs\": [\n        \"Legfeljebb egy percben beszélj valamiről, amiről szívesen mesélsz. Ne gyakorold be és ne vedd fel újra csak azért, hogy tökéletes legyen.\",\n        \"A szemmagasságba helyezett kamera, a világos arc és a mellkasig látható kép segít, hogy Rita megfigyelhesse a beszédedet.\"\n      ],\n      \"items\": [],\n      \"media\": [\n        1\n      ]\n    },\n    {\n      \"layout\": \"S15\",\n      \"title\": \"Mielőtt videót választasz\",\n      \"paragraphs\": [],\n      \"items\": [\n        [\n          \"Mi kerül a visszajelzésbe?\",\n          \"A felvételen látható konkrét megfigyelés és egy következő gyakorlási szempont. Egy rövid videó nem mutat meg minden beszédhelyzetet.\"\n        ],\n        [\n          \"Miért spontán videó?\",\n          \"Így természetes megszólalásból indulunk ki. Nem a begyakorolt felvétel minőségét értékeljük.\"\n        ],\n        [\n          \"Ki nézi meg?\",\n          \"Nagy Rita Gréta logopédus és beszédtanár. A valódi szolgáltatásban személyes választ adna.\"\n        ],\n        [\n          \"Kapok automatikusan ajánlatokat?\",\n          \"Az opcionális hírlevélre és kampányüzenetekre külön lehet majd feliratkozni. A videóhoz kapcsolódó választ ettől külön kezeljük.\"\n        ],\n        [\n          \"Mi működik most?\",\n          \"A következő képernyő helyi frontend bemutató. A videó nem kerül szerverre, és a visszajelzés mintaszöveg.\"\n        ]\n      ],\n      \"media\": [],\n      \"anchor\": \"kerdesek\"\n    },\n    {\n      \"layout\": \"S20\",\n      \"title\": \"Tudd meg, mire érdemes először figyelned\",\n      \"paragraphs\": [\n        \"Mutasd meg egy rövid, spontán videón, hogyan beszélsz. A személyes visszajelzés után könnyebb lehet kijelölnöd a következő gyakorlási fókuszt.\",\n        \"Ingyenes első lépés, vásárlási kötelezettség nélkül. Most a videóválasztás és a válasz állapotait mutató bemutató nyílik meg.\"\n      ],\n      \"items\": [],\n      \"media\": [],\n      \"cta_variant\": \"free-2\"\n    },\n    {\n      \"layout\": \"S28\",\n      \"title\": \"Komplex Logopédia\",\n      \"paragraphs\": [\n        \"Frontend bemutató. A videóküldés, a válaszadási idő és a szolgáltatási feltételek még véglegesítendők.\"\n      ],\n      \"items\": [],\n      \"media\": []\n    }\n  ],\n  \"id\": \"free-b\"\n}\n\nPre-generation concrete criticism, already reflected in this copy. The UI must preserve those fixes:\n[\n  [\n    \"Az általános beszédfejlesztési ígéret nem segített a bizonytalan érdeklődőnek.\",\n    \"A látogató előbb megnevez egy helyzetet, majd megérti, hogy a visszajelzés gyakorlási fókuszt ad.\"\n  ],\n  [\n    \"A visszajelzés és a vásárlási lépés összemosódott.\",\n    \"A teljes oldal az ingyenes lépésről szól, és kimondja az önálló döntés lehetőségét.\"\n  ],\n  [\n    \"A sablon véleményblokkja bizonyítékot sugallt volna.\",\n    \"A vízszintes kártyák konkrét megfigyelési témákat mutatnak, név és csillagok nélkül.\"\n  ]\n]\n\nACTUAL incumbent @font-face declarations:\n@font-face{font-family:Quicksand Variablefont Wght;src:url(https://cdn.prod.website-files.com/670786dbc9081bdd565d8269/67078930698de7f94d825e52_Quicksand-VariableFont_wght.ttf)format(\"truetype\");font-weight:300 700;font-style:normal;font-display:swap}\n@font-face{font-family:Nunitosans Variablefont Ytlc Opsz Wdth Wght;src:url(https://cdn.prod.website-files.com/670786dbc9081bdd565d8269/6707893068ac68080d606ef1_NunitoSans-VariableFont_YTLC%2Copsz%2Cwdth%2Cwght.ttf)format(\"truetype\");font-weight:200 1000;font-style:normal;font-display:swap}\n\nACTUAL supplied layout kit HTML (media-encoded placeholders replaced, original structural CSS/markup/behavior retained). Use its assigned layout vocabulary and adapt irrelevant functions truthfully:\n\n<!DOCTYPE html>\n\n<html lang=\"hu\">\n<head>\n<meta charset=\"utf-8\"/>\n<meta content=\"width=device-width, initial-scale=1.0\" name=\"viewport\"/>\n<title>Design 2 · Layout template</title>\n<meta content=\"[TEMPLATE: Meta leírás, 140-160 karakter, fő kulcsszóval]\" name=\"description\"/>\n<style>\n/* ==========================================================================\n   [TEMPLATE ANNOTATION]: This file is a LAYOUT template. It decides section\n   order, HTML structure, layout CSS (grid, flex, sticky, 3D transforms and the\n   transitions the JavaScript depends on), interactive classes, ids, the fixed\n   widgets and the JavaScript. It decides NOTHING about fonts, colours, radius,\n   shadows, hover effects, icon weight or decorations. Every value in :root is a\n   neutral placeholder that the styling prompt replaces in one place.\n   ========================================================================== */\n:root {\n  --brand: #4a4a4a;\n  --brand-hover: #3a3a3a;\n  --brand-dark: #333333;\n  --brand-darkest: #1a1a1a;\n  --brand-light: #e0e0e0;\n  --accent: #5c5c5c;\n\n  --white: #ffffff;\n  --black: #000000;\n  --gray-50: #f7f7f7;\n  --gray-100: #e6e6e6;\n  --gray-200: #d6d6d6;\n  --gray-300: #c2c2c2;\n  --gray-400: #a3a3a3;\n  --gray-500: #8a8a8a;\n  --gray-600: #6b6b6b;\n  --gray-700: #454545;\n  --gray-800: #262626;\n\n  --text-dark: #1a1a1a;\n  --text-muted: #4a4a4a;\n  --text-light: #e8e8e8;\n\n  --max-w: 1320px;\n  --section-padding-y: 120px;\n  --section-padding-x: 24px;\n  --header-margin-bottom: 60px;\n  --radius: 8px;\n}\n\n/* 1. RESET AND BASE */\n*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\nhtml { scroll-behavior: smooth; }\nbody {\n  font-family: system-ui, sans-serif;\n  background-color: var(--white);\n  color: var(--text-muted);\n  line-height: 1.6;\n  font-size: 1.0625rem;\n  position: relative;\n}\n/* [TEMPLATE ANNOTATION]: body.no-scroll is set by the lightbox only. It uses\n   position: fixed instead of overflow: hidden, because overflow on body would\n   kill the sticky galleries (see the sticky-gallery rule below). */\nbody.no-scroll { position: fixed; width: 100%; }\nh1, h2, h3, h4, h5, h6 { font-family: system-ui, sans-serif; line-height: 1.2; color: var(--text-dark); font-weight: 700; margin-bottom: 1rem; }\np { margin-bottom: 1.25rem; }\na { text-decoration: none; color: inherit; }\nul, ol { list-style: none; }\nimg { max-width: 100%; height: auto; display: block; border-radius: var(--radius); }\nsection, header, footer, div[id] { scroll-margin-top: 140px; }\n\n/* 2. UTILITIES */\n.container { width: 100%; max-width: var(--max-w); margin: 0 auto; padding: 0 var(--section-padding-x); position: relative; z-index: 1; }\n.text-center { text-align: center; }\n.bg-gray { background-color: var(--gray-50); }\n.bg-white { background-color: var(--white); }\n.bg-alternate { background-color: var(--gray-50); }\n.d-flex { display: flex; }\n.align-items-center { align-items: center; }\n.justify-content-between { justify-content: space-between; }\n.gap-10 { gap: 10px; }\n.gap-20 { gap: 20px; }\n/* [TEMPLATE ANNOTATION]: dark-bg-text marks every text that sits on a dark\n   background. The styling prompt puts the light colour and the contrast text\n   shadow here, in one place. */\n.dark-bg-text { color: var(--text-light); }\n.dark-bg-text-sub { color: var(--text-light); }\n.section-header { margin-bottom: var(--header-margin-bottom); position: relative; z-index: 2; }\n.section-header.text-center { text-align: center; }\n.section-title { font-size: clamp(2rem, 4vw, 3rem); margin-bottom: 16px; }\n.section-subtitle { display: block; font-size: 1rem; letter-spacing: 0.12em; text-transform: uppercase; font-weight: 700; margin-bottom: 10px; color: var(--text-muted); }\n.pill-badge { display: inline-flex; align-items: center; gap: 8px; background: var(--brand-light); color: var(--text-dark); padding: 8px 16px; border-radius: var(--radius); font-size: 0.9rem; font-weight: 600; margin-bottom: 20px; }\n.pill-badge span.highlight { background: var(--gray-300); color: var(--text-dark); padding: 2px 10px; border-radius: var(--radius); font-size: 0.8rem; }\n\n/* [TEMPLATE ANNOTATION]: .reveal is the scroll-reveal contract. The observer\n   adds .visible. An element must be fully visible with .visible OR with\n   prefers-reduced-motion, never hidden for good. */\n.reveal { opacity: 0; transform: translateY(24px); transition: opacity 0.6s, transform 0.6s; }\n.reveal.visible { opacity: 1; transform: none; }\n@media (prefers-reduced-motion: reduce) { .reveal, .reveal.visible { opacity: 1; transform: none; transition: none; } }\n\n/* 3. BUTTONS */\n.btn { display: inline-flex; align-items: center; justify-content: center; gap: 10px; padding: 16px 32px; border-radius: var(--radius); font-weight: 700; font-size: 1.05rem; cursor: pointer; border: 2px solid transparent; font-family: inherit; line-height: 1; }\n.btn-primary { background-color: var(--brand); color: var(--text-light); }\n.btn-brand { background-color: var(--brand-dark); color: var(--text-light); }\n.btn-outline { background-color: transparent; color: var(--text-dark); border: 2px solid var(--gray-400); }\n.btn:disabled { opacity: 0.6; cursor: not-allowed; }\n.btn-play { background: transparent; color: var(--text-dark); padding: 10px; display: inline-flex; align-items: center; gap: 12px; cursor: pointer; border: none; font-family: inherit; font-size: 1.05rem; }\n.btn-play i { display: flex; align-items: center; justify-content: center; width: 50px; height: 50px; background: var(--brand); color: var(--text-light); border-radius: 50%; }\n\n/* 4. FORM CONTROLS */\n.input-group { margin-bottom: 20px; }\n.input-group label { display: block; font-weight: 600; color: var(--text-dark); margin-bottom: 8px; }\ninput, select, textarea { width: 100%; padding: 14px 18px; border-radius: var(--radius); border: 1px solid var(--gray-300); background: var(--gray-100); font-family: inherit; font-size: 1rem; color: var(--text-dark); }\ntextarea { resize: vertical; min-height: 110px; }\n.form-step { display: none; }\n.form-step.active { display: block; }\n.service-select-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 15px; margin-bottom: 25px; }\n.service-select-card { border: 2px solid var(--gray-300); border-radius: var(--radius); padding: 20px 12px; text-align: center; cursor: pointer; background: transparent; user-select: none; }\n.service-select-card i { font-size: 2.2rem; display: block; margin-bottom: 8px; color: var(--text-dark); }\n.service-select-card span { display: block; font-weight: 600; color: var(--text-dark); }\n.service-select-card.selected { border-color: var(--brand); background: var(--gray-200); }\n.step-buttons { display: flex; gap: 15px; margin-top: 20px; }\n\n/* 5. BLOCK 1 - TOP BAR AND NAV */\n.header-sticky-wrapper { position: relative; z-index: 1000; }\n.top-bar { background-color: var(--brand-darkest); color: var(--text-light); padding: 10px 0; font-size: 0.9rem; }\n.top-bar a { color: var(--text-light); }\n.top-bar i { margin-right: 8px; }\n.top-bar-inner { display: flex; justify-content: space-between; align-items: center; gap: 12px 20px; flex-wrap: wrap; }\n/* [TEMPLATE ANNOTATION]: Primary source nav model. The nav floats over the hero and\n   the scroll handler adds .scrolled on #headerWrapper, which pins it. */\n.header-main { position: absolute; top: 100%; left: 0; width: 100%; z-index: 1000; background: transparent; padding: 15px 0; }\n.header-sticky-wrapper.scrolled .header-main { position: fixed; top: 0; background: var(--white); padding: 10px 0; }\n.nav { display: flex; justify-content: space-between; align-items: center; gap: 20px; }\n.nav-logo-link { display: flex; align-items: center; gap: 12px; font-weight: 800; font-size: 1.5rem; color: var(--text-dark); }\n.nav-logo-plaque { display: inline-flex; align-items: center; justify-content: center; background: var(--white); padding: 6px; border-radius: var(--radius); }\n.nav-logo-img { height: 44px; width: auto; object-fit: contain; }\n.nav-links { display: flex; gap: 28px; align-items: center; }\n.nav-links a { font-weight: 600; color: var(--text-dark); }\n.nav-cta { display: flex; align-items: center; }\n.mobile-menu-btn { display: none; font-size: 2rem; color: var(--text-dark); background: none; border: none; cursor: pointer; padding: 4px 8px; width: auto; }\n.mobile-menu { display: none; background: var(--white); border-top: 1px solid var(--gray-200); padding: 16px var(--section-padding-x); }\n.mobile-menu.open { display: block; }\n.mobile-menu a { display: block; padding: 12px 0; font-weight: 600; color: var(--text-dark); border-bottom: 1px solid var(--gray-200); }\n\n/* 6. BLOCK 2 AND 5 - HERO LAYOUT */\n.hero { position: relative; padding: 200px 0 100px; background: var(--gray-50); overflow: hidden; }\n.spotlight { position: relative; padding: var(--section-padding-y) 0; background: var(--white); overflow: hidden; }\n.hero-grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr); gap: 60px; align-items: center; position: relative; z-index: 2; }\n.hero-text { padding-right: 20px; }\n.hero-text h1 { font-size: clamp(2.4rem, 4.5vw, 4rem); margin-bottom: 20px; line-height: 1.08; }\n.hero-text p.subtitle { font-size: 1.1rem; margin-bottom: 36px; max-width: 90%; }\n.hero-actions { display: flex; align-items: center; gap: 20px; margin-bottom: 36px; flex-wrap: wrap; }\n.hero-reviews { display: flex; align-items: center; gap: 15px; }\n.review-avatars { display: flex; }\n.review-avatars img { width: 45px; height: 45px; border-radius: 50%; border: 3px solid var(--white); margin-left: -15px; object-fit: cover; }\n.review-avatars img:first-child { margin-left: 0; }\n.review-stars { display: flex; flex-direction: column; }\n.review-stars .stars { display: flex; gap: 2px; color: var(--brand); }\n.review-stars span { font-size: 0.85rem; font-weight: 600; color: var(--text-dark); }\n.hero-visual { position: relative; display: flex; justify-content: center; align-items: center; height: 520px; }\n.target-wrapper { position: relative; width: 360px; height: 360px; display: flex; justify-content: center; align-items: center; }\n.ring { position: absolute; border-radius: 50%; border: 1px solid var(--gray-300); top: 50%; left: 50%; transform: translate(-50%, -50%); }\n.ring-1 { width: 100%; height: 100%; }\n.ring-2 { width: 122%; height: 122%; border-style: dashed; }\n.ring-3 { width: 142%; height: 142%; border-width: 2px; }\n.crosshair { position: absolute; background: var(--gray-100); border: 2px solid var(--brand); border-radius: 50%; width: 12px; height: 12px; }\n.ch-top { top: -6px; left: 50%; transform: translateX(-50%); }\n.ch-bottom { bottom: -6px; left: 50%; transform: translateX(-50%); }\n.ch-left { left: -6px; top: 50%; transform: translateY(-50%); }\n.ch-right { right: -6px; top: 50%; transform: translateY(-50%); }\n.hero-image-circle { width: 100%; height: 100%; border-radius: 50%; overflow: hidden; position: relative; z-index: 5; border: 10px solid var(--white); }\n.hero-image-circle img { width: 100%; height: 100%; object-fit: cover; border-radius: 0; }\n.floating-icon { position: absolute; width: 70px; height: 70px; background: var(--brand-dark); border-radius: 50%; display: flex; justify-content: center; align-items: center; color: var(--text-light); font-size: 2rem; z-index: 10; border: 4px solid var(--white); }\n.fi-1 { top: 8%; left: -4%; animation: floatY 4s ease-in-out infinite; }\n.fi-2 { bottom: 12%; right: -4%; animation: floatY 5s ease-in-out infinite alternate; }\n@keyframes floatY { 0% { transform: translateY(0); } 50% { transform: translateY(-15px); } 100% { transform: translateY(0); } }\n\n/* 7. BLOCK 3 - TRUST BADGES */\n.trust-badges { background: var(--brand-dark); padding: 60px 0; color: var(--text-light); position: relative; z-index: 5; }\n.trust-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 30px; text-align: center; }\n.trust-item { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 15px; font-size: 1.1rem; font-weight: 700; color: var(--text-light); }\n.trust-item i { font-size: 2.6rem; padding: 15px; border-radius: var(--radius); background: var(--gray-700); }\n\n/* 8. BLOCK 4 - SERVICE DETAIL WITH GALLERY TRACK */\n.service-detail { padding: 80px 0; }\n.sd2-mobile-title { display: none; }\n.sd2-desktop-title { display: block; }\n.sd2-service-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 60px; align-items: stretch; }\n.sd2-content-side { display: flex; flex-direction: column; gap: 32px; }\n.sd2-feature-cards { display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; }\n.sd2-feature-card { background: var(--gray-100); border-radius: var(--radius); padding: 28px; display: flex; gap: 20px; align-items: flex-start; position: relative; }\n.sd2-feature-card i { font-size: 2.6rem; color: var(--text-dark); padding: 12px; border-radius: var(--radius); background: var(--gray-200); flex-shrink: 0; }\n.sd2-feature-card h4 { font-size: 1.25rem; margin-bottom: 8px; }\n.sd2-feature-card p { margin: 0; }\n.sd2-service-gallery { position: relative; width: 100%; height: 100%; }\n.sd2-slider-btn { display: none; }\n.sd2-gallery-track-wrapper { width: 100%; height: 100%; }\n.sd2-gallery-track { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-rows: 1fr 140px; gap: 15px; width: 100%; height: 100%; min-height: 460px; }\n.sd2-gallery-item { position: relative; border-radius: var(--radius); overflow: hidden; background: var(--gray-100); height: 100%; }\n.sd2-gallery-item img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 0; }\n.sd2-item-main { grid-column: span 3; }\n.sd2-expand-btn { position: absolute; top: 12px; right: 12px; background: var(--gray-800); color: var(--text-light); width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 1.2rem; cursor: pointer; z-index: 5; }\n\n/* 9. BLOCK 6 - STATS */\n.stats-section { background: var(--brand-darkest); padding: var(--section-padding-y) 0; color: var(--text-light); }\n.stats-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 30px; }\n.stat-item { padding: 20px; text-align: center; }\n.stat-item i { font-size: 3rem; margin-bottom: 16px; display: inline-block; color: var(--text-light); }\n.stat-item h3 { font-size: 3rem; line-height: 1; margin-bottom: 8px; color: var(--text-light); }\n.stat-item p { margin: 0; text-transform: uppercase; letter-spacing: 0.1em; }\n\n/* 10. BLOCK 7 - ABOUT */\n.about-section { padding: var(--section-padding-y) 0; background: var(--white); }\n.about-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 60px; align-items: center; }\n.about-img { position: relative; z-index: 2; }\n.about-img img { width: 100%; height: 460px; object-fit: cover; }\n.about-experience { position: absolute; bottom: -20px; left: 0; background: var(--gray-100); padding: 22px 26px; border-radius: var(--radius); z-index: 3; display: flex; align-items: center; gap: 18px; }\n.about-experience i { font-size: 2.6rem; color: var(--text-dark); }\n.about-experience p { margin: 0; font-weight: 700; text-transform: uppercase; font-size: 0.9rem; line-height: 1.3; color: var(--text-dark); }\n\n/* 11. BLOCK 8 - WHY US / FOUNDATION */\n.foundation-section { padding: var(--section-padding-y) 0; background: var(--gray-50); overflow: hidden; }\n.foundation-grid { display: grid; grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); gap: 60px; align-items: center; }\n.foundation-images { position: relative; display: flex; align-items: center; }\n.img-main-card { width: 88%; height: 400px; border-radius: var(--radius); overflow: hidden; position: relative; z-index: 2; }\n.img-main-card img { width: 100%; height: 100%; object-fit: cover; border-radius: 0; }\n.experience-badge { position: absolute; bottom: 20px; right: 0; background: var(--gray-100); padding: 22px 26px; border-radius: var(--radius); z-index: 3; display: flex; align-items: center; gap: 18px; }\n.experience-badge h3 { font-size: 2.6rem; margin: 0; line-height: 1; }\n.experience-badge p { font-size: 0.9rem; font-weight: 700; text-transform: uppercase; margin: 0; line-height: 1.2; color: var(--text-dark); }\n.foundation-list { margin: 24px 0 32px; }\n.foundation-list li { display: flex; align-items: flex-start; gap: 15px; margin-bottom: 16px; }\n.foundation-list i { font-size: 1.4rem; color: var(--text-dark); padding: 8px; border-radius: 50%; background: var(--gray-200); }\n.foundation-list p { margin: 0; }\n\n/* 12. BLOCK 9 - MATERIALS ACCORDION */\n.materials-section { padding: var(--section-padding-y) 0; background: var(--white); }\n.accordion-container { display: flex; height: 480px; gap: 15px; }\n.accordion-panel { flex: 1; position: relative; overflow: hidden; border-radius: var(--radius); transition: flex 0.6s; cursor: pointer; }\n.accordion-panel img { width: 100%; height: 100%; object-fit: cover; border-radius: 0; }\n.accordion-panel:hover { flex: 4; }\n.accordion-content { position: absolute; bottom: 0; left: 0; right: 0; padding: 28px; color: var(--text-light); background: var(--gray-800); opacity: 0; transition: opacity 0.6s; z-index: 2; }\n.accordion-panel:hover .accordion-content { opacity: 1; }\n.accordion-content h4 { font-size: 1.5rem; margin-bottom: 8px; color: var(--text-light); }\n.accordion-content p { margin: 0; color: var(--text-light); }\n.accordion-panel .vertical-title { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%) rotate(270deg); font-size: 1.4rem; letter-spacing: 3px; text-transform: uppercase; color: var(--text-light); font-weight: 800; white-space: nowrap; pointer-events: none; z-index: 3; }\n.accordion-panel:hover .vertical-title { opacity: 0; }\n\n/* 13. BLOCK 10 - SERVICES DARK GRID */\n.services-dark { background: var(--brand-darkest); padding: var(--section-padding-y) 0; position: relative; }\n.services-dark .section-title { color: var(--text-light); text-align: center; max-width: 800px; margin-left: auto; margin-right: auto; margin-bottom: 50px; }\n.services-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 26px; }\n.service-card-ref { background: var(--gray-100); border-radius: var(--radius); padding: 0; overflow: hidden; position: relative; }\n.service-card-ref img { width: 100%; height: 200px; object-fit: cover; border-radius: 0; }\n.service-card-icon { position: absolute; right: 22px; top: 170px; width: 60px; height: 60px; background: var(--gray-200); color: var(--text-dark); border-radius: 50%; display: flex; justify-content: center; align-items: center; font-size: 1.6rem; border: 4px solid var(--white); }\n.service-card-content { padding: 34px 26px 26px; }\n.service-card-content h4 { font-size: 1.2rem; margin-bottom: 12px; }\n.service-card-content p { font-size: 0.95rem; margin-bottom: 18px; }\n.service-card-content a { font-weight: 700; color: var(--text-dark); display: inline-flex; align-items: center; gap: 6px; }\n\n/* 14. BLOCK 11 - STICKY DETAILS */\n.sticky-section { padding: var(--section-padding-y) 0; background: var(--white); }\n/* [TEMPLATE ANNOTATION]: .sticky-left pins while .sticky-right scrolls. Do not\n   put overflow or contain on .sticky-wrapper, it would break the pinning. */\n.sticky-wrapper { display: flex; gap: 60px; align-items: flex-start; }\n.sticky-left { position: sticky; top: 150px; width: 40%; }\n.sticky-right { width: 60%; display: flex; flex-direction: column; gap: 40px; }\n.scroll-card { background: var(--gray-100); border-radius: var(--radius); overflow: hidden; }\n.scroll-card img { width: 100%; height: 320px; object-fit: cover; border-radius: 0; }\n.scroll-card-content { padding: 32px; }\n.scroll-card-content h3 { font-size: 1.5rem; margin-bottom: 12px; }\n.scroll-feature-list { display: flex; flex-wrap: wrap; gap: 16px; }\n.scroll-feature-item { display: inline-flex; align-items: center; gap: 8px; font-weight: 600; color: var(--text-dark); }\n\n/* 15. BLOCK 12 - PROCESS */\n.process-section { padding: var(--section-padding-y) 0; background: var(--gray-50); text-align: center; overflow: hidden; }\n.process-container { position: relative; margin-top: 60px; max-width: 1000px; margin-inline: auto; }\n.process-line { position: absolute; top: 80px; left: 10%; width: 80%; height: 10px; background: transparent; z-index: 1; border-top: 4px dashed var(--gray-300); }\n.process-steps-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 40px; position: relative; z-index: 2; }\n.process-step { display: flex; flex-direction: column; align-items: center; }\n.step-img-wrapper { width: 160px; height: 160px; border-radius: 50%; background: var(--gray-100); padding: 10px; margin-bottom: 26px; position: relative; }\n.step-img-wrapper img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; }\n.step-number { position: absolute; bottom: 0; right: 0; width: 40px; height: 40px; background: var(--brand-dark); color: var(--text-light); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 1.1rem; border: 3px solid var(--white); }\n.process-step h4 { font-size: 1.2rem; margin-bottom: 8px; }\n.process-step p { font-size: 0.95rem; max-width: 260px; margin: 0 auto; }\n\n/* 16. BLOCK 13 - TESTIMONIALS */\n.testimonials { padding: var(--section-padding-y) 0; background: var(--white); }\n.test-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 26px; }\n.test-card { background: var(--gray-100); border-radius: var(--radius); padding: 34px; display: flex; flex-direction: column; justify-content: space-between; }\n.test-stars { display: flex; gap: 3px; margin-bottom: 16px; color: var(--brand); }\n.test-quote { margin-bottom: 26px; }\n.test-author { display: flex; align-items: center; justify-content: space-between; border-top: 1px solid var(--gray-300); padding-top: 18px; gap: 12px; }\n.test-author-info { display: flex; align-items: center; gap: 14px; }\n.test-avatar { width: 50px; height: 50px; border-radius: 50%; background: var(--gray-200); color: var(--text-dark); display: flex; align-items: center; justify-content: center; font-weight: 700; }\n.test-name h5 { margin: 0; font-size: 1.05rem; }\n.test-name span { font-size: 0.85rem; }\n.google-logo { width: 24px; height: 24px; flex-shrink: 0; }\n\n/* 17. SHARED GALLERY PIECES */\n.img-wrapper { border-radius: var(--radius); overflow: hidden; position: relative; background: var(--gray-100); }\n.img-wrapper img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }\n.img-expand { position: absolute; top: 12px; right: 12px; display: flex; align-items: center; justify-content: center; cursor: pointer; z-index: 5; }\n.img-expand i { color: var(--text-light); font-size: 1.3rem; background: var(--gray-800); padding: 10px; border-radius: 50%; }\n\n/* [TEMPLATE ANNOTATION]: never put overflow: hidden, overflow: auto, overflow-x,\n   overflow-y or contain on .gallery-motion-v2, .gallery-motion-v5, body, html or\n   any other ancestor of .v2-sticky or .v5-sticky. It disables position: sticky and\n   the galleries stop pinning and rotating. */\n.gallery-motion-v2 { height: 300vh; background: var(--gray-50); position: relative; margin-bottom: var(--section-padding-y); }\n/* [TEMPLATE ANNOTATION]: The sticky container locks the view for 100vh and the\n   flex centering keeps the 3D carousel dead centre. perspective and\n   transform-style are load bearing for the cylinder. */\n.v2-sticky { position: sticky; top: 0; height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; padding-top: 100px; perspective: 1500px; overflow: visible; }\n.v2-header { position: absolute; top: 12%; left: 50%; transform: translateX(-50%); width: 100%; z-index: 20; margin-bottom: 0; }\n.v2-carousel { position: relative; width: 360px; height: 460px; transform-style: preserve-3d; will-change: transform; }\n.v2-item { position: absolute; inset: 0; border: 4px solid var(--white); border-radius: var(--radius); overflow: hidden; }\n\n/* [TEMPLATE ANNOTATION]: never put overflow: hidden, overflow: auto, overflow-x,\n   overflow-y or contain on .gallery-motion-v2, .gallery-motion-v5, body, html or\n   any other ancestor of .v2-sticky or .v5-sticky. It disables position: sticky and\n   the galleries stop pinning and rotating. */\n.gallery-motion-v5 { height: 300vh; background: var(--white); position: relative; margin-bottom: var(--section-padding-y); }\n.v5-sticky { position: sticky; top: 0; height: 100vh; overflow: hidden; display: flex; align-items: center; justify-content: center; }\n.v5-inner { position: absolute; top: 0; left: 0; width: 100%; height: 100vh; padding-top: 130px; display: grid; grid-template-columns: repeat(3, 26vw); grid-auto-rows: 25vh; gap: 2vw; align-content: center; justify-content: center; will-change: transform, opacity; z-index: 1; }\n.v5-inner .img-wrapper { width: 100%; height: 100%; }\n/* [TEMPLATE ANNOTATION]: SPLIT GATES LOGIC. Two panels exactly 50% wide, each\n   holding an image forced to 200% width, the right one offset by left: -100%.\n   That gives a seamless split line in the exact centre. */\n.v5-gate-panel { position: absolute; top: 0; width: 50%; height: 100vh; overflow: hidden; z-index: 10; will-change: transform; background: var(--white); }\n.v5-gate-left { left: 0; }\n.v5-gate-right { right: 0; }\n.v5-gate-panel img { position: absolute; width: 200%; height: 100vh; object-fit: cover; top: 0; border-radius: 0; max-width: none; }\n.v5-gate-left img { left: 0; }\n.v5-gate-right img { left: -100%; }\n.v5-header { position: absolute; top: calc(50% + 60px); left: 50%; transform: translate(-50%, -50%); z-index: 20; text-align: center; pointer-events: none; width: 100%; }\n.v5-header .section-title, .v5-header .section-subtitle { color: var(--text-light); }\n\n/* 18. LIGHTBOX */\n.lightbox-overlay { position: fixed; inset: 0; background: var(--brand-darkest); z-index: 9999; display: none; flex-direction: column; align-items: center; justify-content: center; }\n.lightbox-overlay.active { display: flex; }\n.lb-close { position: absolute; top: 24px; right: 32px; color: var(--text-light); font-size: 2.4rem; cursor: pointer; z-index: 100; }\n.lb-nav { position: absolute; top: 50%; transform: translateY(-50%); color: var(--text-light); font-size: 2.6rem; cursor: pointer; z-index: 100; padding: 20px; }\n.lb-prev { left: 16px; }\n.lb-next { right: 16px; }\n.lb-img-container { position: relative; width: 80vw; height: 80vh; display: flex; justify-content: center; align-items: center; }\n.lb-img { position: absolute; max-width: 100%; max-height: 100%; object-fit: contain; opacity: 0; }\n.lb-img.active { opacity: 1; z-index: 10; }\n/* [TEMPLATE ANNOTATION]: the enter and exit classes are set by changeLightboxImg\n   and removed 500 ms later. Keep the class names and the 500 ms budget in sync\n   with the script. */\n.lb-img.enter-next { animation: slideInRight 0.5s forwards; }\n.lb-img.enter-prev { animation: slideInLeft 0.5s forwards; }\n.lb-img.exit-next { animation: slideOutLeft 0.5s forwards; }\n.lb-img.exit-prev { animation: slideOutRight 0.5s forwards; }\n@keyframes slideInRight { from { transform: translateX(50px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }\n@keyframes slideInLeft { from { transform: translateX(-50px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }\n@keyframes slideOutLeft { from { transform: translateX(0); opacity: 1; } to { transform: translateX(-50px); opacity: 0; } }\n@keyframes slideOutRight { from { transform: translateX(0); opacity: 1; } to { transform: translateX(50px); opacity: 0; } }\n\n/* 19. BLOCK 16 - CTA BAND */\n.cta-section { padding: var(--section-padding-y) 0; background: var(--white); }\n.cta-box { background: var(--gray-100); border-radius: var(--radius); overflow: hidden; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center; position: relative; }\n.cta-content { padding: 60px 48px; position: relative; z-index: 2; }\n.cta-content .section-title { font-size: clamp(1.8rem, 3vw, 2.6rem); }\n.cta-content p { color: var(--text-muted); margin-bottom: 28px; }\n.cta-image { height: 100%; position: relative; min-height: 420px; }\n.cta-image img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 0; }\n\n/* 20. BLOCK 17 - CALCULATOR A (card price calculator) */\n.calc-section { padding: var(--section-padding-y) 0; background: var(--gray-50); }\n.v1-card { background: var(--gray-100); border-radius: var(--radius); padding: 44px; max-width: 800px; margin: 0 auto; position: relative; }\n.v1-progress { display: flex; justify-content: space-between; margin-bottom: 36px; position: relative; }\n.v1-progress::before { content: ''; position: absolute; top: 50%; left: 0; width: 100%; height: 4px; background: var(--gray-300); transform: translateY(-50%); z-index: 1; }\n.v1-progress-bar { position: absolute; top: 50%; left: 0; height: 4px; background: var(--brand); transform: translateY(-50%); z-index: 2; transition: width 0.4s; }\n.v1-step-indicator { width: 45px; height: 45px; border-radius: 50%; background: var(--gray-200); color: var(--text-muted); display: flex; align-items: center; justify-content: center; font-weight: 800; z-index: 3; position: relative; border: 4px solid var(--white); }\n.v1-step-indicator.active { background: var(--brand); color: var(--text-light); }\n.v1-step-indicator.completed { background: var(--brand-dark); color: var(--text-light); }\n.v1-step { display: none; }\n.v1-step.active { display: block; }\n.v1-step h3 { font-size: 1.5rem; margin-bottom: 20px; text-align: center; }\n.v1-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 15px; margin-bottom: 26px; }\n.v1-option { border: 2px solid var(--gray-300); border-radius: var(--radius); padding: 22px 12px; text-align: center; cursor: pointer; user-select: none; background: transparent; }\n.v1-option i { font-size: 2.6rem; color: var(--text-dark); margin-bottom: 10px; display: block; }\n.v1-option span { font-weight: 700; color: var(--text-dark); }\n.v1-option.selected { border-color: var(--brand); background: var(--gray-200); }\n.v1-actions { display: flex; justify-content: space-between; gap: 16px; margin-top: 26px; border-top: 1px solid var(--gray-300); padding-top: 26px; }\n.slider-container { margin: 32px 0 40px; }\n.slider-val { font-size: 2.4rem; font-weight: 800; color: var(--text-dark); text-align: center; margin-bottom: 16px; }\ninput[type=range] { -webkit-appearance: none; appearance: none; width: 100%; background: transparent; padding: 0; border: none; }\ninput[type=range]::-webkit-slider-runnable-track { width: 100%; height: 8px; cursor: pointer; background: var(--gray-300); border-radius: 4px; }\ninput[type=range]::-webkit-slider-thumb { -webkit-appearance: none; height: 28px; width: 28px; border-radius: 50%; background: var(--brand); cursor: pointer; margin-top: -10px; border: 4px solid var(--white); }\n.v1-result-box { background: var(--brand-darkest); color: var(--text-light); padding: 36px; border-radius: var(--radius); text-align: center; margin-bottom: 26px; }\n.v1-result-box h4 { color: var(--text-light); font-size: 1rem; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 10px; }\n.v1-result-box .price { font-size: 3rem; font-weight: 800; color: var(--text-light); line-height: 1; margin-bottom: 12px; }\n.v1-result-box p { color: var(--text-light); font-size: 0.95rem; margin: 0; }\n.calc-note { text-align: center; font-weight: 600; margin-bottom: 18px; }\n.calc-error { color: var(--text-dark); font-weight: 700; text-align: center; margin-bottom: 12px; }\n.calc-form-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 15px; }\n.v1-done { text-align: center; padding: 40px 0; }\n.v1-done i { font-size: 4rem; color: var(--text-dark); margin-bottom: 16px; display: block; }\n\n/* 21. BLOCK 18 - CALCULATOR B (split screen configurator) */\n.config-section { padding: var(--section-padding-y) 0; background: var(--white); }\n.v3-wrapper { display: flex; align-items: stretch; max-width: 1100px; margin: 0 auto; background: var(--gray-100); border-radius: var(--radius); overflow: hidden; min-height: 600px; }\n.v3-left { width: 35%; background: var(--brand-darkest); color: var(--text-light); padding: 44px 34px; display: flex; flex-direction: column; }\n.v3-left h3 { color: var(--text-light); font-size: 1.5rem; margin-bottom: 12px; }\n.v3-left p { color: var(--text-light); }\n.v3-summary-box { background: var(--gray-800); border-radius: var(--radius); padding: 24px; margin-top: auto; }\n.v3-summary-item { display: flex; justify-content: space-between; gap: 12px; margin-bottom: 14px; border-bottom: 1px dashed var(--gray-600); padding-bottom: 14px; align-items: center; }\n.v3-summary-item:last-child { margin-bottom: 0; border-bottom: none; padding-bottom: 0; }\n.v3-summary-label { color: var(--text-light); font-size: 0.95rem; }\n.v3-summary-value { font-weight: 700; text-align: right; color: var(--text-light); }\n.v3-total-wrap { margin-top: 24px; border-top: 1px solid var(--gray-600); padding-top: 18px; }\n.v3-total-label { display: block; color: var(--text-light); font-size: 0.95rem; margin-bottom: 6px; }\n.v3-total { font-size: 2rem; color: var(--text-light); font-weight: 800; line-height: 1; }\n.v3-right { width: 65%; padding: 44px 34px; background: var(--gray-100); }\n.v3-step-container { background: transparent; border-radius: var(--radius); margin-bottom: 18px; border: 1px solid var(--gray-300); }\n.v3-step-header { padding: 22px; display: flex; justify-content: space-between; align-items: center; cursor: pointer; gap: 12px; }\n.v3-step-header h4 { margin: 0; font-size: 1.1rem; display: flex; align-items: center; gap: 14px; }\n.v3-step-num { width: 30px; height: 30px; background: var(--gray-200); color: var(--text-dark); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.9rem; flex-shrink: 0; }\n.v3-step-header .status-icon { color: var(--gray-400); font-size: 1.4rem; }\n.v3-step-container.completed .status-icon { color: var(--text-dark); }\n.v3-step-body { padding: 0 22px 22px; display: none; }\n.v3-step-container.active { border-color: var(--brand); }\n.v3-step-container.active .v3-step-body { display: block; }\n.v3-step-container.active .v3-step-header { border-bottom: 1px solid var(--gray-300); margin-bottom: 18px; }\n.v3-step-container.active .v3-step-num { background: var(--brand); color: var(--text-light); }\n.v3-radio-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 15px; }\n.v3-radio-label { display: flex; flex-direction: column; padding: 18px; border: 2px solid var(--gray-300); border-radius: var(--radius); cursor: pointer; background: transparent; }\n.v3-radio-label input { display: none; }\n.v3-radio-label.checked { border-color: var(--brand); background: var(--gray-200); }\n.v3-radio-title { font-weight: 800; color: var(--text-dark); margin-bottom: 5px; font-size: 1.02rem; display: flex; align-items: center; gap: 8px; }\n.v3-radio-desc { font-size: 0.9rem; line-height: 1.4; }\n\n/* 22. BLOCK 19 - CONTACT */\n.contact-redesigned { padding: var(--section-padding-y) 0; background: var(--gray-50); }\n.contact-wrapper { max-width: 1100px; margin: 0 auto; padding: 0 var(--section-padding-x); }\n.contact-grid { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 2fr); gap: 30px; align-items: start; }\n.contact-left { background: var(--brand-darkest); border-radius: var(--radius); padding: 44px 30px; color: var(--text-light); display: flex; flex-direction: column; }\n.contact-left h3 { color: var(--text-light); font-size: 1.8rem; margin-bottom: 16px; }\n.contact-left p { color: var(--text-light); margin-bottom: 30px; }\n.contact-info-block { background: var(--gray-800); border-radius: var(--radius); padding: 18px 22px; display: flex; align-items: center; gap: 18px; margin-bottom: 16px; }\n.icon-circle { width: 50px; height: 50px; border-radius: 50%; background: var(--brand); display: flex; align-items: center; justify-content: center; font-size: 1.6rem; color: var(--text-light); flex-shrink: 0; }\n.contact-info-block small { display: block; font-size: 0.9rem; color: var(--text-light); margin-bottom: 4px; }\n.contact-info-block strong { display: block; font-size: 1.1rem; font-weight: 700; color: var(--text-light); }\n.contact-right { background: var(--gray-100); border-radius: var(--radius); padding: 44px 34px; }\n.contact-right h3 { font-size: 1.5rem; margin-bottom: 20px; }\n\n/* 23. BLOCK 20 - FOOTER */\n.footer { background: var(--brand-darkest); color: var(--text-light); padding: 80px 0 30px; }\n.footer p { color: var(--text-light); }\n.footer-grid { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1.5fr) minmax(0, 1.5fr); gap: 50px; margin-bottom: 50px; }\n.footer-col h4 { font-size: 1.2rem; margin-bottom: 22px; color: var(--text-light); }\n.footer-links { display: flex; flex-direction: column; gap: 14px; }\n.footer-links a { color: var(--text-light); display: flex; align-items: center; gap: 10px; }\n.footer-bottom { padding-top: 26px; border-top: 1px solid var(--gray-700); font-size: 0.9rem; color: var(--text-light); display: flex; justify-content: space-between; align-items: center; gap: 20px; flex-wrap: wrap; }\n.footer-bottom p { margin: 0; }\n.footer-bottom a { color: var(--text-light); }\n\n/* 24. FIXED WIDGETS */\n.widget-phone { position: fixed; bottom: 30px; right: 30px; height: 60px; width: 60px; background: var(--brand-dark); color: var(--text-light); border-radius: 30px; display: flex; align-items: center; z-index: 1050; overflow: hidden; transition: width 0.4s; cursor: pointer; }\n.widget-phone .icon-wrapper { min-width: 60px; height: 60px; display: flex; align-items: center; justify-content: center; font-size: 1.6rem; }\n.widget-phone .text-wrapper { white-space: nowrap; font-weight: 700; padding-right: 22px; opacity: 0; transition: opacity 0.2s; }\n.widget-phone:hover { width: 220px; }\n.widget-phone:hover .text-wrapper { opacity: 1; }\n\n/* 25. ADDITIONAL CONTENT SLOTS (competitor modelled, same classes as above) */\n.uf-section { padding: var(--section-padding-y) 0; background: var(--white); }\n.uf-section.bg-alternate { background: var(--gray-50); }\n.uf-grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 26px; }\n.uf-grid-2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 26px; }\n.uf-card { background: var(--gray-100); border-radius: var(--radius); padding: 32px; }\n.uf-card h3 { font-size: 1.3rem; margin-bottom: 12px; }\n/* [TEMPLATE ANNOTATION]: wide tables scroll inside their own wrapper, never on the\n   page. .uf-table-wrap is not an ancestor of a sticky element, so overflow is safe\n   here. */\n.uf-table-wrap { width: 100%; overflow-x: auto; }\n.uf-table { width: 100%; border-collapse: collapse; min-width: 560px; }\n.uf-table th, .uf-table td { text-align: left; padding: 16px 18px; border-bottom: 1px solid var(--gray-300); }\n.uf-table th { font-weight: 700; color: var(--text-dark); }\n.uf-timeline { display: flex; flex-direction: column; gap: 26px; max-width: 760px; margin: 0 auto; }\n.uf-timeline-item { display: grid; grid-template-columns: 60px minmax(0, 1fr); gap: 20px; align-items: start; }\n.uf-timeline-dot { width: 44px; height: 44px; border-radius: 50%; background: var(--brand-dark); color: var(--text-light); display: flex; align-items: center; justify-content: center; font-weight: 700; }\n.uf-area-list { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 14px; }\n.uf-area-item { display: flex; align-items: center; gap: 10px; padding: 14px 16px; background: var(--gray-100); border-radius: var(--radius); font-weight: 600; color: var(--text-dark); }\n.uf-badge-strip { display: flex; flex-wrap: wrap; gap: 20px; justify-content: center; align-items: center; }\n.uf-badge-item { display: flex; flex-direction: column; align-items: center; gap: 10px; width: 160px; text-align: center; }\n.uf-badge-item img { width: 140px; height: 70px; object-fit: contain; }\n\n/* 26. MEDIA QUERIES */\n@media (max-width: 1200px) {\n  .hero-grid { grid-template-columns: minmax(0, 1fr); text-align: center; gap: 40px; }\n  .hero-text { padding-right: 0; }\n  .hero-actions, .hero-reviews { justify-content: center; }\n  .foundation-grid, .about-grid, .sd2-service-grid, .contact-grid { grid-template-columns: minmax(0, 1fr); }\n  .services-grid, .stats-grid, .test-grid, .uf-grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n  .cta-box { grid-template-columns: minmax(0, 1fr); }\n  .uf-area-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n}\n@media (max-width: 992px) {\n  .nav-links, .nav-cta { display: none; }\n  .mobile-menu-btn { display: block; }\n  .process-steps-grid { grid-template-columns: minmax(0, 1fr); gap: 50px; }\n  .process-line { display: none; }\n  .footer-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }\n  .sticky-wrapper { flex-direction: column; }\n  .sticky-left { position: relative; top: 0; width: 100%; margin-bottom: 24px; }\n  .sticky-right { width: 100%; }\n  .accordion-container { flex-direction: column; height: auto; }\n  .accordion-panel { height: 160px; }\n  .accordion-panel .vertical-title { transform: translate(-50%, -50%); }\n  .v3-wrapper { flex-direction: column; }\n  .v3-left, .v3-right { width: 100%; }\n  .v5-inner { grid-template-columns: repeat(3, 30vw); grid-auto-rows: 20vh; }\n  .v2-carousel { width: 280px; height: 380px; }\n  .sd2-mobile-title { display: block; }\n  .sd2-desktop-title { display: none; }\n  /* [TEMPLATE ANNOTATION]: below 992 px the gallery track becomes a slider. The\n     wrapper clips it and sd2MoveGallery translates the track. The wrapper is not\n     an ancestor of a sticky element, so overflow is allowed here. */\n  .sd2-gallery-track-wrapper { overflow: hidden; position: relative; width: 100%; padding: 10px 0; }\n  .sd2-gallery-track { display: flex; gap: 15px; height: auto; min-height: 0; transition: transform 0.4s; }\n  .sd2-gallery-item { flex: 0 0 calc(50% - 7.5px); height: 240px; }\n  .sd2-item-main { height: 240px; }\n  .sd2-slider-btn { display: flex; position: absolute; top: 50%; transform: translateY(-50%); width: 45px; height: 45px; border-radius: 50%; background: var(--gray-100); color: var(--text-dark); align-items: center; justify-content: center; font-size: 1.6rem; border: none; cursor: pointer; z-index: 10; padding: 0; }\n  .sd2-prev-btn { left: 0; }\n  .sd2-next-btn { right: 0; }\n}\n@media (max-width: 768px) {\n  :root { --section-padding-y: 80px; }\n  .hero { padding: 170px 0 70px; }\n  .top-bar { font-size: 0.8rem; }\n  .top-bar-inner { justify-content: center; text-align: center; }\n  .top-bar-inner > div { flex-wrap: wrap; justify-content: center; gap: 10px; }\n  .hero-visual { height: 380px; }\n  .target-wrapper { width: 220px; height: 220px; }\n  .services-grid, .stats-grid, .test-grid, .trust-grid, .footer-grid, .uf-grid-3, .uf-grid-2, .v1-grid, .v3-radio-grid, .service-select-grid, .calc-form-row { grid-template-columns: minmax(0, 1fr); }\n  .contact-left, .contact-right, .v1-card { padding: 28px 20px; }\n  .cta-content { padding: 40px 24px; }\n  .v5-inner { grid-template-columns: repeat(3, 28vw); grid-auto-rows: 15vh; }\n  .v2-carousel { width: 200px; height: 300px; }\n  .v2-header { top: 8%; }\n  .uf-area-list { grid-template-columns: minmax(0, 1fr); }\n  .lb-img-container { width: 92vw; height: 74vh; }\n}\n\n/* Review revision: native disclosures, animated reviews, integrated modules. */\n[hidden] { display: none !important; }\nbutton,input,textarea { font: inherit; }\nbutton { cursor: pointer; }\nbutton:focus-visible,summary:focus-visible,a:focus-visible,input:focus-visible,textarea:focus-visible { outline: 3px solid var(--brand); outline-offset: 4px; }\n#hero { padding-top: 160px; padding-bottom: 72px; }\n#hero .hero-grid { align-items: start; gap: 40px; }\n#hero .hero-text { padding-top: 24px; padding-right: 0; }\n.trust-count { font-size: clamp(2.6rem,5vw,4rem); line-height: 1; font-variant-numeric: tabular-nums; letter-spacing: -.04em; }\n.trust-item { gap: 14px; }\n.trust-item+.trust-item { border-left: 1px solid var(--gray-600); }\n.sd2-feature-card { display: block; padding: 0; border: 1px solid var(--gray-300); text-align: left; }\n.sd2-feature-card summary { display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 22px 24px; cursor: pointer; list-style: none; }\n.sd2-feature-card summary::-webkit-details-marker { display: none; }\n.sd2-feature-card summary h4 { margin: 0; font-size: 1.12rem; }\n.disclosure-arrow { width: 22px; height: 22px; flex: 0 0 22px; fill: none; stroke: currentColor; stroke-width: 1.8; transition: transform .2s; }\n.sd2-feature-card[open] .disclosure-arrow { transform: rotate(180deg); }\n.service-answer { padding: 0 24px 24px; }\n.service-answer p { padding-top: 18px; border-top: 1px solid var(--gray-300); font-size: 1rem; }\n.sd2-slider-btn svg,.sd2-expand-btn svg { width: 1.25em; height: 1.25em; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }\n.sd2-expand-btn:focus-visible { outline: 3px solid var(--brand); outline-offset: 3px; }\n.accordion-panel { transition: flex .6s, outline .2s; }\n.accordion-panel.is-open { flex: 4; }\n.accordion-panel.is-open .accordion-content { opacity: 1; }\n.accordion-panel.is-open .vertical-title { opacity: 0; }\n.accordion-panel:focus-visible { outline: 3px solid var(--brand); outline-offset: 4px; }\n.testimonials { background: var(--gray-50); }\n.test-controls { display: flex; justify-content: center; margin: -20px 0 30px; }\n.test-pause { padding: 10px 18px; border-radius: var(--radius); border: 1px solid var(--gray-300); color: var(--text-dark); background: transparent; font-size: .9rem; }\n.test-columns { display: grid; grid-template-columns: repeat(3,minmax(0,1fr)); gap: 24px; height: 580px; overflow: hidden; mask-image: linear-gradient(to bottom,transparent,var(--black) 6%,var(--black) 94%,transparent); }\n.test-col { min-width: 0; }\n.test-col-inner { animation: review-scroll 32s linear infinite; }\n.test-col-inner.reverse { animation-direction: reverse; animation-duration: 36s; }\n.test-group { display: flex; flex-direction: column; gap: 24px; padding-bottom: 24px; }\n.test-card { min-height: 265px; padding: 28px 24px; border: 1px solid var(--gray-300); }\n.test-author { border-top: 1px solid var(--gray-400); margin-top: 4px; }\n.test-author-info { min-width: 0; gap: 10px; }\n.test-avatar { flex: 0 0 40px; width: 40px; height: 40px; font-size: .75rem; }\n.test-name { min-width: 0; overflow-wrap: anywhere; }\n.test-name h5 { font-size: .95rem; }\n.test-name span { font-size: .8rem; }\n.test-columns:hover .test-col-inner,.test-columns:focus-within .test-col-inner,.test-columns.paused .test-col-inner { animation-play-state: paused; }\n@keyframes review-scroll { to { transform: translateY(-50%); } }\n.review-anchor { display: block; height: 0; }\n#uf-5 .section-header { max-width: 740px; margin-left: auto; margin-right: auto; }\n.uf-timeline { display: grid; grid-template-columns: repeat(4,minmax(0,1fr)); gap: 24px; max-width: none; position: relative; }\n.uf-timeline::before { content: ''; position: absolute; left: 24px; right: 24px; top: 29px; height: 1px; background: var(--gray-400); }\n.uf-timeline-item { display: flex; flex-direction: column; gap: 24px; position: relative; }\n.uf-timeline-dot { width: 60px; height: 60px; border: 7px solid var(--gray-50); border-radius: 50%; z-index: 1; font-size: .95rem; flex: 0 0 60px; }\n.uf-timeline-item>div:last-child { flex: 1; width: 100%; border: 1px solid var(--gray-300); border-radius: var(--radius); padding: 26px 22px; background: var(--gray-100); }\n.uf-timeline-item h3 { font-size: 1.1rem; margin-bottom: 14px; }\n.uf-timeline-item p { font-size: .95rem; margin: 0; }\n.widget-phone { bottom: 158px; right: 24px; width: 52px; height: 52px; }\n.widget-phone .icon-wrapper { min-width: 52px; height: 52px; }\n.widget-phone svg,.chat-toggle svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }\n.widget-phone:focus-visible { width: 220px; }\n.widget-phone:focus-visible .text-wrapper { opacity: 1; }\n.widget-chat { position: fixed; right: 24px; bottom: 92px; z-index: 1060; }\n.chat-toggle { width: 52px; height: 52px; border: 1px solid var(--brand-dark); border-radius: 50%; display: flex; align-items: center; justify-content: center; color: var(--text-light); background: var(--brand); }\n.chat-window { position: absolute; right: 0; bottom: 0; width: min(390px,calc(100vw - 32px)); max-height: calc(100dvh - 120px); overflow-y: auto; border: 1px solid var(--gray-400); border-radius: var(--radius); background: var(--gray-100); box-shadow: 0 14px 40px #0003; }\n.chat-header { position: relative; padding: 26px 48px 22px 24px; background: var(--brand-dark); color: var(--text-light); }\n.chat-header h3 { color: var(--text-light); font-size: 1.25rem; margin: 0 0 8px; }\n.chat-header p { margin: 0; font-size: .9rem; }\n.chat-close { position: absolute; right: 10px; top: 10px; width: 36px; height: 36px; background: transparent; color: var(--text-light); border: 0; font-size: 26px; }\n.chat-body { display: flex; flex-direction: column; padding: 24px; gap: 12px; }\n.chat-body label { font-size: .9rem; font-weight: 600; color: var(--text-dark); }\n.chat-body input,.chat-body textarea { width: 100%; min-width: 0; padding: 12px; border: 1px solid var(--gray-400); border-radius: var(--radius); background: transparent; color: var(--text-dark); }\n.chat-body textarea { resize: vertical; min-height: 90px; }\n.chat-body .btn { padding: 12px; margin-top: 8px; }\n.chat-status { margin: 0; font-size: .85rem; }\n@media(max-width:991px) {\n #hero { padding-top: 150px; }\n #hero .hero-text { padding-top: 0; }\n #hero .subtitle { margin-left: auto; margin-right: auto; }\n .test-columns { gap: 14px; }\n .test-card { padding: 24px 16px; }\n .test-author { flex-wrap: wrap; }\n .uf-timeline { grid-template-columns: repeat(2,minmax(0,1fr)); gap: 28px; }\n .uf-timeline::before { display: none; }\n}\n@media(max-width:767px) {\n #hero { padding-top: 140px; padding-bottom: 56px; }\n .trust-item+.trust-item { border-left: 0; border-top: 1px solid var(--gray-600); padding-top: 28px; }\n .test-columns { grid-template-columns: minmax(0,1fr); height: auto; overflow: visible; mask-image: none; }\n .test-col-inner { animation: none; }\n .test-clone { display: none; }\n .test-controls { display: none; }\n .test-card { min-height: 0; padding: 26px; }\n .test-author { flex-wrap: nowrap; }\n .test-group { gap: 16px; padding-bottom: 0; }\n .test-columns { gap: 16px; }\n .uf-timeline { grid-template-columns: minmax(0,1fr); gap: 24px; }\n .uf-timeline::before { display: block; left: 25px; top: 26px; bottom: 26px; right: auto; width: 1px; height: auto; }\n .uf-timeline-item { display: grid; grid-template-columns: 52px minmax(0,1fr); gap: 14px; align-items: start; }\n .uf-timeline-dot { width: 52px; height: 52px; border-width: 6px; }\n .uf-timeline-item>div:last-child { padding: 22px 18px; }\n .accordion-panel .vertical-title { width: calc(100% - 24px); max-width: 100%; white-space: normal; overflow-wrap: anywhere; text-align: center; line-height: 1.2; transform: translate(-50%,-50%); background: var(--gray-800); padding: 6px 10px; border-radius: var(--radius); }\n .widget-phone,.widget-chat { right: 16px; }\n .sd2-feature-card summary { padding: 20px; }\n .service-answer { padding: 0 20px 20px; }\n}\n@media(max-width:767px) {\n .experience-badge { left: 0; right: 0; width: 100%; max-width: 100%; display: grid; grid-template-columns: minmax(0,1fr); padding: 16px; gap: 8px; }\n .experience-badge h3 { font-size: clamp(1.8rem, 9vw, 2.3rem); }\n .experience-badge p { min-width: 0; overflow-wrap: anywhere; }\n #uf-3 .uf-table-wrap { overflow: visible; }\n #uf-3 .uf-table { display: block; width: 100%; min-width: 0; border-collapse: separate; }\n #uf-3 .uf-table thead { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }\n #uf-3 .uf-table tbody { display: grid; gap: 16px; }\n #uf-3 .uf-table tr { display: block; padding: 12px 16px; border: 1px solid var(--gray-300); border-radius: var(--radius); background: var(--gray-100); }\n #uf-3 .uf-table td { display: grid; grid-template-columns: minmax(0,.85fr) minmax(0,1.15fr); gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--gray-300); overflow-wrap: anywhere; }\n #uf-3 .uf-table td:last-child { border-bottom: 0; }\n #uf-3 .uf-table td::before { content: attr(data-label); color: var(--text-dark); font-weight: 700; }\n}\n@media(prefers-reduced-motion:reduce) {\n .test-columns { height: auto; overflow: visible; mask-image: none; }\n .test-col-inner { animation: none; }\n .test-clone,.test-controls { display: none; }\n .disclosure-arrow { transition: none; }\n}\n\n/* Compact hero calculator overrides, append after base v1 styles. */\n:root {\n --hero-card-bg:#fff;\n --hero-card-border:#ddd;\n --hero-card-shadow:#0000000c;\n --hero-muted:#555;\n --hero-tag-bg:#eee;\n --hero-text:#333;\n --hero-selected:#222;\n --hero-selected-bg:#f2f2f2;\n --hero-input-border:#ccc;\n --hero-heading:#222;\n --hero-subtle:#666;\n}\n#arkalkulator.hero-calculator { width:100%; max-width:540px; min-width:0; margin-inline:auto; scroll-margin-top:110px; }\n#arkalkulator .v1-card { width:100%; padding:26px; background:var(--hero-card-bg); border:1px solid var(--hero-card-border); box-shadow:0 16px 44px var(--hero-card-shadow); }\n#arkalkulator .v1-card-heading { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:22px; }\n#arkalkulator .v1-eyebrow { font-size:12px; font-weight:700; color:var(--hero-muted); overflow-wrap:anywhere; }\n#arkalkulator .v1-demo-tag { padding:3px 9px; border-radius:4px; font-size:11px; font-weight:700; background:var(--hero-tag-bg); color:var(--hero-muted); }\n#arkalkulator .v1-progress { margin-bottom:22px; }\n#arkalkulator .v1-step-indicator { width:32px; height:32px; font-size:12px; border-width:3px; }\n#arkalkulator .v1-step h3 { font-size:clamp(18px,2vw,23px); line-height:1.25; margin-bottom:10px; text-align:left; }\n#arkalkulator .v1-description { font-size:13px; line-height:1.5; margin-bottom:18px; color:var(--hero-subtle); }\n#arkalkulator .v1-grid { grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px; margin-bottom:0; }\n#arkalkulator .v1-option { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:10px; padding:18px 10px; min-height:94px; font:inherit; border-radius:8px; border-width:1px; color:var(--hero-text); }\n#arkalkulator .v1-option svg { width:22px; height:22px; flex:none; }\n#arkalkulator .v1-option span { font-size:12px; line-height:1.4; overflow-wrap:anywhere; }\n#arkalkulator .v1-option.selected { border-color:var(--hero-selected); box-shadow:inset 0 0 0 1px var(--hero-selected); background:var(--hero-selected-bg); }\n#arkalkulator .v1-actions { margin-top:18px; padding-top:18px; gap:10px; flex-wrap:wrap; }\n#arkalkulator .v1-actions-end { justify-content:flex-end; }\n#arkalkulator .btn { padding:12px 16px; min-height:44px; font-size:12px; white-space:normal; text-align:center; }\n#arkalkulator button:disabled { opacity:.45; cursor:not-allowed; }\n#arkalkulator :is(button,input):focus-visible { outline:3px solid var(--hero-muted); outline-offset:3px; }\n#arkalkulator h3:focus { outline:none; }\n#arkalkulator label { display:block; font-size:12px; font-weight:600; margin:12px 0 6px; }\n#arkalkulator input:not([type=range]) { width:100%; min-width:0; min-height:42px; border:1px solid var(--hero-input-border); border-radius:6px; background:var(--hero-card-bg); padding:9px 12px; font:inherit; font-size:14px; color:var(--hero-heading); }\n#arkalkulator .v1-size-row { display:flex; align-items:center; gap:16px; margin-bottom:16px; }\n#arkalkulator .v1-size-row input { width:110px; }\n#arkalkulator #v1-area-val { font-size:22px; font-weight:700; color:var(--hero-heading); }\n#arkalkulator #v1-area { width:100%; accent-color:var(--hero-text); }\n#arkalkulator .v1-range-labels { display:flex; justify-content:space-between; font-size:11px; color:var(--hero-subtle); }\n#arkalkulator .v1-result-box { padding:20px 14px; margin-bottom:16px; }\n#arkalkulator .v1-result-box h4 { font-size:10px; }\n#arkalkulator .v1-result-box .price { font-size:clamp(26px,4vw,36px); line-height:1.2; overflow-wrap:anywhere; }\n#arkalkulator .v1-result-box p,#arkalkulator .v1-demo-note { font-size:11px; line-height:1.5; }\n#arkalkulator .v1-demo-note { margin:12px 0 0; color:var(--hero-subtle); }\n#arkalkulator .v1-done { padding:18px 0; }\n#arkalkulator .v1-done p { font-size:14px; margin-bottom:18px; }\n@media(max-width:480px) { #arkalkulator .v1-card { padding:20px 16px; } #arkalkulator .v1-option { padding:15px 8px; } }\n@media(prefers-reduced-motion:reduce) { #arkalkulator *,#arkalkulator *::before { animation:none!important; transition:none!important; } }\n</style>\n</head>\n<body>\n<header class=\"header-sticky-wrapper\" data-block=\"1\" id=\"headerWrapper\">\n<div class=\"top-bar\" data-section-id=\"S1\">\n<div class=\"container top-bar-inner\">\n<div class=\"d-flex gap-20 align-items-center\">\n<span id=\"S1\">S1 · <i class=\"ph ph-placeholder\"></i> [TEMPLATE: Cím, irányítószám és utca]</span>\n<span><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Nyitvatartás]</span>\n</div>\n<div class=\"d-flex gap-20 align-items-center\">\n<a href=\"tel:+3600000000\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Telefonszám]</a>\n<a href=\"/cdn-cgi/l/email-protection#a5d1c0c8d5c9c4d1c0e5c0ddc4c8d5c9c08bc6cac8\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: E-mail cím]</a>\n</div>\n</div>\n</div>\n<div class=\"header-main\" data-section-id=\"S2\">\n<div class=\"container\">\n<nav class=\"nav\">\n<a class=\"nav-logo-link\" href=\"#hero\">\n<span class=\"nav-logo-plaque\"><img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"nav-logo-img\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/></span>\n</a>\n<div class=\"nav-links\">\n<a href=\"#rolunk\" id=\"S2\">S2 · [TEMPLATE: Menüpont 1]</a>\n<a href=\"#szolgaltatasok\">[TEMPLATE: Menüpont 2]</a>\n<a href=\"#munkafolyamat\">[TEMPLATE: Menüpont 3]</a>\n<a href=\"#velemenyek\">[TEMPLATE: Menüpont 4]</a>\n<a href=\"#arkalkulator\">[TEMPLATE: Menüpont 5]</a>\n</div>\n<div class=\"nav-cta\">\n<a class=\"btn btn-primary\" href=\"#ajanlat\">[TEMPLATE: Fő CTA, 2-3 szó]</a>\n</div>\n<button aria-expanded=\"false\" aria-label=\"Menü\" class=\"mobile-menu-btn\" onclick=\"toggleMobileMenu()\" type=\"button\"><i class=\"ph ph-placeholder\"></i></button>\n</nav>\n</div>\n<div class=\"mobile-menu\" id=\"mobile-menu\">\n<a href=\"#rolunk\">[TEMPLATE: Menüpont 1]</a>\n<a href=\"#szolgaltatasok\">[TEMPLATE: Menüpont 2]</a>\n<a href=\"#munkafolyamat\">[TEMPLATE: Menüpont 3]</a>\n<a href=\"#velemenyek\">[TEMPLATE: Menüpont 4]</a>\n<a href=\"#ajanlat\">[TEMPLATE: Fő CTA, 2-3 szó]</a>\n</div>\n</div>\n</header>\n<header class=\"hero\" data-block=\"2\" data-section-id=\"S3\" id=\"hero\">\n<div class=\"container\">\n<div class=\"hero-grid\">\n<div class=\"hero-text reveal\">\n<div class=\"pill-badge\"><span class=\"highlight\">[TEMPLATE: Címke]</span> [TEMPLATE: Rövid kiemelés, 3-5 szó]</div>\n<h1 id=\"S3\">S3 · [TEMPLATE: Hero cím, 6-9 szó, fő kulcsszóval]</h1>\n<p class=\"subtitle\">[TEMPLATE: Pozicionáló mondat a saját oldalról, 15-25 szó]</p>\n<div class=\"hero-actions\">\n<a class=\"btn btn-brand\" href=\"#ajanlat\">[TEMPLATE: Elsődleges CTA]</a>\n<a class=\"btn-play\" href=\"#szolgaltatasok\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Másodlagos CTA]</a>\n</div>\n<div class=\"hero-reviews\">\n<div class=\"review-avatars\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n<div class=\"review-stars\">\n<div class=\"stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<span>[TEMPLATE: Értékelés száma és darabszáma]</span>\n</div>\n</div>\n</div>\n<div aria-labelledby=\"v1-title\" class=\"hero-calculator\" data-block=\"17\" id=\"arkalkulator\">\n<div class=\"v1-card\">\n<div class=\"v1-card-heading\"><span class=\"v1-eyebrow\">[TEMPLATE: Kalkulátor neve]</span><span class=\"v1-demo-tag\">Demó</span></div>\n<div aria-label=\"Kalkulátor lépései\" class=\"v1-progress\">\n<div class=\"v1-progress-bar\" id=\"v1-bar\" style=\"width:0%\"></div>\n<span aria-current=\"step\" aria-label=\"1. Választás\" class=\"v1-step-indicator active\" id=\"v1-ind-1\">1</span>\n<span aria-label=\"2. Mennyiség\" class=\"v1-step-indicator\" id=\"v1-ind-2\">2</span>\n<span aria-label=\"3. Eredmény\" class=\"v1-step-indicator\" id=\"v1-ind-3\">3</span>\n<span aria-label=\"4. Ellenőrzés\" class=\"v1-step-indicator\" id=\"v1-ind-4\">4</span>\n</div>\n<div class=\"v1-step active\" id=\"v1-step-1\">\n<h3 id=\"v1-title\" tabindex=\"-1\">Válasszon egy lehetőséget</h3>\n<p class=\"v1-description\">[TEMPLATE: Rövid útmutató a választáshoz]</p>\n<div aria-label=\"Elérhető lehetőségek\" class=\"v1-grid\">\n<button aria-pressed=\"false\" class=\"v1-option\" data-v1-option=\"0\" onclick=\"v1SelectType(this)\" type=\"button\"><svg aria-hidden=\"true\" fill=\"none\" height=\"22\" stroke=\"currentColor\" stroke-width=\"1.5\" viewbox=\"0 0 24 24\" width=\"22\"><rect height=\"16\" rx=\"2\" width=\"16\" x=\"4\" y=\"4\"></rect></svg><span>[TEMPLATE: Opció 1]</span></button>\n<button aria-pressed=\"false\" class=\"v1-option\" data-v1-option=\"1\" onclick=\"v1SelectType(this)\" type=\"button\"><svg aria-hidden=\"true\" fill=\"none\" height=\"22\" stroke=\"currentColor\" stroke-width=\"1.5\" viewbox=\"0 0 24 24\" width=\"22\"><rect height=\"16\" rx=\"2\" width=\"16\" x=\"4\" y=\"4\"></rect><path d=\"M12 4v16\"></path></svg><span>[TEMPLATE: Opció 2]</span></button>\n<button aria-pressed=\"false\" class=\"v1-option\" data-v1-option=\"2\" onclick=\"v1SelectType(this)\" type=\"button\"><svg aria-hidden=\"true\" fill=\"none\" height=\"22\" stroke=\"currentColor\" stroke-width=\"1.5\" viewbox=\"0 0 24 24\" width=\"22\"><rect height=\"16\" rx=\"2\" width=\"16\" x=\"4\" y=\"4\"></rect><path d=\"M4 12h16\"></path></svg><span>[TEMPLATE: Opció 3]</span></button>\n<button aria-pressed=\"false\" class=\"v1-option\" data-v1-option=\"3\" onclick=\"v1SelectType(this)\" type=\"button\"><svg aria-hidden=\"true\" fill=\"none\" height=\"22\" stroke=\"currentColor\" stroke-width=\"1.5\" viewbox=\"0 0 24 24\" width=\"22\"><rect height=\"16\" rx=\"2\" width=\"16\" x=\"4\" y=\"4\"></rect><path d=\"M4 12h16M12 4v16\"></path></svg><span>[TEMPLATE: Opció 4]</span></button>\n</div>\n<div class=\"v1-actions v1-actions-end\"><button class=\"btn btn-primary\" disabled=\"\" id=\"v1-btn-1\" onclick=\"v1Next(2)\" type=\"button\">Tovább a mennyiséghez →</button></div>\n</div>\n<div class=\"v1-step\" id=\"v1-step-2\">\n<h3 tabindex=\"-1\">Adja meg a mennyiséget</h3>\n<p class=\"v1-description\">[TEMPLATE: A méret vagy mennyiség magyarázata]</p>\n<label for=\"v1-area-number\">Mennyiség (m²)</label>\n<div class=\"v1-size-row\"><input id=\"v1-area-number\" inputmode=\"numeric\" max=\"150\" min=\"1\" oninput=\"v1UpdateSlider(this)\" step=\"1\" type=\"number\" value=\"20\"/><output for=\"v1-area v1-area-number\" id=\"v1-area-val\">20 m²</output></div>\n<input aria-label=\"Mennyiség négyzetméterben\" id=\"v1-area\" max=\"150\" min=\"1\" oninput=\"v1UpdateSlider(this)\" step=\"1\" type=\"range\" value=\"20\"/>\n<div class=\"v1-range-labels\"><span>1 m²</span><span>150 m²</span></div>\n<div class=\"v1-actions\"><button class=\"btn btn-outline\" onclick=\"v1Next(1)\" type=\"button\">Vissza</button><button class=\"btn btn-primary\" onclick=\"v1Next(3)\" type=\"button\">Eredmény →</button></div>\n</div>\n<div class=\"v1-step\" id=\"v1-step-3\">\n<h3 tabindex=\"-1\">Becsült eredmény</h3>\n<div class=\"v1-result-box\"><h4>Bemutató kalkuláció</h4><div class=\"price\" id=\"v1-final-price\">0 Ft</div><p>Demó árakkal számolva. Nem minősül ajánlatnak.</p></div>\n<form id=\"v1-form\" novalidate=\"\" onsubmit=\"event.preventDefault();v1Submit()\">\n<p class=\"calc-error\" hidden=\"\" id=\"v1-error\" role=\"alert\">Adjon meg nevet és érvényes e-mail-címet.</p>\n<label for=\"v1-name\">Név *</label><input autocomplete=\"name\" id=\"v1-name\" required=\"\" type=\"text\"/>\n<label for=\"v1-email\">E-mail-cím *</label><input autocomplete=\"email\" id=\"v1-email\" required=\"\" type=\"email\"/>\n<label for=\"v1-phone\">Telefonszám (opcionális)</label><input autocomplete=\"tel\" id=\"v1-phone\" type=\"tel\"/>\n<p class=\"v1-demo-note\">A demó helyben ellenőrzi az adatokat, nem küldi el őket.</p>\n<div class=\"v1-actions\"><button class=\"btn btn-outline\" onclick=\"v1Next(2)\" type=\"button\">Vissza</button><button class=\"btn btn-primary\" type=\"submit\">Demó ellenőrzése</button></div>\n</form>\n</div>\n<div class=\"v1-step\" id=\"v1-step-4\"><div class=\"v1-done\"><h3 tabindex=\"-1\">Az ellenőrzés sikerült</h3><p>Ez egy bemutató. Az adatokat nem küldtük el.</p><button class=\"btn btn-outline\" onclick=\"v1Next(3)\" type=\"button\">Vissza az eredményhez</button></div></div>\n</div>\n</div>\n</div>\n</div>\n</header>\n<section class=\"trust-badges\" data-block=\"3\" data-section-id=\"S4\" id=\"bizalom\">\n<div class=\"container trust-grid reveal\">\n<div class=\"trust-item\"><strong aria-label=\"120, mintaérték\" class=\"trust-count\" data-count=\"120\">0</strong><span id=\"S4\">S4 · [TEMPLATE: Igazolt tény 1]</span></div>\n<div class=\"trust-item\"><strong aria-label=\"15, mintaérték\" class=\"trust-count\" data-count=\"15\">0</strong><span>[TEMPLATE: Igazolt tény 2]</span></div>\n<div class=\"trust-item\"><strong aria-label=\"98, mintaérték\" class=\"trust-count\" data-count=\"98\">0</strong><span>[TEMPLATE: Igazolt tény 3]</span></div>\n</div>\n</section>\n<section class=\"config-section\" data-block=\"18\" data-section-id=\"S5\" id=\"konfigurator\">\n<div class=\"container\">\n<div class=\"section-header text-center\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S5\">S5 · [TEMPLATE: Konfigurátor cím, 3-6 szó]</h2>\n</div>\n<div class=\"v3-wrapper reveal\">\n<div class=\"v3-left\">\n<h3>[TEMPLATE: Összegzés címe]</h3>\n<p>[TEMPLATE: Összegzés felvezetése, 15-25 szó]</p>\n<div class=\"v3-summary-box\">\n<div class=\"v3-summary-item\">\n<span class=\"v3-summary-label\">[TEMPLATE: 1. adat neve]</span>\n<span class=\"v3-summary-value\" id=\"v3-sum-type\">[TEMPLATE: Üres érték jele]</span>\n</div>\n<div class=\"v3-summary-item\">\n<span class=\"v3-summary-label\">[TEMPLATE: 2. adat neve]</span>\n<span class=\"v3-summary-value\" id=\"v3-sum-base\">[TEMPLATE: Üres érték jele]</span>\n</div>\n<div class=\"v3-summary-item\">\n<span class=\"v3-summary-label\">[TEMPLATE: 3. adat neve]</span>\n<span class=\"v3-summary-value\" id=\"v3-sum-size\">10 m²</span>\n</div>\n<div class=\"v3-total-wrap\">\n<span class=\"v3-total-label\">[TEMPLATE: Irányár felirata]</span>\n<div class=\"v3-total\" id=\"v3-sum-price\">0 Ft</div>\n</div>\n</div>\n</div>\n<div class=\"v3-right\">\n<div class=\"v3-step-container active\" id=\"v3-cont-1\">\n<div class=\"v3-step-header\" onclick=\"v3Toggle(1)\">\n<h4><span class=\"v3-step-num\">1</span> [TEMPLATE: 1. konfigurátor kérdés]</h4>\n<i class=\"ph ph-placeholder status-icon\"></i>\n</div>\n<div class=\"v3-step-body\">\n<div class=\"v3-radio-grid\">\n<label class=\"v3-radio-label\">\n<input data-v3-option=\"0\" name=\"v3-type\" onchange=\"v3UpdateType(this)\" type=\"radio\" value=\"[TEMPLATE: Típus 1]\"/>\n<span class=\"v3-radio-title\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Típus 1]</span>\n<span class=\"v3-radio-desc\">[TEMPLATE: Típus 1 magyarázata, 4-8 szó]</span>\n</label>\n<label class=\"v3-radio-label\">\n<input data-v3-option=\"1\" name=\"v3-type\" onchange=\"v3UpdateType(this)\" type=\"radio\" value=\"[TEMPLATE: Típus 2]\"/>\n<span class=\"v3-radio-title\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Típus 2]</span>\n<span class=\"v3-radio-desc\">[TEMPLATE: Típus 2 magyarázata, 4-8 szó]</span>\n</label>\n<label class=\"v3-radio-label\">\n<input data-v3-option=\"2\" name=\"v3-type\" onchange=\"v3UpdateType(this)\" type=\"radio\" value=\"[TEMPLATE: Típus 3]\"/>\n<span class=\"v3-radio-title\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Típus 3]</span>\n<span class=\"v3-radio-desc\">[TEMPLATE: Típus 3 magyarázata, 4-8 szó]</span>\n</label>\n<label class=\"v3-radio-label\">\n<input data-v3-option=\"3\" name=\"v3-type\" onchange=\"v3UpdateType(this)\" type=\"radio\" value=\"[TEMPLATE: Típus 4]\"/>\n<span class=\"v3-radio-title\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Típus 4]</span>\n<span class=\"v3-radio-desc\">[TEMPLATE: Típus 4 magyarázata, 4-8 szó]</span>\n</label>\n</div>\n</div>\n</div>\n<div class=\"v3-step-container\" id=\"v3-cont-2\">\n<div class=\"v3-step-header\" onclick=\"v3Toggle(2)\">\n<h4><span class=\"v3-step-num\">2</span> [TEMPLATE: 2. konfigurátor kérdés]</h4>\n<i class=\"ph ph-placeholder status-icon\"></i>\n</div>\n<div class=\"v3-step-body\">\n<div class=\"v3-radio-grid\">\n<label class=\"v3-radio-label\">\n<input data-v3-base=\"0\" name=\"v3-base\" onchange=\"v3UpdateBase(this)\" type=\"radio\" value=\"[TEMPLATE: Alap 1]\"/>\n<span class=\"v3-radio-title\">[TEMPLATE: Alap 1]</span>\n<span class=\"v3-radio-desc\">[TEMPLATE: Alap 1 magyarázata, 4-8 szó]</span>\n</label>\n<label class=\"v3-radio-label\">\n<input data-v3-base=\"1\" name=\"v3-base\" onchange=\"v3UpdateBase(this)\" type=\"radio\" value=\"[TEMPLATE: Alap 2]\"/>\n<span class=\"v3-radio-title\">[TEMPLATE: Alap 2]</span>\n<span class=\"v3-radio-desc\">[TEMPLATE: Alap 2 magyarázata, 4-8 szó]</span>\n</label>\n<label class=\"v3-radio-label\">\n<input data-v3-base=\"2\" name=\"v3-base\" onchange=\"v3UpdateBase(this)\" type=\"radio\" value=\"[TEMPLATE: Alap 3]\"/>\n<span class=\"v3-radio-title\">[TEMPLATE: Alap 3]</span>\n<span class=\"v3-radio-desc\">[TEMPLATE: Alap 3 magyarázata, 4-8 szó]</span>\n</label>\n<label class=\"v3-radio-label\">\n<input data-v3-base=\"3\" name=\"v3-base\" onchange=\"v3UpdateBase(this)\" type=\"radio\" value=\"[TEMPLATE: Alap 4]\"/>\n<span class=\"v3-radio-title\">[TEMPLATE: Alap 4]</span>\n<span class=\"v3-radio-desc\">[TEMPLATE: Alap 4 magyarázata, 4-8 szó]</span>\n</label>\n</div>\n</div>\n</div>\n<div class=\"v3-step-container\" id=\"v3-cont-3\">\n<div class=\"v3-step-header\" onclick=\"v3Toggle(3)\">\n<h4><span class=\"v3-step-num\">3</span> [TEMPLATE: 3. konfigurátor kérdés]</h4>\n<i class=\"ph ph-placeholder status-icon\"></i>\n</div>\n<div class=\"v3-step-body\">\n<div class=\"input-group\">\n<label for=\"v3-size-input\">[TEMPLATE: Mennyiség mező neve]</label>\n<input id=\"v3-size-input\" min=\"1\" oninput=\"v3UpdateSize(this.value)\" type=\"number\" value=\"10\"/>\n</div>\n<div class=\"calc-form-row\">\n<div class=\"input-group\">\n<label for=\"v3-name\">[TEMPLATE: Név mező]</label>\n<input id=\"v3-name\" placeholder=\"[TEMPLATE: Név mező]\" type=\"text\"/>\n</div>\n<div class=\"input-group\">\n<label for=\"v3-phone\">[TEMPLATE: Telefon mező]</label>\n<input id=\"v3-phone\" placeholder=\"[TEMPLATE: Telefon mező]\" type=\"tel\"/>\n</div>\n</div>\n<p class=\"calc-error\" hidden=\"\" id=\"v3-message\">[TEMPLATE: Visszajelző üzenet]</p>\n<button class=\"btn btn-primary\" onclick=\"v3Submit()\" style=\"width: 100%;\" type=\"button\">[TEMPLATE: Ajánlatkérés gomb] <i class=\"ph ph-placeholder\"></i></button>\n</div>\n</div>\n</div>\n</div>\n</div>\n</section><section class=\"service-detail bg-white\" data-block=\"4\" data-section-id=\"S6\" id=\"szolgaltatas-1\">\n<div class=\"container\">\n<h2 class=\"section-title sd2-mobile-title\" id=\"S6\">S6 · [TEMPLATE: Szolgáltatás 1 címe, egy magas szándékú kulcsszóval]</h2>\n<div class=\"sd2-service-grid\">\n<div class=\"sd2-service-gallery\">\n<button aria-controls=\"szolgaltatas-1-gallery-track\" aria-label=\"Előző kép\" class=\"sd2-slider-btn sd2-prev-btn\" onclick=\"sd2MoveGallery(this, -1)\" type=\"button\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"m15 5-7 7 7 7\"></path></svg></button>\n<button aria-controls=\"szolgaltatas-1-gallery-track\" aria-label=\"Következő kép\" class=\"sd2-slider-btn sd2-next-btn\" onclick=\"sd2MoveGallery(this, 1)\" type=\"button\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"m9 5 7 7-7 7\"></path></svg></button>\n<div class=\"sd2-gallery-track-wrapper\">\n<div class=\"sd2-gallery-track\" id=\"szolgaltatas-1-gallery-track\">\n<div class=\"sd2-gallery-item sd2-item-main img-wrapper\" data-lb-group=\"sd-1\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" data-cid=\"path:body&gt;section#szolgaltatas-1&gt;div&gt;div&gt;div:nth-of-type(1)&gt;div&gt;div&gt;div:nth-of-type(1)&gt;img\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div aria-label=\"Kép megnyitása nagy méretben\" class=\"sd2-expand-btn\" onclick=\"openLightbox('sd-1', 0)\" role=\"button\" tabindex=\"0\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M8 3H3v5M3 3l7 7M16 3h5v5m0-5-7 7M8 21H3v-5m0 5 7-7m6 7h5v-5m0 5-7-7\"></path></svg></div>\n</div>\n<div class=\"sd2-gallery-item img-wrapper\" data-lb-group=\"sd-1\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div aria-label=\"Kép megnyitása nagy méretben\" class=\"sd2-expand-btn\" onclick=\"openLightbox('sd-1', 1)\" role=\"button\" tabindex=\"0\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M8 3H3v5M3 3l7 7M16 3h5v5m0-5-7 7M8 21H3v-5m0 5 7-7m6 7h5v-5m0 5-7-7\"></path></svg></div>\n</div>\n<div class=\"sd2-gallery-item img-wrapper\" data-lb-group=\"sd-1\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div aria-label=\"Kép megnyitása nagy méretben\" class=\"sd2-expand-btn\" onclick=\"openLightbox('sd-1', 2)\" role=\"button\" tabindex=\"0\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M8 3H3v5M3 3l7 7M16 3h5v5m0-5-7 7M8 21H3v-5m0 5 7-7m6 7h5v-5m0 5-7-7\"></path></svg></div>\n</div>\n<div class=\"sd2-gallery-item img-wrapper\" data-lb-group=\"sd-1\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div aria-label=\"Kép megnyitása nagy méretben\" class=\"sd2-expand-btn\" onclick=\"openLightbox('sd-1', 3)\" role=\"button\" tabindex=\"0\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M8 3H3v5M3 3l7 7M16 3h5v5m0-5-7 7M8 21H3v-5m0 5 7-7m6 7h5v-5m0 5-7-7\"></path></svg></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sd2-content-side\">\n<div>\n<h2 class=\"section-title sd2-desktop-title\">S6 · [TEMPLATE: Szolgáltatás 1 címe, egy magas szándékú kulcsszóval]</h2>\n<p>[TEMPLATE: Szolgáltatás 1 leírása a saját oldalról, 40-60 szó, kulcsszavakkal]</p>\n</div>\n<div class=\"sd2-feature-cards\">\n<details class=\"sd2-feature-card\" data-cid=\"path:body&gt;section#szolgaltatas-1&gt;div&gt;div&gt;div:nth-of-type(2)&gt;div:nth-of-type(2)&gt;div:nth-of-type(1)\" open=\"\"><summary><h4>[TEMPLATE: Előny 1 címe]</h4><svg aria-hidden=\"true\" class=\"disclosure-arrow\" viewbox=\"0 0 24 24\"><path d=\"m6 9 6 6 6-6\"></path></svg></summary><div class=\"service-answer\"><p>[TEMPLATE: Előny 1 magyarázata, 15-25 szó]</p></div></details>\n<details class=\"sd2-feature-card\"><summary><h4>[TEMPLATE: Előny 2 címe]</h4><svg aria-hidden=\"true\" class=\"disclosure-arrow\" viewbox=\"0 0 24 24\"><path d=\"m6 9 6 6 6-6\"></path></svg></summary><div class=\"service-answer\"><p>[TEMPLATE: Előny 2 magyarázata, 15-25 szó]</p></div></details>\n</div>\n</div>\n</div>\n</div>\n</section>\n<section class=\"service-detail bg-alternate\" data-block=\"4\" data-section-id=\"S7\" id=\"szolgaltatas-2\">\n<div class=\"container\">\n<h2 class=\"section-title sd2-mobile-title\" id=\"S7\">S7 · [TEMPLATE: Szolgáltatás 2 címe, egy magas szándékú kulcsszóval]</h2>\n<div class=\"sd2-service-grid\">\n<div class=\"sd2-content-side\">\n<div>\n<h2 class=\"section-title sd2-desktop-title\">S7 · [TEMPLATE: Szolgáltatás 2 címe, egy magas szándékú kulcsszóval]</h2>\n<p>[TEMPLATE: Szolgáltatás 2 leírása a saját oldalról, 40-60 szó, kulcsszavakkal]</p>\n</div>\n<div class=\"sd2-feature-cards\">\n<details class=\"sd2-feature-card\" open=\"\"><summary><h4>[TEMPLATE: Előny 1 címe]</h4><svg aria-hidden=\"true\" class=\"disclosure-arrow\" viewbox=\"0 0 24 24\"><path d=\"m6 9 6 6 6-6\"></path></svg></summary><div class=\"service-answer\"><p>[TEMPLATE: Előny 1 magyarázata, 15-25 szó]</p></div></details>\n<details class=\"sd2-feature-card\"><summary><h4>[TEMPLATE: Előny 2 címe]</h4><svg aria-hidden=\"true\" class=\"disclosure-arrow\" viewbox=\"0 0 24 24\"><path d=\"m6 9 6 6 6-6\"></path></svg></summary><div class=\"service-answer\"><p>[TEMPLATE: Előny 2 magyarázata, 15-25 szó]</p></div></details>\n</div>\n</div>\n<div class=\"sd2-service-gallery\">\n<button aria-controls=\"szolgaltatas-2-gallery-track\" aria-label=\"Előző kép\" class=\"sd2-slider-btn sd2-prev-btn\" onclick=\"sd2MoveGallery(this, -1)\" type=\"button\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"m15 5-7 7 7 7\"></path></svg></button>\n<button aria-controls=\"szolgaltatas-2-gallery-track\" aria-label=\"Következő kép\" class=\"sd2-slider-btn sd2-next-btn\" onclick=\"sd2MoveGallery(this, 1)\" type=\"button\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"m9 5 7 7-7 7\"></path></svg></button>\n<div class=\"sd2-gallery-track-wrapper\">\n<div class=\"sd2-gallery-track\" id=\"szolgaltatas-2-gallery-track\">\n<div class=\"sd2-gallery-item sd2-item-main img-wrapper\" data-lb-group=\"sd-2\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div aria-label=\"Kép megnyitása nagy méretben\" class=\"sd2-expand-btn\" onclick=\"openLightbox('sd-2', 0)\" role=\"button\" tabindex=\"0\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M8 3H3v5M3 3l7 7M16 3h5v5m0-5-7 7M8 21H3v-5m0 5 7-7m6 7h5v-5m0 5-7-7\"></path></svg></div>\n</div>\n<div class=\"sd2-gallery-item img-wrapper\" data-lb-group=\"sd-2\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div aria-label=\"Kép megnyitása nagy méretben\" class=\"sd2-expand-btn\" onclick=\"openLightbox('sd-2', 1)\" role=\"button\" tabindex=\"0\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M8 3H3v5M3 3l7 7M16 3h5v5m0-5-7 7M8 21H3v-5m0 5 7-7m6 7h5v-5m0 5-7-7\"></path></svg></div>\n</div>\n<div class=\"sd2-gallery-item img-wrapper\" data-lb-group=\"sd-2\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div aria-label=\"Kép megnyitása nagy méretben\" class=\"sd2-expand-btn\" onclick=\"openLightbox('sd-2', 2)\" role=\"button\" tabindex=\"0\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M8 3H3v5M3 3l7 7M16 3h5v5m0-5-7 7M8 21H3v-5m0 5 7-7m6 7h5v-5m0 5-7-7\"></path></svg></div>\n</div>\n<div class=\"sd2-gallery-item img-wrapper\" data-lb-group=\"sd-2\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div aria-label=\"Kép megnyitása nagy méretben\" class=\"sd2-expand-btn\" onclick=\"openLightbox('sd-2', 3)\" role=\"button\" tabindex=\"0\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M8 3H3v5M3 3l7 7M16 3h5v5m0-5-7 7M8 21H3v-5m0 5 7-7m6 7h5v-5m0 5-7-7\"></path></svg></div>\n</div>\n</div>\n</div>\n</div>\n</div>\n</div>\n</section>\n<section class=\"service-detail bg-white\" data-block=\"4\" data-section-id=\"S8\" id=\"szolgaltatas-3\">\n<div class=\"container\">\n<h2 class=\"section-title sd2-mobile-title\" id=\"S8\">S8 · [TEMPLATE: Szolgáltatás 3 címe, egy magas szándékú kulcsszóval]</h2>\n<div class=\"sd2-service-grid\">\n<div class=\"sd2-service-gallery\">\n<button aria-controls=\"szolgaltatas-3-gallery-track\" aria-label=\"Előző kép\" class=\"sd2-slider-btn sd2-prev-btn\" onclick=\"sd2MoveGallery(this, -1)\" type=\"button\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"m15 5-7 7 7 7\"></path></svg></button>\n<button aria-controls=\"szolgaltatas-3-gallery-track\" aria-label=\"Következő kép\" class=\"sd2-slider-btn sd2-next-btn\" onclick=\"sd2MoveGallery(this, 1)\" type=\"button\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"m9 5 7 7-7 7\"></path></svg></button>\n<div class=\"sd2-gallery-track-wrapper\">\n<div class=\"sd2-gallery-track\" id=\"szolgaltatas-3-gallery-track\">\n<div class=\"sd2-gallery-item sd2-item-main img-wrapper\" data-lb-group=\"sd-3\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div aria-label=\"Kép megnyitása nagy méretben\" class=\"sd2-expand-btn\" onclick=\"openLightbox('sd-3', 0)\" role=\"button\" tabindex=\"0\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M8 3H3v5M3 3l7 7M16 3h5v5m0-5-7 7M8 21H3v-5m0 5 7-7m6 7h5v-5m0 5-7-7\"></path></svg></div>\n</div>\n<div class=\"sd2-gallery-item img-wrapper\" data-lb-group=\"sd-3\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div aria-label=\"Kép megnyitása nagy méretben\" class=\"sd2-expand-btn\" onclick=\"openLightbox('sd-3', 1)\" role=\"button\" tabindex=\"0\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M8 3H3v5M3 3l7 7M16 3h5v5m0-5-7 7M8 21H3v-5m0 5 7-7m6 7h5v-5m0 5-7-7\"></path></svg></div>\n</div>\n<div class=\"sd2-gallery-item img-wrapper\" data-lb-group=\"sd-3\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div aria-label=\"Kép megnyitása nagy méretben\" class=\"sd2-expand-btn\" onclick=\"openLightbox('sd-3', 2)\" role=\"button\" tabindex=\"0\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M8 3H3v5M3 3l7 7M16 3h5v5m0-5-7 7M8 21H3v-5m0 5 7-7m6 7h5v-5m0 5-7-7\"></path></svg></div>\n</div>\n<div class=\"sd2-gallery-item img-wrapper\" data-lb-group=\"sd-3\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div aria-label=\"Kép megnyitása nagy méretben\" class=\"sd2-expand-btn\" onclick=\"openLightbox('sd-3', 3)\" role=\"button\" tabindex=\"0\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M8 3H3v5M3 3l7 7M16 3h5v5m0-5-7 7M8 21H3v-5m0 5 7-7m6 7h5v-5m0 5-7-7\"></path></svg></div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sd2-content-side\">\n<div>\n<h2 class=\"section-title sd2-desktop-title\">S8 · [TEMPLATE: Szolgáltatás 3 címe, egy magas szándékú kulcsszóval]</h2>\n<p>[TEMPLATE: Szolgáltatás 3 leírása a saját oldalról, 40-60 szó, kulcsszavakkal]</p>\n</div>\n<div class=\"sd2-feature-cards\">\n<details class=\"sd2-feature-card\" open=\"\"><summary><h4>[TEMPLATE: Előny 1 címe]</h4><svg aria-hidden=\"true\" class=\"disclosure-arrow\" viewbox=\"0 0 24 24\"><path d=\"m6 9 6 6 6-6\"></path></svg></summary><div class=\"service-answer\"><p>[TEMPLATE: Előny 1 magyarázata, 15-25 szó]</p></div></details>\n<details class=\"sd2-feature-card\"><summary><h4>[TEMPLATE: Előny 2 címe]</h4><svg aria-hidden=\"true\" class=\"disclosure-arrow\" viewbox=\"0 0 24 24\"><path d=\"m6 9 6 6 6-6\"></path></svg></summary><div class=\"service-answer\"><p>[TEMPLATE: Előny 2 magyarázata, 15-25 szó]</p></div></details>\n</div>\n</div>\n</div>\n</div>\n</section>\n<section class=\"spotlight\" data-block=\"5\" data-section-id=\"S9\" id=\"kiemelt-szolgaltatas\">\n<div class=\"container\">\n<div class=\"hero-grid\">\n<div class=\"hero-visual\">\n<div class=\"target-wrapper\">\n<div class=\"ring ring-1\"></div>\n<div class=\"ring ring-2\">\n<div class=\"crosshair ch-top\"></div>\n<div class=\"crosshair ch-bottom\"></div>\n<div class=\"crosshair ch-left\"></div>\n<div class=\"crosshair ch-right\"></div>\n</div>\n<div class=\"ring ring-3\"></div>\n<div class=\"hero-image-circle\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n<div class=\"floating-icon fi-1\"><i class=\"ph ph-placeholder\"></i></div>\n<div class=\"floating-icon fi-2\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n</div>\n<div class=\"hero-text reveal\">\n<div class=\"pill-badge\"><span class=\"highlight\">[TEMPLATE: Címke]</span> [TEMPLATE: Rövid kiemelés, 3-5 szó]</div>\n<h2 class=\"section-title\" id=\"S9\">S9 · [TEMPLATE: Kiemelt szolgáltatás címe, 5-8 szó]</h2>\n<p class=\"subtitle\">[TEMPLATE: A zászlóshajó szolgáltatás bemutatása a saját oldalról, 30-50 szó]</p>\n<div class=\"hero-actions\">\n<a class=\"btn btn-brand\" href=\"#ajanlat\">[TEMPLATE: Elsődleges CTA]</a>\n<a class=\"btn-play\" href=\"#arkalkulator\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Másodlagos CTA]</a>\n</div>\n<div class=\"hero-reviews\">\n<div class=\"review-avatars\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n<div class=\"review-stars\">\n<div class=\"stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<span>[TEMPLATE: Értékelés száma és darabszáma]</span>\n</div>\n</div>\n</div>\n</div>\n</div>\n</section>\n<section class=\"stats-section\" data-block=\"6\" data-section-id=\"S10\" id=\"szamok\">\n<div class=\"container\">\n<div class=\"section-header text-center\">\n<h2 class=\"section-title dark-bg-text\" id=\"S10\">S10 · [TEMPLATE: Számok szekció címe, 4-7 szó]</h2>\n</div>\n<div class=\"stats-grid reveal\">\n<div class=\"stat-item\">\n<i class=\"ph ph-placeholder\"></i>\n<h3 class=\"dark-bg-text\">[TEMPLATE: Szám 1]</h3>\n<p class=\"dark-bg-text-sub\">[TEMPLATE: Szám 1 megnevezése]</p>\n</div>\n<div class=\"stat-item\">\n<i class=\"ph ph-placeholder\"></i>\n<h3 class=\"dark-bg-text\">[TEMPLATE: Szám 2]</h3>\n<p class=\"dark-bg-text-sub\">[TEMPLATE: Szám 2 megnevezése]</p>\n</div>\n<div class=\"stat-item\">\n<i class=\"ph ph-placeholder\"></i>\n<h3 class=\"dark-bg-text\">[TEMPLATE: Szám 3]</h3>\n<p class=\"dark-bg-text-sub\">[TEMPLATE: Szám 3 megnevezése]</p>\n</div>\n<div class=\"stat-item\">\n<i class=\"ph ph-placeholder\"></i>\n<h3 class=\"dark-bg-text\">[TEMPLATE: Szám 4]</h3>\n<p class=\"dark-bg-text-sub\">[TEMPLATE: Szám 4 megnevezése]</p>\n</div>\n</div>\n</div>\n</section>\n<section class=\"about-section\" data-block=\"7\" data-section-id=\"S11\" id=\"rolunk\">\n<div class=\"container about-grid\">\n<div class=\"about-img reveal\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"about-experience\">\n<i class=\"ph ph-placeholder\"></i>\n<p>[TEMPLATE: Rövid kiemelés a csapatról, 2-4 szó]</p>\n</div>\n</div>\n<div class=\"about-content\">\n<div class=\"section-header\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S11\">S11 · [TEMPLATE: Rólunk cím, 5-8 szó]</h2>\n</div>\n<p>[TEMPLATE: Bemutatkozás első bekezdése a saját oldalról, 40-60 szó]</p>\n<p>[TEMPLATE: Bemutatkozás második bekezdése a saját oldalról, 40-60 szó]</p>\n<div class=\"hero-actions\">\n<a class=\"btn btn-primary\" href=\"#ajanlat\">[TEMPLATE: Elsődleges CTA]</a>\n<a class=\"btn btn-outline\" href=\"#munkafolyamat\">[TEMPLATE: Másodlagos CTA]</a>\n</div>\n</div>\n</div>\n</section>\n<section class=\"foundation-section\" data-block=\"8\" data-section-id=\"S12\" id=\"miert-mi\">\n<div class=\"container foundation-grid\">\n<div class=\"foundation-images\">\n<div class=\"img-main-card\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n<div class=\"experience-badge\">\n<h3>[TEMPLATE: Kiemelt szám]</h3>\n<p>[TEMPLATE: A szám megnevezése]</p>\n</div>\n</div>\n<div class=\"foundation-text reveal\">\n<div class=\"pill-badge\"><span class=\"highlight\">[TEMPLATE: Címke]</span> [TEMPLATE: Rövid kiemelés, 3-5 szó]</div>\n<h2 class=\"section-title\" id=\"S12\">S12 · [TEMPLATE: Miért minket cím, 5-8 szó, kulcsszóval]</h2>\n<p>[TEMPLATE: Bevezető a saját oldal alapján, 30-45 szó]</p>\n<div class=\"service-select-grid\">\n<div class=\"service-select-card\">\n<i class=\"ph ph-placeholder\"></i>\n<span>[TEMPLATE: USP 1]</span>\n</div>\n<div class=\"service-select-card\">\n<i class=\"ph ph-placeholder\"></i>\n<span>[TEMPLATE: USP 2]</span>\n</div>\n<div class=\"service-select-card\">\n<i class=\"ph ph-placeholder\"></i>\n<span>[TEMPLATE: USP 3]</span>\n</div>\n<div class=\"service-select-card\">\n<i class=\"ph ph-placeholder\"></i>\n<span>[TEMPLATE: USP 4]</span>\n</div>\n</div>\n<ul class=\"foundation-list\">\n<li><i class=\"ph ph-placeholder\"></i><p>[TEMPLATE: Garancia vagy előny 1, 12-20 szó]</p></li>\n<li><i class=\"ph ph-placeholder\"></i><p>[TEMPLATE: Garancia vagy előny 2, 12-20 szó]</p></li>\n<li><i class=\"ph ph-placeholder\"></i><p>[TEMPLATE: Garancia vagy előny 3, 12-20 szó]</p></li>\n</ul>\n<a class=\"btn btn-outline\" href=\"#ajanlat\">[TEMPLATE: CTA szöveg]</a>\n</div>\n</div>\n</section>\n<section class=\"materials-section\" data-block=\"9\" data-section-id=\"S13\" id=\"anyagok\">\n<div class=\"container\">\n<div class=\"section-header text-center\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S13\">S13 · [TEMPLATE: Anyagok vagy csomagok cím, 4-7 szó]</h2>\n<p>[TEMPLATE: Egy mondatos bevezető, 15-25 szó]</p>\n</div>\n<div class=\"accordion-container reveal\">\n<div aria-controls=\"materials-panel-content-1\" aria-expanded=\"false\" class=\"accordion-panel\" data-material-index=\"1\" role=\"button\" tabindex=\"0\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"vertical-title\">[TEMPLATE: Panel 1 rövid neve]</div>\n<div class=\"accordion-content\" id=\"materials-panel-content-1\">\n<h4>[TEMPLATE: Panel 1 címe]</h4>\n<p>[TEMPLATE: Panel 1 leírása, 20-35 szó]</p>\n</div>\n</div>\n<div aria-controls=\"materials-panel-content-2\" aria-expanded=\"false\" class=\"accordion-panel\" data-material-index=\"2\" role=\"button\" tabindex=\"0\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"vertical-title\">[TEMPLATE: Panel 2 rövid neve]</div>\n<div class=\"accordion-content\" id=\"materials-panel-content-2\">\n<h4>[TEMPLATE: Panel 2 címe]</h4>\n<p>[TEMPLATE: Panel 2 leírása, 20-35 szó]</p>\n</div>\n</div>\n<div aria-controls=\"materials-panel-content-3\" aria-expanded=\"false\" class=\"accordion-panel\" data-material-index=\"3\" role=\"button\" tabindex=\"0\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"vertical-title\">[TEMPLATE: Panel 3 rövid neve]</div>\n<div class=\"accordion-content\" id=\"materials-panel-content-3\">\n<h4>[TEMPLATE: Panel 3 címe]</h4>\n<p>[TEMPLATE: Panel 3 leírása, 20-35 szó]</p>\n</div>\n</div>\n<div aria-controls=\"materials-panel-content-4\" aria-expanded=\"false\" class=\"accordion-panel\" data-material-index=\"4\" role=\"button\" tabindex=\"0\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"vertical-title\">[TEMPLATE: Panel 4 rövid neve]</div>\n<div class=\"accordion-content\" id=\"materials-panel-content-4\">\n<h4>[TEMPLATE: Panel 4 címe]</h4>\n<p>[TEMPLATE: Panel 4 leírása, 20-35 szó]</p>\n</div>\n</div>\n</div>\n</div>\n</section>\n<section class=\"services-dark\" data-block=\"10\" data-section-id=\"S14\" id=\"szolgaltatasok\">\n<div class=\"container\">\n<h2 class=\"section-title\" id=\"S14\">S14 · [TEMPLATE: Szolgáltatások cím, 5-8 szó, kulcsszóval]</h2>\n<div class=\"services-grid reveal\">\n<div class=\"service-card-ref\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"service-card-icon\"><i class=\"ph ph-placeholder\"></i></div>\n<div class=\"service-card-content\">\n<h4>[TEMPLATE: Szolgáltatás 1 neve]</h4>\n<p>[TEMPLATE: Szolgáltatás 1 rövid leírása, 15-25 szó]</p>\n<a href=\"#szolgaltatas-1\">[TEMPLATE: Link szöveg] <i class=\"ph ph-placeholder\"></i></a>\n</div>\n</div>\n<div class=\"service-card-ref\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"service-card-icon\"><i class=\"ph ph-placeholder\"></i></div>\n<div class=\"service-card-content\">\n<h4>[TEMPLATE: Szolgáltatás 2 neve]</h4>\n<p>[TEMPLATE: Szolgáltatás 2 rövid leírása, 15-25 szó]</p>\n<a href=\"#szolgaltatas-2\">[TEMPLATE: Link szöveg] <i class=\"ph ph-placeholder\"></i></a>\n</div>\n</div>\n<div class=\"service-card-ref\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"service-card-icon\"><i class=\"ph ph-placeholder\"></i></div>\n<div class=\"service-card-content\">\n<h4>[TEMPLATE: Szolgáltatás 3 neve]</h4>\n<p>[TEMPLATE: Szolgáltatás 3 rövid leírása, 15-25 szó]</p>\n<a href=\"#szolgaltatas-3\">[TEMPLATE: Link szöveg] <i class=\"ph ph-placeholder\"></i></a>\n</div>\n</div>\n<div class=\"service-card-ref\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"service-card-icon\"><i class=\"ph ph-placeholder\"></i></div>\n<div class=\"service-card-content\">\n<h4>[TEMPLATE: Szolgáltatás 4 neve]</h4>\n<p>[TEMPLATE: Szolgáltatás 4 rövid leírása, 15-25 szó]</p>\n<a href=\"#szolgaltatasok-reszletek\">[TEMPLATE: Link szöveg] <i class=\"ph ph-placeholder\"></i></a>\n</div>\n</div>\n</div>\n</div>\n</section>\n<section class=\"sticky-section\" data-block=\"11\" data-section-id=\"S15\" id=\"szolgaltatasok-reszletek\">\n<div class=\"container sticky-wrapper\">\n<div class=\"sticky-left\">\n<div class=\"section-header\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S15\">S15 · [TEMPLATE: Részletek cím, 4-7 szó]</h2>\n</div>\n<p>[TEMPLATE: Bevezető a részletekhez, 30-45 szó]</p>\n<a class=\"btn btn-primary\" href=\"#ajanlat\">[TEMPLATE: CTA szöveg]</a>\n</div>\n<div class=\"sticky-right\">\n<div class=\"scroll-card reveal\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"scroll-card-content\">\n<h3>[TEMPLATE: Részlet vagy GYIK kérdés 1]</h3>\n<p>[TEMPLATE: Válasz 1 a saját oldalról, 30-50 szó]</p>\n<div class=\"scroll-feature-list\">\n<span class=\"scroll-feature-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Kiemelés 1]</span>\n<span class=\"scroll-feature-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Kiemelés 2]</span>\n</div>\n</div>\n</div>\n<div class=\"scroll-card reveal\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"scroll-card-content\">\n<h3>[TEMPLATE: Részlet vagy GYIK kérdés 2]</h3>\n<p>[TEMPLATE: Válasz 2 a saját oldalról, 30-50 szó]</p>\n<div class=\"scroll-feature-list\">\n<span class=\"scroll-feature-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Kiemelés 1]</span>\n<span class=\"scroll-feature-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Kiemelés 2]</span>\n</div>\n</div>\n</div>\n<div class=\"scroll-card reveal\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"scroll-card-content\">\n<h3>[TEMPLATE: Részlet vagy GYIK kérdés 3]</h3>\n<p>[TEMPLATE: Válasz 3 a saját oldalról, 30-50 szó]</p>\n<div class=\"scroll-feature-list\">\n<span class=\"scroll-feature-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Kiemelés 1]</span>\n<span class=\"scroll-feature-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Kiemelés 2]</span>\n</div>\n</div>\n</div>\n<div class=\"scroll-card reveal\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"scroll-card-content\">\n<h3>[TEMPLATE: Részlet vagy GYIK kérdés 4]</h3>\n<p>[TEMPLATE: Válasz 4 a saját oldalról, 30-50 szó]</p>\n<div class=\"scroll-feature-list\">\n<span class=\"scroll-feature-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Kiemelés 1]</span>\n<span class=\"scroll-feature-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Kiemelés 2]</span>\n</div>\n</div>\n</div>\n</div>\n</div>\n</section>\n<section class=\"process-section\" data-block=\"12\" data-section-id=\"S16\" id=\"munkafolyamat\">\n<div class=\"container\">\n<div class=\"pill-badge\"><span class=\"highlight\">[TEMPLATE: Címke]</span> [TEMPLATE: Rövid kiemelés, 3-5 szó]</div>\n<h2 class=\"section-title\" id=\"S16\">S16 · [TEMPLATE: Munkafolyamat cím, 4-7 szó]</h2>\n<div class=\"process-container reveal\" id=\"uf-1\">\n<div class=\"process-line\"></div>\n<div class=\"process-steps-grid\">\n<div class=\"process-step\">\n<div class=\"step-img-wrapper\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"step-number\">1</div>\n</div>\n<h4>[TEMPLATE: 1. lépés címe]</h4>\n<p>[TEMPLATE: 1. lépés leírása, 15-25 szó]</p>\n</div>\n<div class=\"process-step\">\n<div class=\"step-img-wrapper\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"step-number\">2</div>\n</div>\n<h4>[TEMPLATE: 2. lépés címe]</h4>\n<p>[TEMPLATE: 2. lépés leírása, 15-25 szó]</p>\n</div>\n<div class=\"process-step\">\n<div class=\"step-img-wrapper\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"step-number\">3</div>\n</div>\n<h4>[TEMPLATE: 3. lépés címe]</h4>\n<p>[TEMPLATE: 3. lépés leírása, 15-25 szó]</p>\n</div>\n</div>\n</div>\n</div>\n</section>\n<section class=\"testimonials\" data-block=\"13\" data-section-id=\"S17\" id=\"velemenyek\">\n<div class=\"container\">\n<div class=\"section-header text-center\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S17\">S17 · [TEMPLATE: Vélemények cím, 3-6 szó]</h2>\n</div>\n<div class=\"test-controls\"><button aria-controls=\"testimonial-columns\" aria-pressed=\"false\" class=\"test-pause\" type=\"button\">Animáció szüneteltetése</button></div><div class=\"test-columns\" id=\"testimonial-columns\"><div class=\"test-col\"><div class=\"test-col-inner\"><div class=\"test-group\"><div class=\"test-card\" data-cid=\"testimonial-1\">\n<div>\n<div class=\"test-stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<p class=\"test-quote\">[TEMPLATE: Vélemény 1 szó szerint az oldalról]</p>\n</div>\n<div class=\"test-author\">\n<div class=\"test-author-info\">\n<div class=\"test-avatar\">[M]</div>\n<div class=\"test-name\">\n<h5>[TEMPLATE: Név]</h5>\n<span>[TEMPLATE: Település vagy szerep]</span>\n</div>\n</div>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"google-logo\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div><div class=\"test-card\" data-cid=\"testimonial-2\">\n<div>\n<div class=\"test-stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<p class=\"test-quote\">[TEMPLATE: Vélemény 2 szó szerint az oldalról]</p>\n</div>\n<div class=\"test-author\">\n<div class=\"test-author-info\">\n<div class=\"test-avatar\">[M]</div>\n<div class=\"test-name\">\n<h5>[TEMPLATE: Név]</h5>\n<span>[TEMPLATE: Település vagy szerep]</span>\n</div>\n</div>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"google-logo\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div></div><div aria-hidden=\"true\" class=\"test-group test-clone\"><div class=\"test-card\">\n<div>\n<div class=\"test-stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<p class=\"test-quote\">[TEMPLATE: Vélemény 1 szó szerint az oldalról]</p>\n</div>\n<div class=\"test-author\">\n<div class=\"test-author-info\">\n<div class=\"test-avatar\">[M]</div>\n<div class=\"test-name\">\n<h5>[TEMPLATE: Név]</h5>\n<span>[TEMPLATE: Település vagy szerep]</span>\n</div>\n</div>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"google-logo\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div><div class=\"test-card\">\n<div>\n<div class=\"test-stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<p class=\"test-quote\">[TEMPLATE: Vélemény 2 szó szerint az oldalról]</p>\n</div>\n<div class=\"test-author\">\n<div class=\"test-author-info\">\n<div class=\"test-avatar\">[M]</div>\n<div class=\"test-name\">\n<h5>[TEMPLATE: Név]</h5>\n<span>[TEMPLATE: Település vagy szerep]</span>\n</div>\n</div>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"google-logo\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div></div></div></div><div class=\"test-col\"><div class=\"test-col-inner reverse\"><div class=\"test-group\"><div class=\"test-card\" data-cid=\"testimonial-3\">\n<div>\n<div class=\"test-stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<p class=\"test-quote\">[TEMPLATE: Vélemény 3 szó szerint az oldalról]</p>\n</div>\n<div class=\"test-author\">\n<div class=\"test-author-info\">\n<div class=\"test-avatar\">[M]</div>\n<div class=\"test-name\">\n<h5>[TEMPLATE: Név]</h5>\n<span>[TEMPLATE: Település vagy szerep]</span>\n</div>\n</div>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"google-logo\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div><div class=\"test-card\" data-cid=\"testimonial-4\">\n<div>\n<div class=\"test-stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<p class=\"test-quote\">[TEMPLATE: Vélemény 4 szó szerint az oldalról]</p>\n</div>\n<div class=\"test-author\">\n<div class=\"test-author-info\">\n<div class=\"test-avatar\">[M]</div>\n<div class=\"test-name\">\n<h5>[TEMPLATE: Név]</h5>\n<span>[TEMPLATE: Település vagy szerep]</span>\n</div>\n</div>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"google-logo\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div></div><div aria-hidden=\"true\" class=\"test-group test-clone\"><div class=\"test-card\">\n<div>\n<div class=\"test-stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<p class=\"test-quote\">[TEMPLATE: Vélemény 3 szó szerint az oldalról]</p>\n</div>\n<div class=\"test-author\">\n<div class=\"test-author-info\">\n<div class=\"test-avatar\">[M]</div>\n<div class=\"test-name\">\n<h5>[TEMPLATE: Név]</h5>\n<span>[TEMPLATE: Település vagy szerep]</span>\n</div>\n</div>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"google-logo\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div><div class=\"test-card\">\n<div>\n<div class=\"test-stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<p class=\"test-quote\">[TEMPLATE: Vélemény 4 szó szerint az oldalról]</p>\n</div>\n<div class=\"test-author\">\n<div class=\"test-author-info\">\n<div class=\"test-avatar\">[M]</div>\n<div class=\"test-name\">\n<h5>[TEMPLATE: Név]</h5>\n<span>[TEMPLATE: Település vagy szerep]</span>\n</div>\n</div>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"google-logo\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div></div></div></div><div class=\"test-col\"><div class=\"test-col-inner\"><div class=\"test-group\"><div class=\"test-card\" data-cid=\"testimonial-5\">\n<div>\n<div class=\"test-stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<p class=\"test-quote\">[TEMPLATE: Vélemény 5 szó szerint az oldalról]</p>\n</div>\n<div class=\"test-author\">\n<div class=\"test-author-info\">\n<div class=\"test-avatar\">[M]</div>\n<div class=\"test-name\">\n<h5>[TEMPLATE: Név]</h5>\n<span>[TEMPLATE: Település vagy szerep]</span>\n</div>\n</div>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"google-logo\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div><div class=\"test-card\" data-cid=\"testimonial-6\">\n<div>\n<div class=\"test-stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<p class=\"test-quote\">[TEMPLATE: Vélemény 6 szó szerint az oldalról]</p>\n</div>\n<div class=\"test-author\">\n<div class=\"test-author-info\">\n<div class=\"test-avatar\">[M]</div>\n<div class=\"test-name\">\n<h5>[TEMPLATE: Név]</h5>\n<span>[TEMPLATE: Település vagy szerep]</span>\n</div>\n</div>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"google-logo\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div></div><div aria-hidden=\"true\" class=\"test-group test-clone\"><div class=\"test-card\">\n<div>\n<div class=\"test-stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<p class=\"test-quote\">[TEMPLATE: Vélemény 5 szó szerint az oldalról]</p>\n</div>\n<div class=\"test-author\">\n<div class=\"test-author-info\">\n<div class=\"test-avatar\">[M]</div>\n<div class=\"test-name\">\n<h5>[TEMPLATE: Név]</h5>\n<span>[TEMPLATE: Település vagy szerep]</span>\n</div>\n</div>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"google-logo\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div><div class=\"test-card\">\n<div>\n<div class=\"test-stars\"><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i><i class=\"ph ph-placeholder\"></i></div>\n<p class=\"test-quote\">[TEMPLATE: Vélemény 6 szó szerint az oldalról]</p>\n</div>\n<div class=\"test-author\">\n<div class=\"test-author-info\">\n<div class=\"test-avatar\">[M]</div>\n<div class=\"test-name\">\n<h5>[TEMPLATE: Név]</h5>\n<span>[TEMPLATE: Település vagy szerep]</span>\n</div>\n</div>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"google-logo\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div></div></div></div></div>\n</div>\n</section>\n<section class=\"gallery-motion-v2\" data-block=\"14\" data-section-id=\"S18\" id=\"galeria-v2\">\n<div class=\"v2-sticky\">\n<div class=\"section-header text-center v2-header\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S18\">S18 · [TEMPLATE: Galéria cím, 3-6 szó]</h2>\n</div>\n<div class=\"v2-carousel\" id=\"v2-ring\">\n<div class=\"img-wrapper v2-item\" data-lb-group=\"v2\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v2', 0)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n<div class=\"img-wrapper v2-item\" data-lb-group=\"v2\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v2', 1)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n<div class=\"img-wrapper v2-item\" data-lb-group=\"v2\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v2', 2)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n<div class=\"img-wrapper v2-item\" data-lb-group=\"v2\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v2', 3)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n<div class=\"img-wrapper v2-item\" data-lb-group=\"v2\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v2', 4)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n<div class=\"img-wrapper v2-item\" data-lb-group=\"v2\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v2', 5)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n</div>\n</div>\n</section>\n<section class=\"gallery-motion-v5\" data-block=\"15\" data-section-id=\"S19\" id=\"galeria-v5\">\n<div class=\"v5-sticky\">\n<div class=\"v5-inner\" id=\"v5-inner\">\n<div class=\"img-wrapper\" data-lb-group=\"v5\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v5', 0)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n<div class=\"img-wrapper\" data-lb-group=\"v5\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v5', 1)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n<div class=\"img-wrapper\" data-lb-group=\"v5\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v5', 2)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n<div class=\"img-wrapper\" data-lb-group=\"v5\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v5', 3)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n<div class=\"img-wrapper\" data-lb-group=\"v5\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v5', 4)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n<div class=\"img-wrapper\" data-lb-group=\"v5\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v5', 5)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n<div class=\"img-wrapper\" data-lb-group=\"v5\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v5', 6)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n<div class=\"img-wrapper\" data-lb-group=\"v5\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v5', 7)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n<div class=\"img-wrapper\" data-lb-group=\"v5\" data-lb-src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<div class=\"img-expand\" onclick=\"openLightbox('v5', 8)\"><i class=\"ph ph-placeholder\"></i></div>\n</div>\n</div>\n<div class=\"v5-gate-panel v5-gate-left\" id=\"v5-left\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n<div class=\"v5-gate-panel v5-gate-right\" id=\"v5-right\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n<div class=\"section-header text-center v5-header\" id=\"v5-title\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S19\">S19 · [TEMPLATE: Galéria cím, 3-6 szó]</h2>\n</div>\n</div>\n</section>\n<section class=\"cta-section\" data-block=\"16\" data-section-id=\"S20\" id=\"ajanlat-cta\">\n<div class=\"container\">\n<div class=\"cta-box reveal\">\n<div class=\"cta-content\">\n<div class=\"pill-badge\"><span class=\"highlight\">[TEMPLATE: Címke]</span> [TEMPLATE: Rövid kiemelés, 3-5 szó]</div>\n<h2 class=\"section-title\" id=\"S20\">S20 · [TEMPLATE: Ajánlati cím, 5-8 szó, kulcsszóval]</h2>\n<p>[TEMPLATE: Ajánlat egy mondatban, 20-35 szó]</p>\n<a class=\"btn btn-primary\" href=\"tel:+3600000000\">[TEMPLATE: Hívás CTA telefonszámmal]</a>\n</div>\n<div class=\"cta-image\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div>\n</div>\n</section>\n<section class=\"contact-redesigned\" data-block=\"19\" data-section-id=\"S21\" id=\"ajanlat\">\n<div class=\"contact-wrapper\">\n<div class=\"section-header text-center\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S21\">S21 · [TEMPLATE: Kapcsolat cím, 4-7 szó]</h2>\n</div>\n<div class=\"contact-grid\">\n<div class=\"contact-left\">\n<h3>[TEMPLATE: Kapcsolat blokk címe]</h3>\n<p>[TEMPLATE: Kapcsolat blokk szövege, 20-30 szó]</p>\n<div class=\"contact-info-block\">\n<div class=\"icon-circle\"><i class=\"ph ph-placeholder\"></i></div>\n<div>\n<small>[TEMPLATE: Telefon felirat]</small>\n<strong>[TEMPLATE: Telefonszám]</strong>\n</div>\n</div>\n<div class=\"contact-info-block\">\n<div class=\"icon-circle\"><i class=\"ph ph-placeholder\"></i></div>\n<div>\n<small>[TEMPLATE: E-mail felirat]</small>\n<strong>[TEMPLATE: E-mail cím]</strong>\n</div>\n</div>\n<div class=\"contact-info-block\">\n<div class=\"icon-circle\"><i class=\"ph ph-placeholder\"></i></div>\n<div>\n<small>[TEMPLATE: Cím felirat]</small>\n<strong>[TEMPLATE: Cím]</strong>\n</div>\n</div>\n</div>\n<div class=\"contact-right\">\n<h3>[TEMPLATE: Űrlap címe]</h3>\n<div class=\"form-step active\" id=\"c-step1\">\n<div class=\"service-select-grid\">\n<div class=\"service-select-card\" onclick=\"toggleContactService(this)\">\n<i class=\"ph ph-placeholder\"></i>\n<span>[TEMPLATE: Szolgáltatás 1]</span>\n</div>\n<div class=\"service-select-card\" onclick=\"toggleContactService(this)\">\n<i class=\"ph ph-placeholder\"></i>\n<span>[TEMPLATE: Szolgáltatás 2]</span>\n</div>\n<div class=\"service-select-card\" onclick=\"toggleContactService(this)\">\n<i class=\"ph ph-placeholder\"></i>\n<span>[TEMPLATE: Szolgáltatás 3]</span>\n</div>\n<div class=\"service-select-card\" onclick=\"toggleContactService(this)\">\n<i class=\"ph ph-placeholder\"></i>\n<span>[TEMPLATE: Szolgáltatás 4]</span>\n</div>\n</div>\n<button class=\"btn btn-primary\" disabled=\"\" id=\"c-nextBtn\" onclick=\"nextContactStep()\" style=\"width: 100%;\" type=\"button\">[TEMPLATE: Tovább gomb]</button>\n</div>\n<div class=\"form-step\" id=\"c-step2\">\n<div class=\"input-group\">\n<label for=\"c-name\">[TEMPLATE: Név mező]</label>\n<input id=\"c-name\" placeholder=\"[TEMPLATE: Név mező]\" type=\"text\"/>\n</div>\n<div class=\"calc-form-row\">\n<div class=\"input-group\">\n<label for=\"c-phone\">[TEMPLATE: Telefon mező]</label>\n<input id=\"c-phone\" placeholder=\"[TEMPLATE: Telefon mező]\" type=\"tel\"/>\n</div>\n<div class=\"input-group\">\n<label for=\"c-email\">[TEMPLATE: E-mail mező]</label>\n<input id=\"c-email\" placeholder=\"[TEMPLATE: E-mail mező]\" type=\"email\"/>\n</div>\n</div>\n<div class=\"input-group\">\n<label for=\"c-message\">[TEMPLATE: Üzenet mező]</label>\n<textarea id=\"c-message\" placeholder=\"[TEMPLATE: Üzenet mező]\"></textarea>\n</div>\n<div class=\"step-buttons\">\n<button class=\"btn btn-outline\" onclick=\"prevContactStep()\" style=\"flex: 1;\" type=\"button\">[TEMPLATE: Vissza gomb]</button>\n<button class=\"btn btn-primary\" style=\"flex: 2;\" type=\"button\">[TEMPLATE: Küldés gomb]</button>\n</div>\n</div>\n</div>\n</div>\n</div>\n</section>\n<div class=\"lightbox-overlay\" id=\"lightbox\">\n<i class=\"ph ph-placeholder lb-close\" onclick=\"closeLightbox()\"></i>\n<i class=\"ph ph-placeholder lb-nav lb-prev\" onclick=\"changeLightboxImg(-1)\"></i>\n<i class=\"ph ph-placeholder lb-nav lb-next\" onclick=\"changeLightboxImg(1)\"></i>\n<div class=\"lb-img-container\" id=\"lb-container\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"lb-img active\" id=\"lb-img-main\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"lb-img\" id=\"lb-img-buffer\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n</div>\n</div>\n<a aria-label=\"[TEMPLATE: Telefonszám]\" class=\"widget-phone\" data-cid=\"path:body&gt;a\" href=\"tel:+3600000000\">\n<div class=\"icon-wrapper\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M7 3H4a1 1 0 0 0-1 1c0 9.4 7.6 17 17 17a1 1 0 0 0 1-1v-3l-5-2-2 2a15 15 0 0 1-7-7l2-2-2-5Z\"></path></svg></div>\n<div class=\"text-wrapper\">[TEMPLATE: Telefonszám]</div>\n</a><div class=\"widget-chat\" id=\"contact-widget\">\n<button aria-controls=\"chat-window\" aria-expanded=\"false\" aria-label=\"Üzenetablak megnyitása\" class=\"chat-toggle\" type=\"button\"><svg aria-hidden=\"true\" viewbox=\"0 0 24 24\"><path d=\"M21 11.5a8.5 8.5 0 0 1-8.5 8.5H4l-3 2 2-6a8.5 8.5 0 1 1 18-4.5Z\"></path><path d=\"M7 9h10M7 13h7\"></path></svg></button>\n<div aria-labelledby=\"chat-title\" class=\"chat-window\" hidden=\"\" id=\"chat-window\" role=\"dialog\">\n<div class=\"chat-header\"><h3 id=\"chat-title\">[TEMPLATE: Üzenetablak címe]</h3><p>[TEMPLATE: Rövid felvezetés]</p><button aria-label=\"Üzenetablak bezárása\" class=\"chat-close\" type=\"button\">×</button></div>\n<form class=\"chat-body\"><label for=\"chat-contact\">[TEMPLATE: E-mail cím]</label><input autocomplete=\"email\" id=\"chat-contact\" name=\"email\" required=\"\" type=\"email\"/><label for=\"chat-message\">[TEMPLATE: Üzenet]</label><textarea id=\"chat-message\" name=\"message\" required=\"\" rows=\"4\"></textarea><button class=\"btn btn-primary\" type=\"submit\">[TEMPLATE: Küldés gomb]</button><p class=\"chat-status\" hidden=\"\" role=\"status\">Bemutató űrlap. Üzenet nem lett elküldve.</p></form></div></div>\n<section class=\"uf-section\" data-section-id=\"S22\" id=\"uf-2\">\n<div class=\"container\">\n<div class=\"section-header text-center\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S22\">S22 · [TEMPLATE: Garancia blokk cím, 4-7 szó]</h2>\n</div>\n<div class=\"uf-grid-3\">\n<div class=\"uf-card\">\n<i class=\"ph ph-placeholder\"></i>\n<h3>[TEMPLATE: Garancia 1 címe]</h3>\n<p>[TEMPLATE: Garancia 1 ajánlatként, 20-35 szó]</p>\n</div>\n<div class=\"uf-card\">\n<i class=\"ph ph-placeholder\"></i>\n<h3>[TEMPLATE: Garancia 2 címe]</h3>\n<p>[TEMPLATE: Garancia 2 ajánlatként, 20-35 szó]</p>\n</div>\n<div class=\"uf-card\">\n<i class=\"ph ph-placeholder\"></i>\n<h3>[TEMPLATE: Garancia 3 címe]</h3>\n<p>[TEMPLATE: Garancia 3 ajánlatként, 20-35 szó]</p>\n</div>\n</div>\n</div>\n</section><section class=\"uf-section bg-alternate\" data-section-id=\"S23\" id=\"uf-3\">\n<div class=\"container\">\n<div class=\"section-header text-center\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S23\">S23 · [TEMPLATE: Ártáblázat cím, 4-7 szó]</h2>\n</div>\n<div class=\"uf-table-wrap\">\n<table class=\"uf-table\">\n<thead>\n<tr>\n<th>[TEMPLATE: Oszlop 1 neve]</th>\n<th>[TEMPLATE: Oszlop 2 neve]</th>\n<th>[TEMPLATE: Oszlop 3 neve]</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td data-label=\"[TEMPLATE: Oszlop 1 neve]\">[TEMPLATE: Tétel 1]</td>\n<td data-label=\"[TEMPLATE: Oszlop 2 neve]\">[TEMPLATE: Egység 1]</td>\n<td data-label=\"[TEMPLATE: Oszlop 3 neve]\">[TEMPLATE: Ártartomány 1]</td>\n</tr>\n<tr>\n<td data-label=\"[TEMPLATE: Oszlop 1 neve]\">[TEMPLATE: Tétel 2]</td>\n<td data-label=\"[TEMPLATE: Oszlop 2 neve]\">[TEMPLATE: Egység 2]</td>\n<td data-label=\"[TEMPLATE: Oszlop 3 neve]\">[TEMPLATE: Ártartomány 2]</td>\n</tr>\n<tr>\n<td data-label=\"[TEMPLATE: Oszlop 1 neve]\">[TEMPLATE: Tétel 3]</td>\n<td data-label=\"[TEMPLATE: Oszlop 2 neve]\">[TEMPLATE: Egység 3]</td>\n<td data-label=\"[TEMPLATE: Oszlop 3 neve]\">[TEMPLATE: Ártartomány 3]</td>\n</tr>\n<tr>\n<td data-label=\"[TEMPLATE: Oszlop 1 neve]\">[TEMPLATE: Tétel 4]</td>\n<td data-label=\"[TEMPLATE: Oszlop 2 neve]\">[TEMPLATE: Egység 4]</td>\n<td data-label=\"[TEMPLATE: Oszlop 3 neve]\">[TEMPLATE: Ártartomány 4]</td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n</section><section class=\"uf-section\" data-section-id=\"S24\" id=\"uf-4\">\n<div class=\"container\">\n<div class=\"section-header text-center\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S24\">S24 · [TEMPLATE: Módszer összehasonlítás cím, 4-7 szó]</h2>\n</div>\n<div class=\"uf-grid-2\">\n<div class=\"uf-card\">\n<h3>[TEMPLATE: A módszer neve]</h3>\n<p>[TEMPLATE: A módszer leírása, 25-40 szó]</p>\n<ul class=\"foundation-list\">\n<li><i class=\"ph ph-placeholder\"></i><p>[TEMPLATE: Szempont 1]</p></li>\n<li><i class=\"ph ph-placeholder\"></i><p>[TEMPLATE: Szempont 2]</p></li>\n<li><i class=\"ph ph-placeholder\"></i><p>[TEMPLATE: Szempont 3]</p></li>\n</ul>\n</div>\n<div class=\"uf-card\">\n<h3>[TEMPLATE: B módszer neve]</h3>\n<p>[TEMPLATE: B módszer leírása, 25-40 szó]</p>\n<ul class=\"foundation-list\">\n<li><i class=\"ph ph-placeholder\"></i><p>[TEMPLATE: Szempont 1]</p></li>\n<li><i class=\"ph ph-placeholder\"></i><p>[TEMPLATE: Szempont 2]</p></li>\n<li><i class=\"ph ph-placeholder\"></i><p>[TEMPLATE: Szempont 3]</p></li>\n</ul>\n</div>\n</div>\n</div>\n</section><section class=\"uf-section bg-alternate\" data-section-id=\"S25\" id=\"uf-5\">\n<div class=\"container\">\n<div class=\"section-header text-center\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S25\">S25 · [TEMPLATE: Idővonal cím, 4-7 szó]</h2>\n</div>\n<ol class=\"uf-timeline\">\n<li class=\"uf-timeline-item\" data-step=\"1\">\n<div class=\"uf-timeline-dot\">01</div>\n<div>\n<h3>[TEMPLATE: Idővonal 1 címe]</h3>\n<p>[TEMPLATE: Idővonal 1 leírása, 20-30 szó]</p>\n</div>\n</li>\n<li class=\"uf-timeline-item\" data-step=\"2\">\n<div class=\"uf-timeline-dot\">02</div>\n<div>\n<h3>[TEMPLATE: Idővonal 2 címe]</h3>\n<p>[TEMPLATE: Idővonal 2 leírása, 20-30 szó]</p>\n</div>\n</li>\n<li class=\"uf-timeline-item\" data-step=\"3\">\n<div class=\"uf-timeline-dot\">03</div>\n<div>\n<h3>[TEMPLATE: Idővonal 3 címe]</h3>\n<p>[TEMPLATE: Idővonal 3 leírása, 20-30 szó]</p>\n</div>\n</li>\n<li class=\"uf-timeline-item\" data-step=\"4\">\n<div class=\"uf-timeline-dot\">04</div>\n<div>\n<h3>[TEMPLATE: Idővonal 4 címe]</h3>\n<p>[TEMPLATE: Idővonal 4 leírása, 20-30 szó]</p>\n</div>\n</li>\n</ol>\n</div>\n</section><section class=\"uf-section\" data-section-id=\"S26\" id=\"uf-6\">\n<div class=\"container\">\n<div class=\"section-header text-center\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S26\">S26 · [TEMPLATE: Szolgáltatási terület cím, 4-7 szó]</h2>\n</div>\n<div class=\"uf-area-list\">\n<div class=\"uf-area-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Terület 1]</div>\n<div class=\"uf-area-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Terület 2]</div>\n<div class=\"uf-area-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Terület 3]</div>\n<div class=\"uf-area-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Terület 4]</div>\n<div class=\"uf-area-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Terület 5]</div>\n<div class=\"uf-area-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Terület 6]</div>\n<div class=\"uf-area-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Terület 7]</div>\n<div class=\"uf-area-item\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Terület 8]</div>\n</div>\n</div>\n</section><section class=\"uf-section bg-alternate\" data-section-id=\"S27\" id=\"uf-7\">\n<div class=\"container\">\n<div class=\"section-header text-center\">\n<span class=\"section-subtitle\">[TEMPLATE: Szekció felcím]</span>\n<h2 class=\"section-title\" id=\"S27\">S27 · [TEMPLATE: Logó vagy tanúsítvány sáv cím, 4-7 szó]</h2>\n</div>\n<div class=\"uf-badge-strip\">\n<div class=\"uf-badge-item\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<span>[TEMPLATE: Jelvény 1 neve]</span>\n</div>\n<div class=\"uf-badge-item\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<span>[TEMPLATE: Jelvény 2 neve]</span>\n</div>\n<div class=\"uf-badge-item\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<span>[TEMPLATE: Jelvény 3 neve]</span>\n</div>\n<div class=\"uf-badge-item\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<span>[TEMPLATE: Jelvény 4 neve]</span>\n</div>\n<div class=\"uf-badge-item\">\n<img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/>\n<span>[TEMPLATE: Jelvény 5 neve]</span>\n</div>\n</div>\n</div>\n</section><footer class=\"footer\" data-block=\"20\" data-section-id=\"S28\" id=\"labresz\">\n<div class=\"container\">\n<div class=\"footer-grid\">\n<div class=\"footer-col\">\n<span class=\"nav-logo-plaque\"><img alt=\"[TEMPLATE IMAGE: mi kerül ide]\" class=\"nav-logo-img\" src=\"https://placehold.co/1600x900?text=TEMPLATE+IMAGE\"/></span>\n<p>[TEMPLATE: Cégbemutató a láblécben, 30-45 szó]</p>\n</div>\n<div class=\"footer-col\">\n<h4 id=\"S28\">S28 · [TEMPLATE: Lábléc oszlop 1 címe]</h4>\n<div class=\"footer-links\">\n<a href=\"#szolgaltatas-1\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Szolgáltatás link 1]</a>\n<a href=\"#szolgaltatas-2\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Szolgáltatás link 2]</a>\n<a href=\"#szolgaltatas-3\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Szolgáltatás link 3]</a>\n<a href=\"#szolgaltatasok\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Szolgáltatás link 4]</a>\n</div>\n</div>\n<div class=\"footer-col\">\n<h4>[TEMPLATE: Lábléc oszlop 2 címe]</h4>\n<div class=\"footer-links\">\n<a href=\"tel:+3600000000\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Telefonszám]</a>\n<a href=\"/cdn-cgi/l/email-protection#2753424a574b46534267425f464a574b420944484a\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: E-mail cím]</a>\n<a href=\"#ajanlat\"><i class=\"ph ph-placeholder\"></i> [TEMPLATE: Cím]</a>\n</div>\n</div>\n</div>\n<div class=\"footer-bottom\">\n<p>[TEMPLATE: Copyright sor a cégnévvel]</p>\n<div class=\"d-flex gap-20\">\n<a href=\"#ajanlat\">[TEMPLATE: Adatkezelési link]</a>\n<a href=\"#ajanlat\">[TEMPLATE: Impresszum link]</a>\n</div>\n</div>\n</div>\n</footer>\n<script data-cfasync=\"false\" src=\"/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js\"></script><script>\n/* [TEMPLATE ANNOTATION]: CALC_CONSTANTS holds every number both calculators use.\n   Fill it from the client's price data, nothing else in the script needs to\n   change. Keep every key, keep the arrays in the same order as the option cards\n   in the markup, and keep every value a positive number so no result can turn\n   negative or NaN. */\nconst CALC_CONSTANTS = {\n  /* number format locale for every displayed price */\n  locale: 'hu-HU',\n  /* currency label appended after every price */\n  currencySuffix: ' Ft',\n  v1: {\n    /* unit price of each option card of #arkalkulator, in the DOM order of\n       data-v1-option 0 to 3, from the client's price list */\n    optionPrices: [10000, 12000, 14000, 16000],\n    /* unit price used before the visitor picks an option, so the result is never\n       empty and never NaN */\n    defaultUnitPrice: 10000,\n    /* slider range of the quantity question, in the unit below */\n    areaMin: 1,\n    areaMax: 150,\n    /* slider position the calculator opens with */\n    areaDefault: 20,\n    /* unit label shown next to the slider value and in the summary */\n    areaUnit: ' m²',\n    /* fixed call out or set up fee added once to every result, 0 when there is none */\n    baseFee: 0\n  },\n  v3: {\n    /* unit price of each type option of #konfigurator, in the DOM order of\n       data-v3-option 0 to 3 */\n    optionPrices: [10000, 12000, 14000, 16000],\n    /* unit price used before a type is chosen */\n    defaultUnitPrice: 10000,\n    /* multiplier of each base condition option, in the DOM order of data-v3-base\n       0 to 3, 1 means no surcharge */\n    baseMultipliers: [1, 1.1, 1.2, 1.3],\n    /* multiplier used before a base condition is chosen */\n    defaultBaseMultiplier: 1,\n    /* quantity the configurator opens with, its minimum and its unit label */\n    sizeDefault: 10,\n    sizeMin: 1,\n    sizeUnit: ' m²',\n    /* fixed fee added once to every result, 0 when there is none */\n    baseFee: 0\n  }\n};\n\n/* ---------- shared helpers ---------- */\nfunction formatPrice(num) {\n  const safe = (!isFinite(num) || num < 0) ? 0 : Math.round(num);\n  return new Intl.NumberFormat(CALC_CONSTANTS.locale, { maximumFractionDigits: 0 }).format(safe) + CALC_CONSTANTS.currencySuffix;\n}\nconst math = {\n  lerp: (start, end, factor) => start * (1 - factor) + end * factor,\n  clamp: (min, max, val) => Math.min(Math.max(val, min), max)\n};\n\n/* ---------- sticky header ---------- */\nwindow.addEventListener('scroll', () => {\n  const header = document.getElementById('headerWrapper');\n  if (!header) return;\n  if (window.scrollY > 40) { header.classList.add('scrolled'); } else { header.classList.remove('scrolled'); }\n});\n\n/* ---------- mobile menu ---------- */\nfunction toggleMobileMenu() {\n  const menu = document.getElementById('mobile-menu');\n  const btn = document.querySelector('.mobile-menu-btn');\n  if (!menu) return;\n  const open = menu.classList.toggle('open');\n  if (btn) btn.setAttribute('aria-expanded', open ? 'true' : 'false');\n}\n\n/* ---------- two step contact form ---------- */\nfunction toggleContactService(card) {\n  card.classList.toggle('selected');\n  const selectedCount = document.querySelectorAll('#c-step1 .service-select-card.selected').length;\n  const nextBtn = document.getElementById('c-nextBtn');\n  if (nextBtn) nextBtn.disabled = selectedCount === 0;\n}\nfunction nextContactStep() {\n  document.getElementById('c-step1').classList.remove('active');\n  document.getElementById('c-step2').classList.add('active');\n}\nfunction prevContactStep() {\n  document.getElementById('c-step2').classList.remove('active');\n  document.getElementById('c-step1').classList.add('active');\n}\n\n/* ---------- service detail gallery slider (below 992 px) ---------- */\nfunction sd2MoveGallery(btn, direction) {\n  const track = btn.closest('.sd2-service-gallery').querySelector('.sd2-gallery-track');\n  const items = track.querySelectorAll('.sd2-gallery-item');\n  const maxIndex = Math.max(0, items.length - 2);\n  let cur = parseInt(track.dataset.slide || '0', 10) + direction;\n  if (cur < 0) cur = 0;\n  if (cur > maxIndex) cur = maxIndex;\n  track.dataset.slide = cur;\n  const itemWidth = items[0].offsetWidth;\n  const gap = 15;\n  track.style.transform = 'translateX(-' + (cur * (itemWidth + gap)) + 'px)';\n}\n\n/* ---------- scroll reveal observer ---------- */\n/* [TEMPLATE ANNOTATION]: the observer only adds .visible. A .reveal element is\n   fully visible with .visible or under prefers-reduced-motion, it is never left\n   hidden. */\nconst revealObserver = new IntersectionObserver((entries) => {\n  entries.forEach((entry) => {\n    if (entry.isIntersecting) {\n      entry.target.classList.add('visible');\n      revealObserver.unobserve(entry.target);\n    }\n  });\n}, { threshold: 0.08 });\ndocument.querySelectorAll('.reveal').forEach((el) => revealObserver.observe(el));\n\n/* ---------- motion galleries ---------- */\nlet targetScroll = window.scrollY;\nlet currentScroll = window.scrollY;\nlet velocity = 0;\nlet winH = window.innerHeight;\nlet winW = window.innerWidth;\nlet isLightboxOpen = false;\n\n/* [TEMPLATE ANNOTATION]: setupCylinder places the six .v2-item panels on a\n   circle. The radius scales with the viewport so the rotating cylinder never\n   sticks out sideways, which would create horizontal page overflow (body must\n   not clip it, see the sticky-gallery rule). */\nconst setupCylinder = () => {\n  const items = document.querySelectorAll('.v2-item');\n  if (!items.length) return;\n  const total = items.length;\n  const radius = winW < 360 ? 120 : (winW < 576 ? 140 : (winW < 992 ? 260 : 380));\n  items.forEach((item, i) => {\n    const angle = (i / total) * 360;\n    item.style.transform = 'rotateY(' + angle + 'deg) translateZ(' + radius + 'px)';\n  });\n};\nwindow.addEventListener('load', setupCylinder);\nsetupCylinder();\nwindow.addEventListener('resize', () => {\n  winH = window.innerHeight;\n  winW = window.innerWidth;\n  setupCylinder();\n  document.querySelectorAll('.sd2-gallery-track').forEach((track) => {\n    if (window.innerWidth > 992) {\n      track.style.transform = 'translateX(0)';\n      track.dataset.slide = 0;\n    }\n  });\n});\nwindow.addEventListener('scroll', () => { if (!isLightboxOpen) targetScroll = window.scrollY; });\n\n/* [TEMPLATE ANNOTATION]: one requestAnimationFrame loop scrubs both galleries.\n   V2 maps the scroll through #galeria-v2 onto one full rotation of #v2-ring.\n   V5 maps the scroll through #galeria-v5 onto the two gate panels, the inner\n   grid and the title. */\nfunction render() {\n  if (isLightboxOpen) return requestAnimationFrame(render);\n  const previousScroll = currentScroll;\n  currentScroll = math.lerp(currentScroll, targetScroll, 0.08);\n  velocity = currentScroll - previousScroll;\n\n  if (Math.abs(targetScroll - currentScroll) > 0.01 || Math.abs(velocity) > 0.01) {\n    const v2 = document.getElementById('galeria-v2');\n    if (v2) {\n      const v2Top = v2.offsetTop - currentScroll;\n      if (v2Top <= 0 && (v2Top + v2.offsetHeight) >= winH) {\n        const maxScroll = v2.offsetHeight - winH;\n        const progress = math.clamp(0, 1, Math.abs(v2Top) / maxScroll);\n        const ring = document.getElementById('v2-ring');\n        if (ring) ring.style.transform = 'rotateY(' + (progress * -360) + 'deg)';\n      }\n    }\n    const v5 = document.getElementById('galeria-v5');\n    if (v5) {\n      const v5Top = v5.offsetTop - currentScroll;\n      if (v5Top <= 0 && (v5Top + v5.offsetHeight) >= winH) {\n        const maxScroll = v5.offsetHeight - winH;\n        const progress = math.clamp(0, 1, Math.abs(v5Top) / maxScroll);\n        const gateL = document.getElementById('v5-left');\n        const gateR = document.getElementById('v5-right');\n        const inner = document.getElementById('v5-inner');\n        const title = document.getElementById('v5-title');\n        const gateProgress = math.clamp(0, 1, progress * 1.5);\n        const easeProg = Math.pow(gateProgress, 2);\n        if (gateL) gateL.style.transform = 'translate3d(' + (-easeProg * 100) + '%, 0, 0)';\n        if (gateR) gateR.style.transform = 'translate3d(' + (easeProg * 100) + '%, 0, 0)';\n        if (inner) {\n          inner.style.transform = 'scale(' + math.lerp(0.8, 1, easeProg) + ')';\n          inner.style.opacity = math.lerp(0, 1, Math.min(progress * 2, 1));\n        }\n        if (title) {\n          const titleProg = math.clamp(0, 1, progress * 6);\n          title.style.opacity = 1 - titleProg;\n          title.style.transform = 'translate(-50%, -50%) scale(' + math.lerp(1, 1.2, titleProg) + ')';\n        }\n      }\n    }\n  }\n  requestAnimationFrame(render);\n}\nrequestAnimationFrame(render);\n\n/* ---------- lightbox ---------- */\nconst lightbox = document.getElementById('lightbox');\nconst lbImgMain = document.getElementById('lb-img-main');\nconst lbImgBuffer = document.getElementById('lb-img-buffer');\nlet currentGalleryData = [];\nlet currentIndex = 0;\nlet isAnimating = false;\n\nfunction openLightbox(group, index) {\n  isLightboxOpen = true;\n  document.body.classList.add('no-scroll');\n  currentGalleryData = Array.from(document.querySelectorAll('.img-wrapper[data-lb-group=\"' + group + '\"]')).map((el) => el.getAttribute('data-lb-src'));\n  currentIndex = index;\n  lightbox.className = 'lightbox-overlay active';\n  lbImgMain.src = currentGalleryData[currentIndex];\n  lbImgMain.className = 'lb-img active';\n  lbImgBuffer.className = 'lb-img';\n}\nfunction closeLightbox() {\n  if (isAnimating) return;\n  lightbox.className = 'lightbox-overlay';\n  document.body.classList.remove('no-scroll');\n  isLightboxOpen = false;\n  targetScroll = currentScroll = window.scrollY;\n}\nfunction changeLightboxImg(dir) {\n  if (isAnimating || currentGalleryData.length <= 1) return;\n  isAnimating = true;\n  let newIndex = currentIndex + dir;\n  if (newIndex < 0) newIndex = currentGalleryData.length - 1;\n  if (newIndex >= currentGalleryData.length) newIndex = 0;\n  lbImgBuffer.src = currentGalleryData[newIndex];\n  const exitClass = dir > 0 ? 'exit-next' : 'exit-prev';\n  const enterClass = dir > 0 ? 'enter-next' : 'enter-prev';\n  lbImgMain.className = 'lb-img active ' + exitClass;\n  lbImgBuffer.className = 'lb-img active ' + enterClass;\n  setTimeout(() => {\n    lbImgMain.src = currentGalleryData[newIndex];\n    lbImgMain.className = 'lb-img active';\n    lbImgBuffer.className = 'lb-img';\n    currentIndex = newIndex;\n    isAnimating = false;\n  }, 500);\n}\n\nconst v1Config = CALC_CONSTANTS.v1;\nconst v1State = {\n  selected: null,\n  unitPrice: Number(v1Config.defaultUnitPrice),\n  area: Number(v1Config.areaDefault),\n  step: 1,\n  validated: false\n};\nfunction v1Calc() {\n  const unitPrice = Number(v1State.unitPrice);\n  const base = Number(v1Config.baseFee);\n  const area = Number(v1State.area);\n  const total = (Number.isFinite(unitPrice) ? Math.max(0,unitPrice) : 0) * (Number.isFinite(area) ? Math.max(0,area) : 0) + (Number.isFinite(base) ? Math.max(0,base) : 0);\n  document.getElementById('v1-final-price').textContent = formatPrice(Number.isFinite(total) ? total : 0);\n}\nfunction v1SelectType(el) {\n  const idx = Number(el.dataset.v1Option);\n  if (!Number.isInteger(idx) || idx < 0 || idx >= v1Config.optionPrices.length) return;\n  document.querySelectorAll('#arkalkulator .v1-option').forEach(opt => { const chosen = opt === el; opt.classList.toggle('selected',chosen); opt.setAttribute('aria-pressed',String(chosen)); });\n  v1State.selected = idx;\n  v1State.unitPrice = v1Config.optionPrices[idx];\n  v1State.validated = false;\n  document.getElementById('v1-btn-1').disabled = false;\n  v1Calc();\n}\nfunction v1UpdateSlider(source = document.getElementById('v1-area')) {\n  const range = document.getElementById('v1-area');\n  const number = document.getElementById('v1-area-number');\n  if (!range || !number) return;\n  const min = Number.isFinite(Number(v1Config.areaMin)) ? Number(v1Config.areaMin) : 1;\n  const max = Number.isFinite(Number(v1Config.areaMax)) ? Math.max(min,Number(v1Config.areaMax)) : Math.max(min,150);\n  const fallback = Number.isFinite(Number(v1Config.areaDefault)) ? Number(v1Config.areaDefault) : min;\n  const raw = Number(source && source.value);\n  const area = Math.max(min,Math.min(max,Math.round(Number.isFinite(raw) ? raw : fallback)));\n  const unit = typeof v1Config.areaUnit === 'string' ? v1Config.areaUnit : ' m²';\n  v1State.area = area;\n  v1State.validated = false;\n  [range,number].forEach(input => { input.min = String(min); input.max = String(max); input.step = '1'; input.value = String(area); });\n  document.getElementById('v1-area-val').textContent = area + unit;\n  const rangeLabels = document.querySelectorAll('#arkalkulator .v1-range-labels span');\n  if (rangeLabels[0]) rangeLabels[0].textContent = min + unit;\n  if (rangeLabels[1]) rangeLabels[1].textContent = max + unit;\n  v1Calc();\n}\nfunction v1Next(step) {\n  if (!Number.isInteger(step) || step < 1 || step > 4 || (step > 1 && v1State.selected === null) || (step === 4 && !v1State.validated)) return;\n  document.querySelectorAll('#arkalkulator .v1-step').forEach(el => el.classList.toggle('active',el.id === 'v1-step-' + step));\n  document.getElementById('v1-bar').style.width = ((step-1)/3*100) + '%';\n  for (let i=1;i<=4;i++) { const ind=document.getElementById('v1-ind-'+i); ind.classList.toggle('active',i===step); ind.classList.toggle('completed',i<step); if(i===step) ind.setAttribute('aria-current','step'); else ind.removeAttribute('aria-current'); }\n  v1State.step = step;\n  v1Calc();\n  const heading = document.querySelector('#v1-step-'+step+' h3');\n  if (heading) heading.focus({preventScroll:true});\n}\nfunction v1Submit() {\n  const name = document.getElementById('v1-name');\n  const email = document.getElementById('v1-email');\n  name.value = name.value.trim(); email.value = email.value.trim();\n  const nameValid = name.value.length > 0;\n  const emailValid = email.value.length > 0 && email.checkValidity();\n  name.setAttribute('aria-invalid',String(!nameValid)); email.setAttribute('aria-invalid',String(!emailValid));\n  document.getElementById('v1-error').hidden = nameValid && emailValid;\n  if (!nameValid || !emailValid) { (nameValid ? email : name).focus(); return; }\n  v1State.validated = true;\n  v1Next(4);\n}\nfunction v1Init() {\n  const root = document.getElementById('arkalkulator');\n  const range = document.getElementById('v1-area');\n  const number = document.getElementById('v1-area-number');\n  if (!root || !range || !number || root.dataset.v1Initialized === 'true') return;\n  root.dataset.v1Initialized = 'true';\n  const min = Number.isFinite(Number(v1Config.areaMin)) ? Number(v1Config.areaMin) : 1;\n  const max = Number.isFinite(Number(v1Config.areaMax)) ? Math.max(min,Number(v1Config.areaMax)) : Math.max(min,150);\n  const fallback = Number.isFinite(Number(v1Config.areaDefault)) ? Number(v1Config.areaDefault) : min;\n  range.min = number.min = String(min);\n  range.max = number.max = String(max);\n  range.step = number.step = '1';\n  range.value = number.value = String(Math.max(min,Math.min(max,fallback)));\n  v1UpdateSlider(range);\n}\nv1Init();\n\n/* ---------- calculator B, split screen configurator ---------- */\nconst v3State = {\n  unitPrice: CALC_CONSTANTS.v3.defaultUnitPrice,\n  baseMultiplier: CALC_CONSTANTS.v3.defaultBaseMultiplier,\n  size: CALC_CONSTANTS.v3.sizeDefault\n};\n\nfunction v3Calc() {\n  const total = v3State.unitPrice * v3State.baseMultiplier * v3State.size + CALC_CONSTANTS.v3.baseFee;\n  const out = document.getElementById('v3-sum-price');\n  if (out) out.textContent = formatPrice(total);\n}\nfunction v3Toggle(step) {\n  document.querySelectorAll('.v3-step-container').forEach((el, index) => {\n    if ((index + 1) === step) { el.classList.add('active'); } else { el.classList.remove('active'); }\n  });\n}\nfunction v3UpdateType(radio) {\n  document.querySelectorAll('input[name=\"v3-type\"]').forEach((r) => r.closest('.v3-radio-label').classList.remove('checked'));\n  radio.closest('.v3-radio-label').classList.add('checked');\n  document.getElementById('v3-sum-type').textContent = radio.value;\n  const price = CALC_CONSTANTS.v3.optionPrices[parseInt(radio.dataset.v3Option, 10)];\n  v3State.unitPrice = (typeof price === 'number' && price > 0) ? price : CALC_CONSTANTS.v3.defaultUnitPrice;\n  v3Calc();\n  document.getElementById('v3-cont-1').classList.add('completed');\n  setTimeout(() => v3Toggle(2), 300);\n}\nfunction v3UpdateBase(radio) {\n  document.querySelectorAll('input[name=\"v3-base\"]').forEach((r) => r.closest('.v3-radio-label').classList.remove('checked'));\n  radio.closest('.v3-radio-label').classList.add('checked');\n  document.getElementById('v3-sum-base').textContent = radio.value;\n  const mult = CALC_CONSTANTS.v3.baseMultipliers[parseInt(radio.dataset.v3Base, 10)];\n  v3State.baseMultiplier = (typeof mult === 'number' && mult > 0) ? mult : CALC_CONSTANTS.v3.defaultBaseMultiplier;\n  v3Calc();\n  document.getElementById('v3-cont-2').classList.add('completed');\n  setTimeout(() => v3Toggle(3), 300);\n}\nfunction v3UpdateSize(val) {\n  const size = Math.max(CALC_CONSTANTS.v3.sizeMin, parseFloat(val) || CALC_CONSTANTS.v3.sizeMin);\n  v3State.size = size;\n  document.getElementById('v3-sum-size').textContent = size + CALC_CONSTANTS.v3.sizeUnit;\n  v3Calc();\n}\nfunction v3Submit() {\n  const msg = document.getElementById('v3-message');\n  if (msg) msg.hidden = false;\n  document.getElementById('v3-cont-3').classList.add('completed');\n}\n\n/* ---------- initial state ---------- */\n\nv3UpdateSize(CALC_CONSTANTS.v3.sizeDefault);\n\n/* Demo count-up values are configurable via data-count, not client claims. */\nconst countNodes=document.querySelectorAll('[data-count]');\nconst reducedMotion=window.matchMedia('(prefers-reduced-motion: reduce)');\nconst countObserver=new IntersectionObserver(entries=>{\n entries.forEach(entry=>{\n  if(!entry.isIntersecting)return;\n  const el=entry.target, target=Number(el.dataset.count)||0;\n  countObserver.unobserve(el);\n  if(reducedMotion.matches){el.textContent=String(target);return;}\n  const start=performance.now();\n  function tick(now){const t=Math.min((now-start)/1300,1);el.textContent=String(Math.round(target*(1-Math.pow(1-t,3))));if(t<1)requestAnimationFrame(tick);}\n  requestAnimationFrame(tick);\n });\n},{threshold:.3});\ncountNodes.forEach(el=>countObserver.observe(el));\nconst pauseReviews=document.querySelector('.test-pause');\npauseReviews.addEventListener('click',()=>{\n const paused=document.querySelector('.test-columns').classList.toggle('paused');\n pauseReviews.setAttribute('aria-pressed',String(paused));\n pauseReviews.textContent=paused?'Animáció folytatása':'Animáció szüneteltetése';\n});\n// Materials panels are a tap and keyboard accordion on narrow screens. Keep\n// the hover treatment for pointer users, while the explicit state also works\n// when there is no hover surface.\nconst materialPanels=[...document.querySelectorAll('#anyagok .accordion-panel')];\nfunction setMaterialPanel(panel,open){\n materialPanels.forEach(other=>{\n  const active=other===panel&&open;\n  other.classList.toggle('is-open',active);\n  other.setAttribute('aria-expanded',String(active));\n });\n}\nmaterialPanels.forEach(panel=>{\n panel.addEventListener('click',event=>{\n  if(event.target.closest('a,button,input,textarea,select'))return;\n  setMaterialPanel(panel,panel.getAttribute('aria-expanded')!=='true');\n });\n panel.addEventListener('keydown',event=>{\n  if(event.key!=='Enter'&&event.key!==' ')return;\n  event.preventDefault();\n  setMaterialPanel(panel,panel.getAttribute('aria-expanded')!=='true');\n });\n});\n// Reset translated service tracks after every resize so a breakpoint change\n// never leaves an item stranded off the new viewport.\nfunction resetServiceGalleries(){\n document.querySelectorAll('.sd2-gallery-track').forEach(track=>{\n  track.dataset.slide='0';\n  track.style.transition='none';\n  track.style.transform='translateX(0)';\n  track.offsetWidth;\n  track.style.removeProperty('transition');\n });\n}\nwindow.addEventListener('resize',resetServiceGalleries);\ndocument.querySelectorAll('.sd2-expand-btn').forEach(button=>button.addEventListener('keydown',event=>{\n if(event.key!=='Enter'&&event.key!==' ')return;\n event.preventDefault();\n button.click();\n}));\nconst chatWidget=document.getElementById('contact-widget'),chatToggle=chatWidget.querySelector('.chat-toggle'),chatWindow=document.getElementById('chat-window');\nfunction setChat(open){\n chatWindow.hidden=!open;chatToggle.setAttribute('aria-expanded',String(open));\n if(open)document.getElementById('chat-contact').focus();else chatToggle.focus();\n}\nchatToggle.addEventListener('click',()=>setChat(chatWindow.hidden));\nchatWidget.querySelector('.chat-close').addEventListener('click',()=>setChat(false));\nchatWidget.addEventListener('keydown',event=>{if(event.key==='Escape'&&!chatWindow.hidden){event.preventDefault();setChat(false);}});\nchatWidget.querySelector('form').addEventListener('submit',event=>{event.preventDefault();chatWidget.querySelector('.chat-status').hidden=false;});\n// Keep mobile navigation from obscuring the selected destination.\ndocument.querySelectorAll('#mobile-menu a').forEach(link=>link.addEventListener('click',()=>{\n document.getElementById('mobile-menu').classList.remove('open');\n document.querySelector('.mobile-menu-btn').setAttribute('aria-expanded','false');\n}));\n</script>\n<!-- comment-html -->\n<script>\n(() => {\n  \"use strict\";\n  // Interaction model inspired by Impeccable's fixed annotation overlay.\n  // Purpose-built for HTML review. No upstream runtime code is copied here.\n  const DOC = \"design-2-layout-template\";\n  const STYLES = \":host{all:initial;color-scheme:light;--deep:#2a54ff;--cyan:#06daff;--grad:linear-gradient(135deg,#2a54ff,#06daff);--ink:#0b1526;--navy:#0e1730;--card:#16224a;--line:#e3eaf5;--paper:#fff;--soft:#eef4ff;--on-dark:#a9bcd8;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,\\\"Segoe UI\\\",sans-serif}\\n*{box-sizing:border-box}\\n.brand,.gate-brand{display:block;pointer-events:none}\\n.brand{width:20px;height:20px;color:var(--ink)}\\n.gate-brand{width:34px;height:34px;margin:2px auto 12px;color:#fff}\\n.brand svg,.gate-brand svg{display:block;width:100%;height:100%}\\n.highlight{position:fixed;display:none;border:2px solid var(--deep);box-shadow:0 0 0 4px rgba(42,84,255,.18);pointer-events:none;z-index:1}\\n.highlight.show{display:block}\\n.pin{position:fixed;z-index:2;min-width:25px;height:25px;padding:0 7px;border:2px solid #fff;border-radius:999px;background:var(--grad);color:#fff;box-shadow:0 2px 10px rgba(11,21,38,.32);font:700 11px/21px ui-monospace,SFMono-Regular,Menlo,monospace;cursor:pointer;pointer-events:auto;transform:translate(-50%,-50%)}\\n.pin:hover,.pin:focus-visible{transform:translate(-50%,-50%) scale(1.08);outline:2px solid var(--deep);outline-offset:2px}\\n.pin.resolved{background:#5c6c85}\\n.toolbar{position:fixed;right:18px;bottom:18px;z-index:4;display:flex;align-items:center;gap:8px;padding:7px 8px 7px 11px;border:1px solid var(--line);border-radius:999px;background:var(--paper);box-shadow:0 12px 38px rgba(11,21,38,.2);color:var(--ink);pointer-events:auto}\\n.toolbar .state{font:700 11px/1 ui-monospace,SFMono-Regular,Menlo,monospace;white-space:nowrap}\\n.toolbar .dot{width:8px;height:8px;border-radius:50%;background:var(--deep)}\\n.toolbar.off .dot{background:#c3cede}\\n.toolbar.off .brand{opacity:.45}\\n.toolbar button,.panel button{border:0;font:700 11px/1.2 inherit;cursor:pointer}\\n.toggle{padding:7px 10px;border-radius:999px!important;background:var(--ink);color:#fff}\\n.toolbar.off .toggle{background:var(--soft);color:var(--ink)}\\n.panel{position:fixed;z-index:5;width:min(360px,calc(100vw - 24px));max-height:min(560px,calc(100vh - 24px));overflow:auto;padding:14px;border:1px solid rgba(255,255,255,.14);border-radius:14px;background:var(--navy);box-shadow:0 22px 70px rgba(11,21,38,.42);color:#fff;pointer-events:auto}\\n.panel.gate{width:min(260px,calc(100vw - 24px))}\\n.diff{margin-top:7px;font:12px/1.5 inherit;overflow-wrap:anywhere;white-space:pre-wrap}\\n.diff .was{color:#9fb0cd;text-decoration:line-through}\\n.diff .now{margin-top:3px;color:#fff}\\n.panel.gate .field{margin-top:0}\\n.panel-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:12px}\\n.eyebrow{color:var(--cyan);font:700 9px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace;letter-spacing:.1em;text-transform:uppercase}\\n.title{margin-top:5px;font:650 13px/1.35 inherit;overflow-wrap:anywhere}\\n.close{width:28px;height:28px;border-radius:50%!important;background:rgba(255,255,255,.1);color:#fff;font-size:16px!important}\\n.field{display:block;margin-top:9px;color:var(--on-dark);font:600 10px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace}\\n.field input,.field textarea{display:block;width:100%;margin-top:5px;border:1px solid rgba(255,255,255,.18);border-radius:8px;background:var(--card);color:#fff;font:13px/1.45 inherit;outline:none}\\n.field input{padding:9px 10px}\\n.field textarea{min-height:92px;padding:10px;resize:vertical}\\n.field input:focus,.field textarea:focus{border-color:var(--cyan);box-shadow:0 0 0 2px rgba(6,218,255,.22)}\\n.panel.drag{border-color:var(--cyan)}\\n.attachment-preview,.thread-attachments{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:7px;margin-top:9px}\\n.attachment-preview-item{position:relative;min-width:0}.attachment-preview img,.thread-attachments img{display:block;width:100%;height:74px;object-fit:cover;border:1px solid rgba(255,255,255,.16);border-radius:8px;background:var(--card)}\\n.attachment-preview-item button{position:absolute;right:3px;top:3px;width:22px;height:22px;padding:0!important;border-radius:50%!important;background:rgba(11,21,38,.86)!important;color:#fff!important}\\n.actions{display:flex;justify-content:flex-end;gap:7px;margin-top:10px}\\n.actions button{padding:8px 11px;border-radius:8px;background:rgba(255,255,255,.1);color:#fff}\\n.actions .primary{background:var(--grad);color:#fff;box-shadow:0 6px 18px -8px rgba(42,84,255,.9)}\\n.panel.gate .actions{justify-content:stretch}\\n.panel.gate .actions .primary{flex:1;padding:10px 11px}\\n.thread{display:grid;gap:8px}\\n.note{padding:10px;border:1px solid rgba(255,255,255,.12);border-radius:10px;background:var(--card)}\\n.note.resolved{opacity:.58}\\n.meta{display:flex;justify-content:space-between;gap:8px;color:var(--on-dark);font:600 9px/1.3 ui-monospace,SFMono-Regular,Menlo,monospace}\\n.text{margin-top:7px;color:#fff;font:12px/1.5 inherit;white-space:pre-wrap;overflow-wrap:anywhere}\\n.note>textarea{display:block;width:100%;min-height:78px;margin-top:7px;padding:8px;border:1px solid var(--cyan);border-radius:8px;background:#1b2a58;color:#fff;font:12px/1.5 inherit;resize:vertical}\\n.note-actions{display:flex;gap:6px;margin-top:8px}\\n.note-actions button{padding:5px 7px;border-radius:6px;background:rgba(255,255,255,.08);color:var(--on-dark);font-size:10px}\\n.note-actions .danger{color:#ffb4ab}\\n.empty{padding:14px 0;color:var(--on-dark);font-size:12px}\\n.error{margin-top:8px;color:#ffb4ab;font-size:11px}\\n@media(max-width:520px){.toolbar{right:10px;bottom:10px}.toolbar .state{display:none}.panel{left:12px!important;right:12px!important;top:auto!important;bottom:58px;width:auto}.pin{min-width:28px;height:28px;line-height:24px}}\\n\";\n  const WORKER = \"https://pipeline-guide-comments.clientsflowdigital.workers.dev\";\n  const IMAGE_UPSTREAM = \"https://fusion-review-comment-images.clientsflowdigital.workers.dev\";\n  const IMAGE_WORKER = /^(localhost|127\\.0\\.0\\.1)$/.test(location.hostname) ? IMAGE_UPSTREAM : \"/__review-image\";\n  const IMAGE_TYPES = new Set([\"image/png\",\"image/jpeg\",\"image/webp\",\"image/gif\"]);\n  const MAX_IMAGE_BYTES = 8 * 1024 * 1024;\n  // The shared comments Worker persists a fixed field set (id, cid, label, text,\n  // author, ts, resolved, doc) and drops everything else, so the fields it would\n  // lose ride along at the end of text behind this marker and are stripped on read.\n  const META = \"\\n\\n[comment-html]\";\n  const AUTHOR_KEY = \"comment-html-author\";\n  // Exact symbol crop from the original ClientsFlow logo served by clientsflow.hu.\n  const MARK = \"<svg data-comment-html-logo=\\\"original\\\" viewBox=\\\"0 0 57 57\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" aria-hidden=\\\"true\\\"><image href=\\\"[template-media-reference]\" width=\\\"284\\\" height=\\\"57\\\" preserveAspectRatio=\\\"xMinYMid meet\\\"/></svg>\";\n  const DRAFT_PREFIX = \"comment-html-draft:\";\n\n  function brandMark(className) {\n    const holder = document.createElement(\"span\");\n    holder.className = className;\n    holder.innerHTML = MARK;\n    return holder;\n  }\n  const SKIP_TAGS = new Set([\"html\",\"head\",\"body\",\"script\",\"style\",\"link\",\"meta\",\"noscript\",\"br\",\"wbr\",\"template\"]);\n  // Contract paragraphs may start with a bold clause number. Those inline children\n  // still form one editable text layer, while block containers remain comment targets.\n  const INLINE_TEXT_TAGS = new Set([\"a\",\"abbr\",\"b\",\"bdi\",\"bdo\",\"br\",\"cite\",\"code\",\"data\",\"del\",\"em\",\"i\",\"ins\",\"kbd\",\"mark\",\"q\",\"s\",\"samp\",\"small\",\"span\",\"strong\",\"sub\",\"sup\",\"time\",\"u\",\"var\"]);\n  const MIXED_TEXT_PARENT_TAGS = new Set([\"blockquote\",\"caption\",\"dd\",\"dt\",\"figcaption\",\"h1\",\"h2\",\"h3\",\"label\",\"li\",\"p\",\"pre\",\"td\",\"th\"]);\n  // Form controls hold their text in a value, not in child nodes, so contenteditable cannot edit them.\n  const NO_EDIT_TAGS = new Set([\"input\",\"textarea\",\"select\",\"option\",\"svg\",\"img\",\"video\",\"canvas\",\"iframe\"]);\n  if (window.CommentHTML) return;\n\n  let comments = [];\n  // Review mode starts off, so the page under review behaves normally until the\n  // reviewer asks for the layer. Ctrl or Command with Space cycles on, off, hidden.\n  // Numbering IS the Ctrl+Space cycle order. It starts at OFF, so the first press turns\n  // review on, the second hides the toolbar for a clean screen, the third comes back to OFF.\n  const MODE_OFF = 0, MODE_ON = 1, MODE_HIDDEN = 2;\n  let mode = MODE_OFF;\n  let enabled = false;\n  let online = false;\n  let activePanel = null;\n  let highlighted = null;\n  let editing = null;\n  const targetCache = new Map();\n  const originals = new Map();\n  let notice = \"\";\n  let noticeTimer = 0;\n\n  const host = document.createElement(\"div\");\n  host.id = \"comment-html-root\";\n  Object.assign(host.style, {position:\"fixed\",inset:\"0\",zIndex:\"2147483000\",pointerEvents:\"none\"});\n  const shadow = host.attachShadow({mode:\"open\"});\n  const style = document.createElement(\"style\");\n  style.textContent = STYLES;\n  shadow.appendChild(style);\n  const pageStyle = document.createElement(\"style\");\n  pageStyle.textContent =\n    \"[data-comment-html-edited]{outline:2px dashed rgba(42,84,255,.5);outline-offset:2px}\" +\n    \"[data-comment-html-deleted]{text-decoration:line-through!important;opacity:.45!important}\" +\n    \"[data-comment-html-editing]{outline:2px solid #2a54ff!important;outline-offset:2px;background:rgba(6,218,255,.12)!important;cursor:text}\";\n  (document.head || document.documentElement).appendChild(pageStyle);\n\n  const highlight = document.createElement(\"div\");\n  highlight.className = \"highlight\";\n  shadow.appendChild(highlight);\n  const pins = document.createElement(\"div\");\n  shadow.appendChild(pins);\n  document.body.appendChild(host);\n\n  function escapeSelector(value) {\n    return window.CSS && CSS.escape ? CSS.escape(value) : String(value).replace(/[\"\\\\]/g, \"\\\\$&\");\n  }\n\n  function pathFor(el) {\n    const parts = [];\n    let node = el;\n    while (node && node !== document.body && parts.length < 8) {\n      let part = node.tagName.toLowerCase();\n      if (node.id) { part += \"#\" + escapeSelector(node.id); parts.unshift(part); break; }\n      const siblings = node.parentElement ? [...node.parentElement.children].filter(child => child.tagName === node.tagName) : [];\n      if (siblings.length > 1) part += \":nth-of-type(\" + (siblings.indexOf(node) + 1) + \")\";\n      parts.unshift(part);\n      node = node.parentElement;\n    }\n    return \"path:body>\" + parts.join(\">\");\n  }\n\n  function cidFor(el) {\n    if (!el) return \"\";\n    const explicit = el.getAttribute(\"data-cid\");\n    if (explicit) return explicit;\n    if (el.id) return \"id:\" + el.id;\n    const cid = pathFor(el);\n    targetCache.set(cid, el);\n    return cid;\n  }\n\n  function registerTargets() {\n    targetCache.clear();\n    document.querySelectorAll(\"[data-cid]\").forEach(el => {\n      const cid = cidFor(el);\n      if (cid && !targetCache.has(cid)) targetCache.set(cid, el);\n    });\n  }\n\n  function targetFor(cid) {\n    if (targetCache.has(cid) && targetCache.get(cid).isConnected) return targetCache.get(cid);\n    if (cid.startsWith(\"id:\")) return document.getElementById(cid.slice(3));\n    const explicit = document.querySelector('[data-cid=\"' + escapeSelector(cid) + '\"]');\n    if (explicit) return explicit;\n    if (cid.startsWith(\"path:\")) {\n      try {\n        // pathFor always prefixes \"body>\" but stops climbing at the first ancestor\n        // with an id, so the prefix lies whenever that ancestor sits inside a\n        // wrapper (a layout shell's <div class=\"deck\">, for instance). Strip it:\n        // the id already anchors the match uniquely, wrapper or not.\n        const raw = cid.slice(5);\n        const matched = document.querySelector(raw.replace(/^body>/, \"\")) || document.querySelector(raw);\n        if (matched) { targetCache.set(cid, matched); return matched; }\n      } catch (_) {}\n    }\n    registerTargets();\n    return targetCache.get(cid) || null;\n  }\n\n  function pickable(el) {\n    if (!(el instanceof Element) || el === host || SKIP_TAGS.has(el.tagName.toLowerCase())) return false;\n    const rect = el.getBoundingClientRect();\n    if (rect.width < 1 || rect.height < 1) return false;\n    const computed = getComputedStyle(el);\n    return computed.display !== \"none\" && computed.visibility !== \"hidden\";\n  }\n\n  // A text layer is a leaf carrying its own words. Line breaks are kept because\n  // Shift and Enter make them, so only spaces and tabs collapse.\n  function rawText(el) {\n    let out = \"\";\n    for (const node of el.childNodes) {\n      if (node.nodeType === 3) out += node.textContent;\n      else if (node.nodeName === \"BR\") out += \"\\n\";\n      else if (node.nodeType === 1 && INLINE_TEXT_TAGS.has(node.tagName.toLowerCase())) out += rawText(node);\n    }\n    return out.replace(/\\r\\n?/g,\"\\n\").replace(/[^\\S\\n]+/g,\" \").replace(/ *\\n */g,\"\\n\").trim();\n  }\n\n  // Breaks are written as elements so they survive whatever white-space the page sets.\n  function setText(el, text) {\n    el.textContent = \"\";\n    String(text).split(\"\\n\").forEach((line, index) => {\n      if (index) el.appendChild(document.createElement(\"br\"));\n      el.appendChild(document.createTextNode(line));\n    });\n  }\n\n  // Elements with element children are left to the comment flow, because rewriting\n  // them would flatten their markup. A break is the one child a rewrite can produce.\n  function textLayer(el) {\n    if (!(el instanceof Element) || NO_EDIT_TAGS.has(el.tagName.toLowerCase())) return false;\n    const mixedText = Boolean(el.closest(\"[data-comment-html-inline-edit]\") && MIXED_TEXT_PARENT_TAGS.has(el.tagName.toLowerCase()));\n    for (const child of el.children) {\n      if (child.tagName === \"BR\") continue;\n      if (!mixedText || !INLINE_TEXT_TAGS.has(child.tagName.toLowerCase())) return false;\n    }\n    return Boolean(rawText(el));\n  }\n\n  function targetFromEvent(event) {\n    if (event.composedPath().includes(host)) return null;\n    let candidate = Number.isFinite(event.clientX) && Number.isFinite(event.clientY)\n      ? document.elementFromPoint(event.clientX,event.clientY)\n      : event.target;\n    if (candidate && candidate.namespaceURI === \"http://www.w3.org/2000/svg\") {\n      candidate = candidate.closest(\"svg\") || candidate;\n    }\n    while (candidate && candidate !== document.documentElement) {\n      if (pickable(candidate)) return candidate;\n      candidate = candidate.parentElement;\n    }\n    return null;\n  }\n\n  function labelFor(el, cid) {\n    if (!el) return cid;\n    const text = (el.getAttribute(\"aria-label\") || el.getAttribute(\"alt\") || el.getAttribute(\"title\") || el.textContent || cid).replace(/\\s+/g,\" \").trim();\n    return text.length > 88 ? text.slice(0,85) + \"…\" : text || cid;\n  }\n\n  function setHighlight(el) {\n    highlighted = enabled && el && el.isConnected ? el : null;\n    if (!highlighted) { highlight.classList.remove(\"show\"); return; }\n    const rect = highlighted.getBoundingClientRect();\n    if (rect.width < 1 || rect.height < 1) { highlighted = null; highlight.classList.remove(\"show\"); return; }\n    Object.assign(highlight.style, {left:rect.left+\"px\",top:rect.top+\"px\",width:rect.width+\"px\",height:rect.height+\"px\"});\n    highlight.classList.add(\"show\");\n  }\n\n  function storedAuthor() {\n    try { return (localStorage.getItem(AUTHOR_KEY) || \"\").replace(/\\s+/g,\" \").trim(); } catch (_) { return \"\"; }\n  }\n\n  function draftKey(cid) { return DRAFT_PREFIX + DOC + \":\" + cid; }\n\n  function readDraft(cid) {\n    try { return localStorage.getItem(draftKey(cid)) || \"\"; } catch (_) { return \"\"; }\n  }\n\n  function writeDraft(cid, value) {\n    try {\n      if (value) localStorage.setItem(draftKey(cid), value);\n      else localStorage.removeItem(draftKey(cid));\n    } catch (_) {}\n  }\n\n  function grouped() {\n    const map = new Map();\n    comments.forEach(comment => {\n      if (!map.has(comment.cid)) map.set(comment.cid, []);\n      map.get(comment.cid).push(comment);\n    });\n    return map;\n  }\n\n  // Pin labels are a running count of commented targets, ordered by each thread's\n  // first comment, so the first element you comment on stays 1 after any delete.\n  function ordinals() {\n    const ranked = [...grouped().entries()]\n      .map(([cid, thread]) => [cid, Math.min(...thread.map(item => item.ts))])\n      .sort((a, b) => a[1] - b[1]);\n    return new Map(ranked.map(([cid], index) => [cid, index + 1]));\n  }\n\n  function editFor(cid) {\n    return comments\n      .filter(item => item.cid === cid && item.kind === \"edit\")\n      .reduce((latest, item) => !latest || item.ts > latest.ts ? item : latest, null);\n  }\n\n  function threadCount(thread) {\n    const edits = thread.filter(item => item.kind === \"edit\").length;\n    const notes = thread.length - edits;\n    return [notes ? notes + \" megjegyz\\u00e9s\" : \"\", edits ? edits + \" v\\u00e1ltoz\\u00e1s\" : \"\"]\n      .filter(Boolean).join(\" · \") || \"Nincs megjegyz\\u00e9s\";\n  }\n\n  // The page shows the proposed copy, so a reviewer reads the result rather than the request.\n  function applyEdits() {\n    const wanted = new Map();\n    comments.forEach(item => { if (item.kind === \"edit\") wanted.set(item.cid, editFor(item.cid)); });\n    [...originals.keys()].forEach(cid => {\n      if (wanted.has(cid)) return;\n      const el = targetFor(cid);\n      if (el) { setText(el, originals.get(cid)); el.removeAttribute(\"data-comment-html-deleted\"); el.removeAttribute(\"data-comment-html-edited\"); }\n      originals.delete(cid);\n    });\n    wanted.forEach((record, cid) => {\n      const el = targetFor(cid);\n      if (!el || el === (editing && editing.el)) return;\n      const current = rawText(el);\n      const before = record.before != null ? record.before : current;\n      // A published revision can remove nodes and shift path-based targets. Never\n      // replay an old edit onto the element that merely inherited that path. If the\n      // accepted text is already baked into the page, leave its inline markup intact.\n      if (!originals.has(cid) && current === record.text && !record.deleted) return;\n      if (!originals.has(cid) && current !== before) return;\n      if (!originals.has(cid)) originals.set(cid, before);\n      setText(el, record.deleted ? originals.get(cid) : record.text);\n      el.toggleAttribute(\"data-comment-html-deleted\", Boolean(record.deleted));\n      el.toggleAttribute(\"data-comment-html-edited\", !record.deleted);\n    });\n  }\n\n  function pinPoint(el, thread) {\n    const rect = el.getBoundingClientRect();\n    const located = [...thread].reverse().find(item => Number.isFinite(item.xPct) && Number.isFinite(item.yPct));\n    const x = located ? located.xPct : .98;\n    const y = located ? located.yPct : .18;\n    return {\n      left: Math.max(14, Math.min(innerWidth - 14, rect.left + rect.width * x)),\n      top: Math.max(14, Math.min(innerHeight - 14, rect.top + rect.height * y)),\n      visible: rect.bottom >= 0 && rect.top <= innerHeight && rect.right >= 0 && rect.left <= innerWidth\n    };\n  }\n\n  function renderPins() {\n    pins.innerHTML = \"\";\n    if (!enabled) return;\n    const ranks = ordinals();\n    grouped().forEach((thread, cid) => {\n      const el = targetFor(cid);\n      if (!el) return;\n      const point = pinPoint(el, thread);\n      if (!point.visible) return;\n      const button = document.createElement(\"button\");\n      button.type = \"button\";\n      button.className = \"pin\" + (thread.every(item => item.resolved) ? \" resolved\" : \"\");\n      button.textContent = String(ranks.get(cid));\n      button.title = \"#\" + ranks.get(cid) + \" · \" + threadCount(thread);\n      Object.assign(button.style, {left:point.left+\"px\",top:point.top+\"px\"});\n      button.addEventListener(\"mouseenter\", () => setHighlight(el));\n      button.addEventListener(\"mouseleave\", () => { if (!activePanel) setHighlight(null); });\n      button.addEventListener(\"click\", event => { event.stopPropagation(); openThread(el,cid,point); });\n      pins.appendChild(button);\n    });\n  }\n\n  // Clamp against the panel's measured box, not a guessed height, so a composer\n  // grown by image previews or a long thread still sits fully inside the viewport.\n  function clampPanel(panel, point) {\n    const margin = 12;\n    const box = panel.getBoundingClientRect();\n    const width = box.width || Math.min(360, innerWidth - 24);\n    const height = box.height;\n    let left = point.left + 18;\n    if (left + width + margin > innerWidth) left = point.left - width - 18;\n    left = Math.max(margin, Math.min(left, innerWidth - width - margin));\n    let top = point.top - 18;\n    top = Math.max(margin, Math.min(top, innerHeight - height - margin));\n    Object.assign(panel.style, {left:left+\"px\",top:top+\"px\"});\n  }\n\n  function positionPanel(panel, point) {\n    panel.point = point;\n    clampPanel(panel, point);\n    if (typeof ResizeObserver === \"function\") {\n      panel.observer = new ResizeObserver(() => clampPanel(panel, point));\n      panel.observer.observe(panel);\n    }\n  }\n\n  function stopEditing() {\n    if (!editing) return;\n    const {el, onBlur} = editing;\n    editing = null;\n    el.removeEventListener(\"blur\", onBlur);\n    el.removeAttribute(\"contenteditable\");\n    el.removeAttribute(\"data-comment-html-editing\");\n  }\n\n  function closePanel() {\n    stopEditing();\n    if (activePanel && activePanel.observer) activePanel.observer.disconnect();\n    if (activePanel) activePanel.remove();\n    activePanel = null;\n    setHighlight(null);\n  }\n\n  function panelShell(el, cid, eyebrow) {\n    closePanel();\n    const panel = document.createElement(\"section\");\n    panel.className = \"panel\";\n    const head = document.createElement(\"div\");\n    head.className = \"panel-head\";\n    const copy = document.createElement(\"div\");\n    const over = document.createElement(\"div\");\n    over.className = \"eyebrow\";\n    over.textContent = eyebrow;\n    const title = document.createElement(\"div\");\n    title.className = \"title\";\n    title.textContent = labelFor(el,cid);\n    copy.append(over,title);\n    const close = document.createElement(\"button\");\n    close.type = \"button\";\n    close.className = \"close\";\n    close.setAttribute(\"aria-label\",\"Bez\\u00e1r\\u00e1s\");\n    close.textContent = \"×\";\n    close.onclick = closePanel;\n    head.append(copy,close);\n    panel.appendChild(head);\n    shadow.appendChild(panel);\n    activePanel = panel;\n    setHighlight(el);\n    return panel;\n  }\n\n  function encode(record) {\n    const extra = {};\n    if (record.kind) extra.kind = record.kind;\n    if (record.before != null) extra.before = record.before;\n    if (record.deleted) extra.deleted = true;\n    if (Number.isFinite(record.xPct)) extra.xPct = record.xPct;\n    if (Number.isFinite(record.yPct)) extra.yPct = record.yPct;\n    if ((record.attachments || []).length) extra.attachments = record.attachments;\n    const body = Object.assign({}, record, {text: record.text || \"\"});\n    if (Object.keys(extra).length) body.text += META + JSON.stringify(extra);\n    return body;\n  }\n\n  function decode(record) {\n    const text = record.text || \"\";\n    const at = text.lastIndexOf(META);\n    if (at < 0) return record;\n    try {\n      const extra = JSON.parse(text.slice(at + META.length));\n      return Object.assign({}, record, extra, {text: text.slice(0,at)});\n    } catch (_) { return record; }\n  }\n\n  async function post(record) {\n    const response = await fetch(WORKER + \"/comments?doc=\" + encodeURIComponent(DOC), {\n      method:\"POST\",headers:{\"Content-Type\":\"application/json\"},body:JSON.stringify(encode(record))\n    });\n    if (!response.ok) throw new Error(\"Save failed\");\n    online = true;\n  }\n\n  async function remove(record) {\n    const response = await fetch(WORKER + \"/comments?doc=\" + encodeURIComponent(DOC) + \"&id=\" + encodeURIComponent(record.id), {method:\"DELETE\"});\n    if (!response.ok) throw new Error(\"Delete failed\");\n    online = true;\n  }\n\n  function safeImageUrl(value) {\n    try {\n      const url = new URL(value,location.href);\n      const direct = new URL(IMAGE_UPSTREAM);\n      const proxied = url.origin === location.origin && url.pathname.startsWith(\"/__review-image/files/\");\n      const upstream = url.origin === direct.origin && url.pathname.startsWith(\"/files/\");\n      return proxied || upstream ? url.href : \"\";\n    } catch (_) { return \"\"; }\n  }\n\n  function imageFromFile(file) {\n    return new Promise((resolve,reject) => {\n      const image = new Image();\n      const url = URL.createObjectURL(file);\n      image.onload = () => { URL.revokeObjectURL(url); resolve(image); };\n      image.onerror = () => { URL.revokeObjectURL(url); reject(new Error(\"A k\\u00e9p nem olvashat\\u00f3.\")); };\n      image.src = url;\n    });\n  }\n\n  async function makeThumbnail(file) {\n    const image = await imageFromFile(file);\n    const scale = Math.min(1,384 / Math.max(image.naturalWidth,image.naturalHeight));\n    const canvas = document.createElement(\"canvas\");\n    canvas.width = Math.max(1,Math.round(image.naturalWidth * scale));\n    canvas.height = Math.max(1,Math.round(image.naturalHeight * scale));\n    canvas.getContext(\"2d\",{alpha:false}).drawImage(image,0,0,canvas.width,canvas.height);\n    const blob = await new Promise(resolve => canvas.toBlob(resolve,\"image/webp\",.82));\n    if (!blob) throw new Error(\"A k\\u00e9p el\\u0151n\\u00e9zete nem k\\u00e9sz\\u00fclt el.\");\n    return new File([blob],\"thumbnail.webp\",{type:\"image/webp\"});\n  }\n\n  async function uploadAttachment(file,commentId) {\n    const thumbnail = await makeThumbnail(file);\n    const form = new FormData();\n    form.append(\"doc\",DOC);\n    form.append(\"comment\",commentId);\n    form.append(\"original\",file,file.name || \"image\");\n    form.append(\"thumbnail\",thumbnail,\"thumbnail.webp\");\n    const response = await fetch(IMAGE_WORKER + \"/upload\",{method:\"POST\",body:form});\n    const body = await response.json().catch(() => ({}));\n    if (!response.ok) throw new Error(body.error || \"A k\\u00e9p felt\\u00f6lt\\u00e9se nem siker\\u00fclt.\");\n    if (!safeImageUrl(body.originalUrl) || !safeImageUrl(body.thumbnailUrl)) throw new Error(\"A k\\u00e9p c\\u00edme \\u00e9rv\\u00e9nytelen.\");\n    return {\n      originalUrl:body.originalUrl,thumbnailUrl:body.thumbnailUrl,mimeType:body.mimeType,\n      byteSize:body.byteSize,sha256:body.sha256,width:body.width ?? null,height:body.height ?? null\n    };\n  }\n\n  async function deleteAttachment(attachment,commentId) {\n    const urls = new Set([attachment.originalUrl,attachment.thumbnailUrl].map(safeImageUrl).filter(Boolean));\n    await Promise.all([...urls].map(async value => {\n      try {\n        const url = new URL(value);\n        url.searchParams.set(\"doc\",DOC);\n        url.searchParams.set(\"comment\",commentId);\n        await fetch(url,{method:\"DELETE\"});\n      } catch (_) {}\n    }));\n  }\n\n  function validateImages(files) {\n    const accepted = [], errors = [];\n    [...files].forEach(file => {\n      if (!IMAGE_TYPES.has(file.type)) errors.push((file.name || \"F\\u00e1jl\") + \": PNG, JPEG, WebP vagy GIF lehet.\");\n      else if (!file.size || file.size > MAX_IMAGE_BYTES) errors.push((file.name || \"F\\u00e1jl\") + \": legfeljebb 8 MB.\");\n      else accepted.push(file);\n    });\n    return {accepted,errors};\n  }\n\n  // Asked once per browser, before the first comment. The mark sits on top, then the\n  // name and the one button, so Enter and Ment\\u00e9s do the same thing and Escape cancels.\n  function openNameGate(el, point, onAccept) {\n    closePanel();\n    const panel = document.createElement(\"section\");\n    panel.className = \"panel gate\";\n    const label = document.createElement(\"label\");\n    label.className = \"field\";\n    label.textContent = \"N\\u00e9v:\";\n    const input = document.createElement(\"input\");\n    input.maxLength = 80;\n    input.setAttribute(\"aria-label\",\"N\\u00e9v\");\n    label.appendChild(input);\n    const actions = document.createElement(\"div\");\n    actions.className = \"actions\";\n    const save = document.createElement(\"button\");\n    save.type = \"button\"; save.className = \"primary\"; save.textContent = \"Ment\\u00e9s\";\n    actions.appendChild(save);\n    panel.append(brandMark(\"gate-brand\"),label,actions);\n    shadow.appendChild(panel);\n    activePanel = panel;\n    setHighlight(el);\n    positionPanel(panel, point);\n    const accept = () => {\n      const name = input.value.replace(/\\s+/g,\" \").trim();\n      if (!name) { input.focus(); return; }\n      try { localStorage.setItem(AUTHOR_KEY, name); } catch (_) {}\n      closePanel();\n      onAccept();\n    };\n    save.onclick = event => { event.stopPropagation(); accept(); };\n    // Read by the single capture-phase key handler; Escape falls through to the close.\n    panel.onkey = event => {\n      if (event.key !== \"Enter\") return false;\n      event.preventDefault(); accept(); return true;\n    };\n    setTimeout(() => input.focus(), 0);\n  }\n\n  // Click a text layer and you rewrite it in place. The outline is the whole editor:\n  // leaving it or pressing Enter saves, Escape reverts, Shift and Enter break the line.\n  // The record keeps the original, so the pin shows before and after.\n  function openInlineEditor(el, cid, ratios) {\n    closePanel();\n    const existing = editFor(cid);\n    const before = existing && existing.before != null ? existing.before : rawText(el);\n    if (!originals.has(cid)) originals.set(cid, before);\n\n    const onBlur = () => { if (editing && editing.el === el) commitEdit(); };\n    editing = {el, cid, before, ratios, saving:false, onBlur};\n    el.setAttribute(\"contenteditable\",\"plaintext-only\");\n    el.setAttribute(\"data-comment-html-editing\",\"\");\n    el.removeAttribute(\"data-comment-html-deleted\");\n    el.addEventListener(\"blur\", onBlur);\n    setHighlight(el);\n    el.focus();\n    const range = document.createRange(); range.selectNodeContents(el);\n    const selection = getSelection(); selection.removeAllRanges(); selection.addRange(range);\n  }\n\n  function cancelEdit() {\n    if (!editing) return;\n    stopEditing(); closePanel(); applyEdits(); renderPins();\n  }\n\n  // Clearing the text is the delete gesture, and it strikes the copy through rather\n  // than removing it, so the pin stays reachable and the change stays revertible.\n  async function commitEdit() {\n    if (!editing || editing.saving) return;\n    const session = editing;\n    const {el, cid, before, ratios} = session;\n    const after = rawText(el);\n    const deleted = !after;\n    const existing = editFor(cid);\n    if (!existing && after === before) { cancelEdit(); return; }\n    const record = existing\n      ? Object.assign({}, existing, {text: deleted ? before : after, deleted, ts: Date.now(), author: storedAuthor() || existing.author})\n      : {id:crypto.randomUUID(), cid, kind:\"edit\", label:labelFor(el,cid), before, text: deleted ? before : after,\n         deleted, author:storedAuthor() || \"Reviewer\", ts:Date.now(), resolved:false, doc:DOC,\n         xPct:ratios.xPct, yPct:ratios.yPct, attachments:[]};\n    session.saving = true;\n    try {\n      await post(record);\n      const at = comments.findIndex(item => item.id === record.id);\n      if (at > -1) comments[at] = record; else comments.push(record);\n      stopEditing(); closePanel(); applyEdits(); updateToolbar(); renderPins();\n    } catch (caught) {\n      session.saving = false;\n      flash(caught.message || \"Nem siker\\u00fclt menteni. Pr\\u00f3b\\u00e1ld \\u00fajra.\");\n      el.focus();\n    }\n  }\n\n  function withAuthor(el, point, run) {\n    if (storedAuthor()) run(); else openNameGate(el, point, run);\n  }\n\n  function openComposer(el, cid, point, ratios) {\n    const panel = panelShell(el,cid,\"\\u00daj megjegyz\\u00e9s\");\n    const textLabel = document.createElement(\"label\");\n    textLabel.className = \"field\";\n    textLabel.textContent = \"Megjegyz\\u00e9s\";\n    const textarea = document.createElement(\"textarea\");\n    textLabel.appendChild(textarea);\n    const preview = document.createElement(\"div\");\n    preview.className = \"attachment-preview\";\n    const error = document.createElement(\"div\");\n    error.className = \"error\";\n    const actions = document.createElement(\"div\");\n    actions.className = \"actions\";\n    const cancel = document.createElement(\"button\");\n    cancel.type = \"button\"; cancel.textContent = \"M\\u00e9gse\";\n    cancel.onclick = event => { event.stopPropagation(); writeDraft(cid,\"\"); closePanel(); };\n    const save = document.createElement(\"button\");\n    save.type = \"button\"; save.className = \"primary\"; save.textContent = \"Ment\\u00e9s\";\n    actions.append(cancel,save);\n    panel.append(textLabel,preview,error,actions);\n    let staged = [];\n    const showError = message => { error.textContent = message; };\n\n    // The draft is the only thing that survives an accidental close, so it is\n    // written on every keystroke and cleared only by an explicit save or cancel.\n    textarea.value = readDraft(cid);\n    textarea.addEventListener(\"input\", () => writeDraft(cid, textarea.value));\n    panel.dirty = () => Boolean(textarea.value.trim() || staged.length);\n\n    const renderPreview = () => {\n      preview.innerHTML = \"\";\n      staged.forEach(file => {\n        const item = document.createElement(\"div\"); item.className = \"attachment-preview-item\";\n        const image = document.createElement(\"img\"); image.className = \"attachment-preview-image\"; image.alt = file.name || \"Attached image\";\n        const url = URL.createObjectURL(file); image.src = url; image.onload = () => URL.revokeObjectURL(url);\n        const removeButton = document.createElement(\"button\"); removeButton.type = \"button\"; removeButton.textContent = \"×\"; removeButton.setAttribute(\"aria-label\",(file.name || \"K\\u00e9p\") + \" elt\\u00e1vol\\u00edt\\u00e1sa\");\n        // Identify by the file itself: a captured index goes stale after a removal.\n        removeButton.onclick = event => {\n          event.stopPropagation();\n          const at = staged.indexOf(file);\n          if (at > -1) staged.splice(at,1);\n          renderPreview();\n        };\n        item.append(image,removeButton); preview.appendChild(item);\n      });\n    };\n    const addFiles = files => {\n      const result = validateImages(files);\n      staged.push(...result.accepted);\n      showError(result.errors.join(\" \"));\n      renderPreview();\n    };\n    // Bound on the panel, not the textarea, so a paste lands wherever focus sits.\n    panel.addEventListener(\"paste\",event => {\n      const files = [...(event.clipboardData?.items || [])].filter(item => item.kind === \"file\").map(item => item.getAsFile()).filter(Boolean);\n      if (files.length) { event.preventDefault(); event.stopPropagation(); addFiles(files); }\n    });\n    panel.ondragover = event => { event.preventDefault(); event.stopPropagation(); panel.classList.add(\"drag\"); };\n    panel.ondragleave = event => { event.preventDefault(); event.stopPropagation(); panel.classList.remove(\"drag\"); };\n    panel.ondrop = event => { event.preventDefault(); event.stopPropagation(); panel.classList.remove(\"drag\"); addFiles(event.dataTransfer.files); };\n\n    async function submit() {\n      if (save.disabled) return;\n      const body = textarea.value.trim();\n      if (!body && !staged.length) { showError(\"\\u00cdrj valamit, vagy tegy\\u00e9l be k\\u00e9pet.\"); return; }\n      const id = crypto.randomUUID();\n      const attachments = [];\n      save.disabled = true; save.textContent = staged.length ? \"Felt\\u00f6lt\\u00e9s…\" : \"Ment\\u00e9s…\"; showError(\"\");\n      try {\n        for (const file of staged) attachments.push(await uploadAttachment(file,id));\n        const record = {id,cid,label:labelFor(el,cid),text:body,author:storedAuthor() || \"Reviewer\",ts:Date.now(),resolved:false,doc:DOC,xPct:ratios.xPct,yPct:ratios.yPct,attachments};\n        await post(record); comments.push(record); writeDraft(cid,\"\"); closePanel(); updateToolbar(); renderPins();\n      } catch (caught) {\n        await Promise.all(attachments.map(attachment => deleteAttachment(attachment,id)));\n        save.disabled = false; save.textContent = \"Ment\\u00e9s\"; showError(caught.message || \"Nem siker\\u00fclt menteni. Pr\\u00f3b\\u00e1ld \\u00fajra.\");\n      }\n    }\n    save.onclick = event => { event.stopPropagation(); submit(); };\n    panel.onkey = event => {\n      if (!(event.metaKey || event.ctrlKey) || event.key !== \"Enter\") return false;\n      event.preventDefault(); submit(); return true;\n    };\n\n    positionPanel(panel,point);\n    // Focus before returning from the click handler so a fast first keystroke is\n    // entered in the composer instead of being swallowed while focus is still on the page.\n    textarea.focus();\n  }\n\n  function openThread(el, cid, point) {\n    const thread = comments.filter(item => item.cid === cid).sort((a,b) => a.ts - b.ts);\n    const panel = panelShell(el,cid,threadCount(thread));\n    const list = document.createElement(\"div\");\n    list.className = \"thread\";\n    thread.forEach(record => {\n      const note = document.createElement(\"article\");\n      note.className = \"note\" + (record.resolved ? \" resolved\" : \"\");\n      const meta = document.createElement(\"div\"); meta.className = \"meta\";\n      const who = document.createElement(\"span\"); who.textContent = record.author || \"Reviewer\";\n      const when = document.createElement(\"span\"); when.textContent = new Date(record.ts).toLocaleString();\n      meta.append(who,when);\n      const body = document.createElement(\"div\");\n      if (record.kind === \"edit\") {\n        body.className = \"diff\";\n        const was = document.createElement(\"div\"); was.className = \"was\"; was.textContent = record.before || \"\";\n        const now = document.createElement(\"div\"); now.className = \"now\"; now.textContent = record.deleted ? \"(t\\u00f6r\\u00f6lve)\" : (record.text || \"\");\n        body.append(was,now);\n      } else { body.className = \"text\"; body.textContent = record.text || \"\"; }\n      const attachmentList = document.createElement(\"div\"); attachmentList.className = \"thread-attachments\";\n      (record.attachments || []).forEach(attachment => {\n        const original = safeImageUrl(attachment.originalUrl), thumbnail = safeImageUrl(attachment.thumbnailUrl);\n        if (!original || !thumbnail) return;\n        const link = document.createElement(\"a\"); link.href = original; link.target = \"_blank\"; link.rel = \"noreferrer\";\n        const image = document.createElement(\"img\"); image.src = thumbnail; image.alt = \"Attached image\";\n        link.appendChild(image); attachmentList.appendChild(link);\n      });\n      const actions = document.createElement(\"div\"); actions.className = \"note-actions\";\n      const resolve = document.createElement(\"button\"); resolve.type = \"button\"; resolve.textContent = record.resolved ? \"\\u00dajranyit\\u00e1s\" : \"K\\u00e9sz\";\n      const edit = document.createElement(\"button\"); edit.type = \"button\"; edit.className = \"edit\"; edit.textContent = \"Szerkeszt\\u00e9s\";\n      const del = document.createElement(\"button\"); del.type = \"button\"; del.className = \"danger\"; del.textContent = \"T\\u00f6rl\\u00e9s\";\n      resolve.onclick = async event => { event.stopPropagation(); const before = record.resolved; record.resolved = !before; try { await post(record); openThread(el,cid,point); renderPins(); } catch (_) { record.resolved = before; } };\n      edit.onclick = event => {\n        event.stopPropagation();\n        const textarea = document.createElement(\"textarea\"); textarea.value = record.text || \"\"; body.replaceWith(textarea);\n        actions.innerHTML = \"\";\n        const saveEdit = document.createElement(\"button\"); saveEdit.type = \"button\"; saveEdit.className = \"edit\"; saveEdit.textContent = \"Ment\\u00e9s\";\n        const cancelEdit = document.createElement(\"button\"); cancelEdit.type = \"button\"; cancelEdit.textContent = \"M\\u00e9gse\";\n        actions.append(saveEdit,cancelEdit); textarea.focus();\n        saveEdit.onclick = async saveEvent => {\n          saveEvent.stopPropagation();\n          const next = textarea.value.trim();\n          if (!next && !(record.attachments || []).length) return;\n          const before = record.text, beforeTs = record.ts;\n          record.text = next; record.ts = Date.now();\n          try { await post(record); openThread(el,cid,point); }\n          catch (_) { record.text = before; record.ts = beforeTs; }\n        };\n        cancelEdit.onclick = cancelEvent => { cancelEvent.stopPropagation(); openThread(el,cid,point); };\n      };\n      del.onclick = async event => {\n        event.stopPropagation();\n        if (!confirm(\"T\\u00f6rl\\u00f6d ezt a megjegyz\\u00e9st?\")) return;\n        try {\n          await remove(record);\n          await Promise.all((record.attachments || []).map(attachment => deleteAttachment(attachment,record.id)));\n          comments = comments.filter(item => item.id !== record.id);\n          if (record.kind === \"edit\") applyEdits();\n          openThread(el,cid,point); updateToolbar(); renderPins();\n        } catch (_) {}\n      };\n      if (record.kind === \"edit\") actions.append(resolve,del); else actions.append(resolve,edit,del);\n      note.append(meta,body); if (attachmentList.childElementCount) note.appendChild(attachmentList); note.appendChild(actions); list.appendChild(note);\n    });\n    if (!thread.length) { const empty = document.createElement(\"div\"); empty.className=\"empty\"; empty.textContent=\"Nincs megjegyz\\u00e9s.\"; list.appendChild(empty); }\n    const add = document.createElement(\"button\"); add.type=\"button\"; add.className=\"primary\"; add.textContent=\"\\u00daj megjegyz\\u00e9s\";\n    const actions = document.createElement(\"div\"); actions.className=\"actions\"; actions.appendChild(add);\n    add.onclick = event => {\n      event.stopPropagation();\n      const rect = el.getBoundingClientRect();\n      const ratios = {xPct:(point.left-rect.left)/Math.max(1,rect.width),yPct:(point.top-rect.top)/Math.max(1,rect.height)};\n      withAuthor(el, point, () => openComposer(el,cid,point,ratios));\n    };\n    panel.append(list,actions);\n    positionPanel(panel,point);\n  }\n\n  const toolbar = document.createElement(\"div\");\n  toolbar.className = \"toolbar\";\n  const statusDot = document.createElement(\"span\"); statusDot.className = \"dot\";\n  const state = document.createElement(\"span\"); state.className = \"state\";\n  const toggle = document.createElement(\"button\"); toggle.type=\"button\"; toggle.className=\"toggle\";\n  toolbar.append(brandMark(\"brand\"),statusDot,state,toggle); shadow.appendChild(toolbar);\n\n  function flash(message) {\n    notice = message;\n    clearTimeout(noticeTimer);\n    noticeTimer = setTimeout(() => { notice = \"\"; updateToolbar(); }, 5000);\n    updateToolbar();\n  }\n\n  function updateToolbar() {\n    toolbar.classList.toggle(\"off\",!enabled);\n    state.textContent = notice || threadCount(comments) + (online ? \"\" : \" · t\\u00f6lt\\u00e9s\");\n    toggle.textContent = enabled ? \"V\\u00e9lem\\u00e9ny be\" : \"V\\u00e9lem\\u00e9ny ki\";\n    toggle.setAttribute(\"aria-pressed\",String(enabled));\n  }\n\n  // The button flips between on and off and never hides the bar; only the shortcut does.\n  toggle.onclick = event => {\n    event.stopPropagation(); setMode(mode === MODE_ON ? MODE_OFF : MODE_ON);\n  };\n\n  function setMode(next) {\n    mode = next;\n    enabled = mode === MODE_ON;\n    closePanel();\n    host.style.display = mode === MODE_HIDDEN ? \"none\" : \"\";\n    updateToolbar(); renderPins();\n  }\n\n  [\"pointerdown\",\"mousedown\",\"focusin\"].forEach(type => shadow.addEventListener(type,event => event.stopPropagation()));\n  document.addEventListener(\"pointermove\", event => {\n    if (!enabled || activePanel || editing) return;\n    const next = targetFromEvent(event);\n    if (next !== highlighted) setHighlight(next);\n  },true);\n  document.addEventListener(\"click\", event => {\n    if (!enabled || event.composedPath().includes(host)) return;\n    // Clicks inside the element being rewritten place the caret; they are not targeting.\n    if (editing && editing.el.contains(event.target)) return;\n    const el = targetFromEvent(event);\n    if (!el) return;\n    event.preventDefault(); event.stopPropagation();\n    // An open editor or a composer holding unsaved work is settled by this click and\n    // never silently swapped onto another target. The next click starts the new one.\n    if (editing) { commitEdit(); return; }\n    if (activePanel && activePanel.dirty && activePanel.dirty()) { closePanel(); return; }\n    const rect = el.getBoundingClientRect();\n    const point = {left:event.clientX,top:event.clientY};\n    const ratios = {xPct:(event.clientX-rect.left)/Math.max(1,rect.width),yPct:(event.clientY-rect.top)/Math.max(1,rect.height)};\n    // Text rewrites in place; everything else comments. Ctrl or Command asks for the\n    // comment on a text layer too.\n    const cid = cidFor(el);\n    if (!(event.metaKey || event.ctrlKey) && textLayer(el)) {\n      withAuthor(el, point, () => openInlineEditor(el,cid,ratios));\n      return;\n    }\n    withAuthor(el, point, () => openComposer(el,cid,point,ratios));\n  },true);\n  // A host page that binds Space or the arrow keys (a slide deck) must never see the\n  // reviewer typing, so the layer's keys are handled here and stopped in the capture\n  // phase, before the page or any of its own listeners can read them. Stopping the\n  // propagation is not preventing the default, so typing still enters the field.\n  // An open panel counts too: its field is focused a tick after it is drawn, and the\n  // first keystroke of a fast reviewer must not fall through to the page in between.\n  const layerKey = event => Boolean(editing) || Boolean(activePanel) || event.composedPath().includes(host);\n  const composing = event => Boolean(editing) || Boolean(activePanel && event.composedPath().includes(activePanel));\n  const swallow = event => { event.stopPropagation(); event.stopImmediatePropagation(); };\n\n  // Bound on the window, not on the document: a host page that already listens on\n  // the document in the capture phase would otherwise read the key before us.\n  window.addEventListener(\"keydown\", event => {\n    // The cycle answers from anywhere except mid-sentence in the layer's own fields.\n    if (event.code === \"Space\" && (event.ctrlKey || event.metaKey) && !composing(event)) {\n      event.preventDefault(); swallow(event);\n      setMode((mode + 1) % 3);\n      return;\n    }\n    // Escape still closes an open panel from anywhere, exactly as it did before.\n    if (!layerKey(event)) { if (event.key === \"Escape\") closePanel(); return; }\n    if (editing) {\n      if (event.key === \"Escape\") { event.preventDefault(); cancelEdit(); }\n      else if (event.key === \"Enter\" && !event.shiftKey) { event.preventDefault(); commitEdit(); }\n    } else {\n      // The open panel reads its own keys here, and Escape closes what it leaves.\n      const handled = activePanel && activePanel.onkey && activePanel.onkey(event);\n      if (!handled && event.key === \"Escape\") closePanel();\n    }\n    swallow(event);\n  }, true);\n  // A stopped keydown still leaves a keypress and a keyup for the page to act on,\n  // the shortcut's own Space included. Bare modifier keys are left alone.\n  [\"keypress\",\"keyup\"].forEach(type => window.addEventListener(type, event => {\n    if (layerKey(event) || (event.code === \"Space\" && (event.ctrlKey || event.metaKey))) swallow(event);\n  }, true));\n  window.addEventListener(\"scroll\", () => { setHighlight(highlighted); renderPins(); },{passive:true});\n  window.addEventListener(\"resize\", () => {\n    setHighlight(highlighted); renderPins();\n    if (activePanel && activePanel.point) clampPanel(activePanel, activePanel.point);\n  });\n\n  async function load() {\n    registerTargets(); updateToolbar();\n    try {\n      const response = await fetch(WORKER + \"/comments?doc=\" + encodeURIComponent(DOC));\n      if (!response.ok) throw new Error(\"Load failed\");\n      comments = (await response.json()).map(decode); online = true;\n    } catch (_) { comments = []; online = false; }\n    applyEdits(); updateToolbar(); renderPins();\n  }\n\n  window.CommentHTML = Object.freeze({refresh:() => {registerTargets();applyEdits();renderPins();},documentId:DOC});\n  load();\n})();\n\n</script>\n<!-- /comment-html -->\n</body>\n</html>\n"
          }
        ]
      }
    ],
    "generationConfig": {
      "maxOutputTokens": 24576,
      "temperature": 0.65,
      "thinkingConfig": {
        "thinkingLevel": "LOW"
      }
    }
  },
  "credential_included": false
}