{"id":17926,"date":"2026-06-09T18:18:51","date_gmt":"2026-06-09T15:18:51","guid":{"rendered":"https:\/\/zeolife.gr\/?page_id=17926"},"modified":"2026-10-20T20:50:38","modified_gmt":"2026-10-20T17:50:38","slug":"zeolite-agriculture-dosage-calculator","status":"publish","type":"page","link":"https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/","title":{"rendered":"Zeolite Agricultural Dosage Guide"},"content":{"rendered":"\n<!-- ==========================================================\n     Zeolite Dosage Guide for Agriculture  (CLEAN) \u2014 ENGLISH\n     20\/10\/2026: Print moved out of the buttons (now centred) to the bottom, into the \"Keep your dosage\" box.\n     20\/10\/2026: Link with the spray guide in both directions (?crop= + trees= \/ stremma=).\n     20\/10\/2026: One-click cart (zl_cart) and return from the eShop without losing the choices (sessionStorage).\n     20\/10\/2026: \"Keep your dosage\": email + reminders per year (Toolkit >= 2.156.0, kind=soil) \u00b7 .ics calendar \u00b7 print.\n     20\/10\/2026: combined yearly program (ZL YEAR, Toolkit >= 2.157.0, kind=combo) when a spray program also exists.\n     Path: \/en\/zeolite-agriculture-dosage-calculator\/\n     ----------------------------------------------------------\n     NO <style>\/<link> (AMP safe) \u2014 styling comes from the\n     Customizer, section \u00a716 .zlcalc (shared by all guides).\n     JS stays here, in an IIFE, as defined by Web Style 2026.\n     Root hook for the JS: id=\"zaCalc\".\n     04\/10\/2026: light\/medium soil \u2192 fine gravel (never powder).\n     ========================================================== -->\n<script type=\"application\/ld+json\">\n{\n  \"@context\": \"https:\/\/schema.org\",\n  \"@graph\": [\n    {\n      \"@type\": \"WebApplication\",\n      \"name\": \"Zeolite Dosage Guide for Agriculture (Online Calculator)\",\n      \"alternateName\": \"Zeolite Dosage Calculator for Agriculture\",\n      \"url\": \"https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/\",\n      \"description\": \"Interactive zeolite dosage guide for agricultural use (online calculator): olive, vineyard, walnut, fruit trees, pistachio trees, cereals, watermelons\/melons, alfalfa, aromatic herbs (oregano, thyme), lawn \/ turf, vegetable garden, ornamentals. Supports 3 brands (Greek Thracian, IMERYS, ZeoGravel\u00ae ZEOCEM) and 3 soil types.\",\n      \"applicationCategory\": \"AgricultureApplication\",\n      \"operatingSystem\": \"Any (web)\",\n      \"inLanguage\": \"en\",\n      \"isAccessibleForFree\": true,\n      \"audience\": {\n        \"@type\": \"Audience\",\n        \"audienceType\": \"Farmers, Agronomists, Agricultural Cooperatives\"\n      },\n      \"publisher\": { \"@type\": \"Organization\", \"name\": \"Zeolife\", \"url\": \"https:\/\/zeolife.gr\/\" }\n    },\n    {\n      \"@type\": \"HowTo\",\n      \"name\": \"How to calculate the right zeolite dose for your agricultural application\",\n      \"description\": \"Guide for calculating zeolite dosage by crop, soil type and product brand.\",\n      \"step\": [\n        { \"@type\": \"HowToStep\", \"name\": \"Choose your crop\", \"text\": \"Pick from 15 categories: olive, vineyard, walnut, fruit trees, pistachio trees, cereals, watermelons\/melons, alfalfa, aromatic herbs (oregano, thyme), lawn \/ turf, vegetable garden, ornamentals, seedling production, cacti, palm trees. If your crop is not listed, ask us for a personalised recommendation.\" },\n        { \"@type\": \"HowToStep\", \"name\": \"Enter the quantity\", \"text\": \"Enter the number of trees\/vines\/plants or the area in stremmata (1 stremma = 1,000 m\u00b2). For trees and vines, choose the planting phase. For lawn and vegetable gardens enter square metres (m\u00b2).\" },\n        { \"@type\": \"HowToStep\", \"name\": \"Choose your soil type\", \"text\": \"Light (sandy), Medium (loamy) or Heavy (clay). This determines the zeolite grain size.\" },\n        { \"@type\": \"HowToStep\", \"name\": \"Choose a brand\", \"text\": \"Greek Thracian, IMERYS, ZeoGravel\u00ae (ZEOCEM) or let us recommend one.\" },\n        { \"@type\": \"HowToStep\", \"name\": \"Application strategy\", \"text\": \"First year (40%), full 3-year programme, or maintenance. For perennial crops such as lawn \/ turf, application is one-off.\" }\n      ]\n    }\n  ]\n}\n<\/script>\n<div class=\"zl zlcalc\" id=\"zaCalc\">\n<div class=\"progress\" aria-hidden=\"true\"><div class=\"progress-bar\" id=\"zaProgress\"><\/div><\/div>\n<div id=\"zaProgressSpacer\" aria-hidden=\"true\" style=\"height:0\"><\/div>\n<div class=\"intro\">\n  <h2>\ud83c\udf3e Zeolite Dosage Guide for Agricultural Use<\/h2>\n  <p>Give us 5 pieces of information and we&#8217;ll recommend the <strong>right product<\/strong> from our 3 ranges (Greek Thracian, IMERYS, ZeoGravel\u00ae ZEOCEM) with <strong>exact dosage<\/strong>, a 3-year programme and automatic discount calculation.<\/p>\n  <div class=\"badges\">\n    <span class=\"badge\">\ud83d\udccb 5-step guide<\/span>\n    <span class=\"badge\">15 crops<\/span>\n    <span class=\"badge\">3 brands \u00d7 9 products<\/span>\n    <span class=\"badge\">3-year programme<\/span>\n    <span class=\"badge\">Auto-discount up to 40%<\/span>\n  <\/div>\n<\/div>\n<!-- STEP 1: CROP -->\n<div class=\"step active\" data-step=\"1\">\n  <h3><span class=\"step-num\">1<\/span>Choose your crop<\/h3>\n  <div class=\"options cols-3\">\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"olive\">\n      <span class=\"opt-title\">\ud83e\uded2 Olive trees<\/span>\n      <span class=\"opt-desc\">8-24 kg\/tree<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"walnut\">\n      <span class=\"opt-title\">\ud83e\udd5c Walnut trees<\/span>\n      <span class=\"opt-desc\">8-24 kg\/tree<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"fruit\">\n      <span class=\"opt-title\">\ud83c\udf4e Fruit trees<\/span>\n      <span class=\"opt-desc\">5-15 kg\/tree<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"pistachio\">\n      <span class=\"opt-title\">\ud83c\udf30 Pistachio trees<\/span>\n      <span class=\"opt-desc\">5-15 kg\/tree<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"vineyard\">\n      <span class=\"opt-title\">\ud83c\udf47 Vineyard<\/span>\n      <span class=\"opt-desc\">0.4-1.2 kg\/vine<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"palm\">\n      <span class=\"opt-title\">\ud83c\udf34 Palm trees<\/span>\n      <span class=\"opt-desc\">up to 24 kg\/tree<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"cereals\">\n      <span class=\"opt-title\">\ud83c\udf3e Cereals \/ Maize<\/span>\n      <span class=\"opt-desc\">up to 300 kg\/stremma<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"melons\">\n      <span class=\"opt-title\">\ud83c\udf49 Watermelons \/ Melons<\/span>\n      <span class=\"opt-desc\">up to 450 kg\/stremma<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"alfalfa\">\n      <span class=\"opt-title\">\ud83c\udf40 Alfalfa (lucerne)<\/span>\n      <span class=\"opt-desc\">up to 150 kg\/stremma<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"herbs\">\n      <span class=\"opt-title\">\ud83c\udf3f Aromatic herbs (oregano, thyme)<\/span>\n      <span class=\"opt-desc\">up to 300 kg\/stremma<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"lawn\">\n      <span class=\"opt-title\">\ud83c\udf3f Lawn \u2013 Turf<\/span>\n      <span class=\"opt-desc\">10 or 30 kg per 100 m\u00b2 \u2014 one-off<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"vegetable\">\n      <span class=\"opt-title\">\ud83e\udd6c Vegetable garden<\/span>\n      <span class=\"opt-desc\">0.5 kg\/m\u00b2 (lifetime)<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"ornamentals\">\n      <span class=\"opt-title\">\ud83c\udf39 Ornamentals<\/span>\n      <span class=\"opt-desc\">Pot or garden<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"seedling\">\n      <span class=\"opt-title\">\ud83c\udf31 Seedling production<\/span>\n      <span class=\"opt-desc\">20% by soil weight<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"succulents\">\n      <span class=\"opt-title\">\ud83c\udf35 Cacti \/ Succulents<\/span>\n      <span class=\"opt-desc\">20% by soil weight<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"crop\" value=\"other\">\n      <span class=\"opt-title\">\u2795 Other crop<\/span>\n      <span class=\"opt-desc\">Not listed? Ask us<\/span>\n    <\/label>\n  <\/div>\n<\/div>\n<!-- STEP 2: QUANTITY (dynamic) -->\n<div class=\"step\" data-step=\"2\">\n  <h3><span class=\"step-num\">2<\/span>Quantity<\/h3>\n  <div id=\"zaQtyContainer\">\n    <p style=\"color:var(--za-muted);font-style:italic;\">First choose a crop in Step 1.<\/p>\n  <\/div>\n<\/div>\n<!-- STEP 3: SOIL -->\n<div class=\"step\" data-step=\"3\">\n  <h3><span class=\"step-num\">3<\/span>Soil type<\/h3>\n  <div id=\"zaSoilOptions\">\n    <div class=\"options cols-3\">\n      <label class=\"option\"><input type=\"radio\" name=\"soil\" value=\"light\">\n        <span class=\"opt-title\">\ud83d\udfe1 Light<\/span>\n        <span class=\"opt-desc\">Sandy, loose \u00b7 fine gravel 1\u20132.5 mm<\/span>\n      <\/label>\n      <label class=\"option\"><input type=\"radio\" name=\"soil\" value=\"medium\">\n        <span class=\"opt-title\">\ud83d\udfe0 Medium<\/span>\n        <span class=\"opt-desc\">Loamy, balanced \u00b7 fine gravel 1\u20132.5 mm<\/span>\n      <\/label>\n      <label class=\"option\"><input type=\"radio\" name=\"soil\" value=\"heavy\">\n        <span class=\"opt-title\">\ud83d\udfe4 Heavy<\/span>\n        <span class=\"opt-desc\">Clay, compacted \u00b7 gravel 2.5\u20135 mm<\/span>\n      <\/label>\n    <\/div>\n    <p class=\"sublabel\">\ud83d\udca1 <strong>Not sure?<\/strong> Take a little moist soil in your palm: if it crumbles easily \u2192 light, if it forms a ball \u2192 medium, if it turns into clay \u2192 heavy.<\/p>\n  <\/div>\n  <div class=\"info-box hidden\" id=\"zaSoilNote\">\n    <strong>\u2705 No selection needed \u2014 the grain size is fixed<\/strong>\n    For <strong>lawn \/ turf<\/strong> the soil type <strong>does not change the recommendation<\/strong>. We always recommend <strong>fine gravel 1\u20132.5 mm<\/strong> (or <strong>0.8\u20132.5 mm<\/strong> for IMERYS): fine enough to pass between the grass blades and reach the roots, without creating dust or sitting on the surface like gravel.\n  <\/div>\n<\/div>\n<!-- STEP 4: BRAND -->\n<div class=\"step\" data-step=\"4\">\n  <h3><span class=\"step-num\">4<\/span>Brand preference<\/h3>\n  <div class=\"options\">\n    <label class=\"option\"><input type=\"radio\" name=\"brand\" value=\"greek_thracian\">\n      <span class=\"opt-title\">\ud83c\uddec\ud83c\uddf7 Greek Thracian<\/span>\n      <span class=\"opt-desc\">80% clinoptilolite, locally produced<\/span>\n      <span class=\"opt-info\">The dosage is increased by 20% because of the 80% purity. Grain sizes: 1\u20132.5 mm and 2.5\u20135 mm, in 25 kg bags and in a 500 g pack.<\/span>\n      <a class=\"opt-more\" href=\"https:\/\/shop.zeolife.gr\/en\/product\/greek-zeolite-one-to-2point5mm\/\" data-za-more=\"https:\/\/shop.zeolife.gr\/en\/product\/greek-zeolite-one-to-2point5mm\/\">\u2139\ufe0f More in the eShop \u2192<\/a>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"brand\" value=\"imerys\">\n      <span class=\"opt-title\">\u2b50 IMERYS<\/span>\n      <span class=\"opt-desc\">\u226585% clinoptilolite, established brand<\/span>\n      <span class=\"opt-info\">Grain sizes: 0.8\u20132.5 mm and 2.5\u20135 mm in 25 kg bags, plus a 5 kg pack for small quantities.<\/span>\n      <a class=\"opt-more\" href=\"https:\/\/shop.zeolife.gr\/en\/product\/zeolite-0point8-to-2point5mm\/\" data-za-more=\"https:\/\/shop.zeolife.gr\/en\/product\/zeolite-0point8-to-2point5mm\/\">\u2139\ufe0f More in the eShop \u2192<\/a>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"brand\" value=\"zeocem\">\n      <span class=\"opt-title\">\u26a1 ZeoGravel\u00ae (ZEOCEM)<\/span>\n      <span class=\"opt-desc\">\u226585% clinoptilolite + activation<\/span>\n      <span class=\"opt-info\">Activated by heat treatment. Grain sizes: 1\u20132.5 mm and 2.5\u20135 mm.<\/span>\n      <a class=\"opt-more\" href=\"https:\/\/shop.zeolife.gr\/en\/product\/zeogravel-activated-zeolite-1-to-2-5-millimetres-fine-gravel-ideal-for-agricultural-use-25-kg\/\" data-za-more=\"https:\/\/shop.zeolife.gr\/en\/product\/zeogravel-activated-zeolite-1-to-2-5-millimetres-fine-gravel-ideal-for-agricultural-use-25-kg\/\">\u2139\ufe0f More in the eShop \u2192<\/a>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"brand\" value=\"best_value\">\n      <span class=\"opt-title\">\ud83d\udca1 You choose for me<\/span>\n      <span class=\"opt-desc\">Smart choice based on soil<\/span>\n    <\/label>\n  <\/div>\n<\/div>\n<!-- STEP 5: STRATEGY -->\n<div class=\"step\" data-step=\"5\">\n  <h3><span class=\"step-num\">5<\/span>Application strategy<\/h3>\n  <div class=\"options cols-3\" id=\"zaStrategyOptions\">\n    <label class=\"option\"><input type=\"radio\" name=\"strategy\" value=\"year1\">\n      <span class=\"opt-title\">\ud83d\udfe2 First phase<\/span>\n      <span class=\"opt-desc\">New: planting dose \u00b7 Existing: 40% of total<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"strategy\" value=\"full3\">\n      <span class=\"opt-title\">\ud83d\udcc5 Full programme<\/span>\n      <span class=\"opt-desc\">3 years (existing) or 4 years (new planting)<\/span>\n    <\/label>\n    <label class=\"option\"><input type=\"radio\" name=\"strategy\" value=\"maintenance\">\n      <span class=\"opt-title\">\ud83d\udd04 Maintenance<\/span>\n      <span class=\"opt-desc\">15% of the total dose<\/span>\n    <\/label>\n  <\/div>\n  <div class=\"info-box hidden\" id=\"zaStrategyNote\">\n    <strong>\u2705 One-off application \u2014 no selection needed<\/strong>\n    <strong>Lawn \/ turf<\/strong> is a <strong>perennial crop<\/strong>: zeolite is incorporated <strong>once and only once<\/strong> and keeps working for many years. No multi-year programme or maintenance dose is needed.\n  <\/div>\n<\/div>\n<!-- STEP (conditional): REQUEST FOR ANOTHER CROP \u2014 shown only when \"Other crop\" is selected -->\n<div class=\"step\" id=\"zaOtherStep\" style=\"display:none\">\n  <button type=\"button\" class=\"btn btn-secondary\" id=\"zaOtherBack\" style=\"padding:.5rem 1.1rem;font-size:.9rem;margin-bottom:1rem\">\u2190 Back to the guide<\/button>\n  <h3><span class=\"step-num\">\u2795<\/span>Tell us about your crop<\/h3>\n  <p style=\"margin:.2rem 0 1rem;color:var(--muted)\">Can&#8217;t find your crop in the list? Tell us what it is and our team will recommend the exact zeolite dosage <strong>free of charge<\/strong>.<\/p>\n  <label class=\"qty-label\" for=\"zaOtherCrop\">Which crop?<\/label>\n  <input type=\"text\" id=\"zaOtherCrop\" class=\"qty-input\" placeholder=\"e.g. Pomegranates, Kiwis, Blackberries, Aromatic herbs\u2026\" autocomplete=\"off\">\n  <div class=\"sub-group\">\n    <label class=\"qty-label\" for=\"zaOtherDetails\">Details <span style=\"font-weight:400;color:var(--muted)\">(optional)<\/span><\/label>\n    <textarea id=\"zaOtherDetails\" class=\"qty-input\" rows=\"3\" placeholder=\"e.g. number of plants or area, soil type, new or existing planting\u2026\"><\/textarea>\n  <\/div>\n  <div class=\"wholesale-cta\" style=\"margin-top:1.25rem\">\n    <strong>\ud83d\udce9 Send us your request<\/strong>\n    <span style=\"display:block;color:var(--muted);font-size:.9rem;margin:-.25rem 0 .25rem\">You&#8217;ll receive a personalised dosage recommendation for your crop.<\/span>\n    <div class=\"wholesale-btns four\">\n      <a id=\"zaOtherWhatsapp\" href=\"https:\/\/wa.me\/306985838343\" target=\"_blank\" rel=\"noopener\">\ud83d\udcac WhatsApp<\/a>\n      <a id=\"zaOtherViber\" href=\"viber:\/\/chat?number=306985838343\">\ud83d\udfe3 Viber<\/a>\n      <a id=\"zaOtherEmail\" href=\"mailto:info@zeolife.gr\">\u2709\ufe0f Email<\/a>\n      <a href=\"tel:+302311295520\">\ud83d\udcde +30 2311 29 55 20<\/a>\n    <\/div>\n  <\/div>\n<\/div>\n<div class=\"actions\" style=\"justify-content:center\">\n  <button type=\"button\" class=\"btn\" id=\"zaCalculate\" disabled=\"\">\ud83d\udccb See the dosage<\/button>\n  <button type=\"button\" class=\"btn btn-secondary\" id=\"zaReset\">\ud83d\udd04 Clear<\/button>\n<\/div>\n<!-- RESULT -->\n<div class=\"result\" id=\"zaResult\">\n  <div class=\"print-only\" style=\"text-align:center;margin-bottom:1rem;padding-bottom:1rem;border-bottom:2px solid #2a9ca0;\">\n    <img decoding=\"async\" src=\"https:\/\/zeolife.gr\/wp-content\/uploads\/\/2019\/11\/logo-zeolife-hor.svg\" alt=\"Zeolife.gr\" data-no-lazy=\"1\" class=\"skip-lazy\" style=\"max-width:280px;height:auto;margin:0 auto 0.5rem;display:block;\">\n    <h2 style=\"color:#26231e;margin:0;font-size:1.2rem;\">Zeolite Application Programme for Agriculture<\/h2>\n    <p style=\"margin:0.3rem 0 0;font-size:0.9rem;color:#6b6a64;\">www.zeolife.gr \u00b7 \u260e +30 2311 29 55 20 \u00b7 \u2709 info@zeolife.gr<\/p>\n    <p style=\"margin:0.3rem 0 0;font-size:0.8rem;color:#6b6a64;font-style:italic;\">Calculation date: <span id=\"zaPrintDate\"><\/span><\/p>\n  <\/div>\n  <h3 id=\"zaResultTitle\">Your personalised dosage recommendation<\/h3>\n  <div id=\"zaResultBody\"><\/div>\n<\/div>\n<\/div>\n<!-- ==== ZL YEAR (20\/10\/2026): combined yearly program \u2014 soil (incorporation guide) + spraying (spray guide). Same code in both guides. ==== -->\n<script>\n(function () {\n  if (window.zlYear) { return; }\n  var KEY = 'zlYear_en';\n  var MAX_AGE = 24 * 3600 * 1000;\n  var CART_URL = 'https:\/\/shop.zeolife.gr\/en\/cart\/';\n  var PLAN_API = 'https:\/\/shop.zeolife.gr\/wp-json\/zt\/v1\/spray-plan';\n  var AMP = String.fromCharCode(38);\n  \/\/ Spray crop \u2192 matching soil crops\n  var SPRAY_TO_SOIL = { olive: ['olive'], citrus: ['fruit'], fruit: ['fruit'], nuts: ['walnut', 'pistachio'], vineyard: ['vineyard'] };\n  var MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n  var shownAt = 0;\n\n  function store() { try { return window.sessionStorage; } catch (e) { return null; } }\n  function load() {\n    var st = store();\n    if (!st) return {};\n    var o = null;\n    try { o = JSON.parse(st.getItem(KEY) || 'null'); } catch (e) { o = null; }\n    return o || {};\n  }\n  function save(part, obj) {\n    var st = store();\n    if (!st) return;\n    var o = load();\n    obj.t = Date.now();\n    o[part] = obj;\n    try { st.setItem(KEY, JSON.stringify(o)); } catch (e) {}\n  }\n  function fresh(x) { return x ? (MAX_AGE > Date.now() - (x.t || 0)) : false; }\n  function match(soil, spray) {\n    var list = SPRAY_TO_SOIL[spray.crop] || [];\n    return list.indexOf(soil.crop) !== -1;\n  }\n  function esc(s) { var t = document.createElement('div'); t.textContent = String(s); return t.innerHTML.replace(\/\"\/g, String.fromCharCode(38) + 'quot;'); }\n  function d8(iso) { var m = \/^(\\d{4})-(\\d{2})-(\\d{2})$\/.exec(iso || ''); return m ? new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3])) : new Date(); }\n  function pad(n) { return (n > 9 ? '' : '0') + n; }\n\n  function combine(soil, spray) {\n    var all = [];\n    soil.payload.stages.forEach(function (s, i) {\n      var c = JSON.parse(JSON.stringify(s));\n      c.type = 'soil'; c.key = 'soil_' + s.key; c.name = 'Soil \u00b7 ' + s.name; c.icon = '\ud83c\udf3e'; c.ord = i;\n      all.push(c);\n    });\n    spray.payload.stages.forEach(function (s, i) {\n      var c = JSON.parse(JSON.stringify(s));\n      c.type = 'spray'; c.key = 'spray_' + s.key; c.name = 'Spraying \u00b7 ' + s.name; c.ord = 10 + i;\n      all.push(c);\n    });\n    all.sort(function (a, b) { if (a.date === b.date) { return a.ord - b.ord; } return a.date > b.date ? 1 : -1; });\n    all = all.slice(0, 8);\n    all.forEach(function (c) { delete c.ord; });\n    return all;\n  }\n  function mergeItems(lists) {\n    var q = {}, order = [];\n    lists.forEach(function (l) {\n      String(l || '').split(',').forEach(function (p) {\n        var m = \/^(\\d+):(\\d+)$\/.exec(p);\n        if (!m) return;\n        if (!q[m[1]]) { q[m[1]] = 0; order.push(m[1]); }\n        q[m[1]] += Number(m[2]);\n      });\n    });\n    var out = [], units = 0;\n    order.forEach(function (id) { out.push(id + ':' + q[id]); units += q[id]; });\n    return { items: out.join(','), units: units };\n  }\n  function detail(s) {\n    var parts = (s.rows || []).map(function (r) { return s.type === 'soil' ? r[4] : (r[1] + ' ' + r[4]); });\n    return parts.join(' + ');\n  }\n\n  function payload(soil, spray) {\n    var y1 = soil.payload.stages[0] || null;\n    var cart = mergeItems([y1 ? y1.items : '', spray.payload.year]);\n    var yearl = [];\n    if (y1) { yearl.push('Soil \u00b7 ' + y1.name + ': ' + (y1.rows[0] ? y1.rows[0][1] + ' \u2014 ' + y1.rows[0][4] : '')); }\n    (spray.payload.yearl || []).forEach(function (l) { yearl.push(l); });\n    return {\n      kind: 'combo', title: soil.name, crop: soil.crop, icon: soil.icon, qty: soil.qty,\n      water: spray.payload.water, tank: spray.payload.tank, guide: spray.payload.guide,\n      year: cart.items, yearl: yearl, stages: combine(soil, spray)\n    };\n  }\n\n  function icsEsc(s) { return String(s).replace(\/\\\\\/g, '\\\\\\\\').replace(\/,\/g, '\\\\,').replace(\/;\/g, '\\\\;').replace(\/\\n\/g, '\\\\n'); }\n  function icsDate(d) { return d.getFullYear() + pad(d.getMonth() + 1) + pad(d.getDate()); }\n  function ics(p) {\n    var lines = ['BEGIN:VCALENDAR', 'VERSION:2.0', 'PRODID:-\/\/Zeolife\/\/Year Program\/\/EL', 'CALSCALE:GREGORIAN'];\n    var stamp = new Date();\n    p.stages.forEach(function (s, i) {\n      var d = d8(s.date);\n      var end = new Date(d.getFullYear(), d.getMonth(), d.getDate() + 1);\n      lines.push('BEGIN:VEVENT');\n      lines.push('UID:zeolife-year-' + p.crop + '-' + i + '-' + icsDate(d) + '@zeolife.gr');\n      lines.push('DTSTAMP:' + icsDate(stamp) + 'T000000Z');\n      lines.push('DTSTART;VALUE=DATE:' + icsDate(d));\n      lines.push('DTEND;VALUE=DATE:' + icsDate(end));\n      lines.push('SUMMARY:' + icsEsc((s.type === 'soil' ? '\ud83c\udf3e ' : '\ud83d\udca8 ') + s.name + ' (' + p.title + ')'));\n      lines.push('DESCRIPTION:' + icsEsc(detail(s) + (s.tip ? '\\n' + s.tip : '')));\n      lines.push('BEGIN:VALARM');\n      lines.push('ACTION:DISPLAY');\n      lines.push('DESCRIPTION:' + icsEsc(s.name));\n      lines.push('TRIGGER:-P' + (s.type === 'soil' ? '7' : '2') + 'D');\n      lines.push('END:VALARM');\n      lines.push('END:VEVENT');\n    });\n    lines.push('END:VCALENDAR');\n    var blob = new Blob([lines.join('\\r\\n')], { type: 'text\/calendar;charset=utf-8' });\n    var a = document.createElement('a');\n    a.href = URL.createObjectURL(blob);\n    a.download = 'zeolife-etisio-programma.ics';\n    document.body.appendChild(a);\n    a.click();\n    setTimeout(function () { URL.revokeObjectURL(a.href); a.parentNode.removeChild(a); }, 1000);\n  }\n\n  function render(before, part) {\n    var old = document.getElementById('zlYearBox');\n    if (old) { old.parentNode.removeChild(old); }\n    if (!before) return;\n    var o = load();\n    var soil = fresh(o.soil) ? o.soil : null;\n    var spray = fresh(o.spray) ? o.spray : null;\n    if (!soil) return;\n    if (!spray) return;\n    if (!match(soil, spray)) return;\n    var p = payload(soil, spray);\n    var cart = mergeItems([p.year]);\n    var back = window.location.origin + window.location.pathname;\n    var h = '<div class=\"zl-keep\" id=\"zlYearBox\"><h4>\ud83d\udcc5 Your program for the year \u2014 soil + spraying<\/h4>';\n    h += '<p class=\"zl-keep-sub\">We combined ' + (part === 'soil' ? 'this dosage with the spray program' : 'this spray program with the soil dosage') + ' you created for <strong>' + esc(soil.name) + ' \u00b7 ' + esc(soil.qty) + '<\/strong>.<\/p>';\n    h += '<div style=\"margin:0 0 1rem\">';\n    p.stages.forEach(function (s) {\n      var d = d8(s.date);\n      h += '<div style=\"display:grid;grid-template-columns:6.5rem minmax(0,1fr);gap:.7rem;padding:.5rem 0;border-bottom:1px solid var(--line)\">';\n      h += '<strong>' + MONTHS[d.getMonth()] + ' ' + d.getFullYear() + '<\/strong>';\n      h += '<span><strong>' + (s.type === 'soil' ? '\ud83c\udf3e ' : esc(s.icon) + ' ') + esc(s.name) + '<\/strong><br><span style=\"font-size:.88rem;color:var(--muted)\">' + esc(detail(s)) + '<\/span><\/span><\/div>';\n    });\n    h += '<\/div>';\n    \/\/ Cart: same button as every \"Add to cart\" in the guides (zl-cartbox + cta-btn).\n    h += '<div class=\"zl-cartbox\"><p>Everything you need for <strong>year 1<\/strong> (soil year 1 + the spray products) goes into the <strong>shop.zeolife.gr<\/strong> cart in the right quantities. There you see final prices and discounts.<\/p>';\n    h += '<a class=\"cta-btn\" id=\"zlYearCart\" href=\"' + (cart.units ? CART_URL + '?zl_cart=' + cart.items + AMP + 'zl_back=' + encodeURIComponent(back) + AMP + 'zl_lang=en' : CART_URL) + '\"><span>\ud83d\uded2 Add to cart (' + cart.units + ') \u2192<\/span><\/a><\/div>';\n    h += '<div class=\"zl-tiles\" style=\"grid-template-columns:repeat(auto-fit,minmax(220px,1fr))\">';\n    h += '<button type=\"button\" class=\"zl-tile\" id=\"zlYearMailT\"><b>\u2709\ufe0f One email for everything<\/b><span>With a reminder before each task<\/span><\/button>';\n    h += '<button type=\"button\" class=\"zl-tile\" id=\"zlYearIcs\"><b>\ud83d\udcc5 The whole program<\/b><span>.ics file for your calendar<\/span><\/button>';\n    h += '<\/div>';\n    h += '<form class=\"zl-mail\" id=\"zlYearMail\" novalidate style=\"display:none\">';\n    h += '<label class=\"qty-label\" for=\"zlYearEmail\">Your email<\/label>';\n    h += '<input type=\"email\" id=\"zlYearEmail\" class=\"qty-input\" placeholder=\"e.g. john@gmail.com\" autocomplete=\"email\" required>';\n    h += '<input type=\"text\" name=\"website\" id=\"zlYearHp\" class=\"zl-hp\" tabindex=\"-1\" autocomplete=\"off\" aria-hidden=\"true\">';\n    h += '<div class=\"zl-rem-lead\" style=\"margin:.6rem 0\">Send me a reminder <select id=\"zlYearLead\"><option value=\"3\">3 days<\/option><option value=\"5\">5 days<\/option><option value=\"7\" selected>7 days<\/option><option value=\"14\">14 days<\/option><\/select> before each task.<\/div>';\n    h += '<label class=\"zl-chk\"><input type=\"checkbox\" id=\"zlYearNews\"><span>I would also like the weekly Zeolife newsletter (tips, offers).<\/span><\/label>';\n    h += '<label class=\"zl-chk\"><input type=\"checkbox\" id=\"zlYearConsent\"><span>I agree that my email is used only to send the program and the reminders. <a href=\"https:\/\/shop.zeolife.gr\/en\/privacy-policy\/\" target=\"_blank\" rel=\"noopener\">Privacy policy<\/a><\/span><\/label>';\n    h += '<div class=\"zl-mail-row\"><button type=\"submit\" class=\"btn\" id=\"zlYearSend\">\u2709\ufe0f Send me the yearly program<\/button><\/div>';\n    h += '<p class=\"zl-status\" id=\"zlYearStatus\" role=\"status\" aria-live=\"polite\"><\/p>';\n    h += '<\/form><\/div>';\n    var box = document.createElement('div');\n    box.innerHTML = h;\n    var el = box.firstChild;\n    before.parentNode.insertBefore(el, before);\n    shownAt = Date.now();\n\n    document.getElementById('zlYearIcs').addEventListener('click', function () { ics(payload(load().soil, load().spray)); });\n    document.getElementById('zlYearMailT').addEventListener('click', function () {\n      var f = document.getElementById('zlYearMail');\n      var on = f.style.display === 'none';\n      f.style.display = on ? '' : 'none';\n      this.classList.toggle('on', on);\n    });\n    document.getElementById('zlYearMail').addEventListener('submit', function (e) {\n      e.preventDefault();\n      var st = document.getElementById('zlYearStatus');\n      var em = document.getElementById('zlYearEmail');\n      var email = (em.value || '').trim();\n      function say(m, k) { st.textContent = m; st.className = 'zl-status' + (k ? ' is-' + k : ''); }\n      if (!\/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\/.test(email)) { say('Please enter a valid email.', 'err'); em.focus(); return; }\n      if (!document.getElementById('zlYearConsent').checked) { say('Please tick the consent box so we can send you the program.', 'err'); return; }\n      var btn = document.getElementById('zlYearSend');\n      btn.disabled = true;\n      say('Sending\u2026', '');\n      var body = new URLSearchParams();\n      body.append('kind', 'combo');\n      body.append('email', email);\n      body.append('lang', 'en');\n      body.append('consent', '1');\n      body.append('remind', '1');\n      body.append('lead', document.getElementById('zlYearLead').value);\n      body.append('newsletter', document.getElementById('zlYearNews').checked ? '1' : '');\n      body.append('website', document.getElementById('zlYearHp').value);\n      body.append('tm', String(Date.now() - shownAt));\n      body.append('plan', JSON.stringify(payload(load().soil, load().spray)));\n      fetch(PLAN_API, { method: 'POST', body: body })\n        .then(function (r) { return r.json().catch(function () { return { ok: false, message: '' }; }); })\n        .then(function (j) { btn.disabled = false; if (j.ok) { say(j.message || 'Sent!', 'ok'); } else { say(j.message || 'Something went wrong. Please try again or call us on +30 2311 29 55 20.', 'err'); } })\n        .catch(function () { btn.disabled = false; say('Could not connect. Please try again shortly.', 'err'); });\n    });\n  }\n\n  window.zlYear = { save: save, render: render, load: load };\n})();\n<\/script>\n\n<script>\n(function(){\n  \/\/ ===== DATA =====\n  var cropData = {\n    olive: {\n      name: 'Olive trees',\n      icon: '\ud83e\uded2',\n      mode: 'tree',\n      phases: {\n        'new': { label: '\ud83c\udf31 New planting', kg: 2, method: 'Mixed with the soil in the planting hole' },\n        existing: { label: '\ud83c\udf33 Existing planting', kg: 24, method: 'From the trunk out to the edge of the canopy' }\n      },\n      perStremmaMax: 600,\n      season: 'Autumn (Oct-Nov) or early spring before bud break',\n      depth: 'From the trunk out to the edge of the canopy \u00b7 Mix in where possible down to 20 cm (new planting: mix with the soil of the planting hole)'\n    },\n    walnut: {\n      name: 'Walnut trees',\n      icon: '\ud83e\udd5c',\n      mode: 'tree',\n      phases: {\n        'new': { label: '\ud83c\udf31 New planting', kg: 2, method: 'Mixed with the soil in the planting hole' },\n        existing: { label: '\ud83c\udf33 Existing planting', kg: 24, method: 'From the trunk out to the edge of the canopy' }\n      },\n      perStremmaMax: 600,\n      season: 'Autumn (Oct-Nov)',\n      depth: 'From the trunk out to the edge of the canopy \u00b7 Mix in where possible down to 20 cm (new planting: mix with the soil of the planting hole)'\n    },\n    fruit: {\n      name: 'Fruit trees',\n      icon: '\ud83c\udf4e',\n      mode: 'tree',\n      phases: {\n        'new': { label: '\ud83c\udf31 New planting', kg: 1, method: 'Mixed with the soil in the planting hole' },\n        existing: { label: '\ud83c\udf33 Existing planting', kg: 15, method: 'From the trunk out to the edge of the canopy' }\n      },\n      perStremmaMax: 450,\n      season: 'Autumn or before flowering',\n      depth: 'From the trunk out to the edge of the canopy \u00b7 Mix in where possible down to 20 cm (new planting: mix with the soil of the planting hole)'\n    },\n    pistachio: {\n      name: 'Pistachio trees',\n      icon: '\ud83c\udf30',\n      mode: 'tree',\n      phases: {\n        'new': { label: '\ud83c\udf31 New planting', kg: 1, method: 'Mixed with the soil in the planting hole' },\n        existing: { label: '\ud83c\udf33 Existing planting', kg: 15, method: 'From the trunk out to the edge of the canopy' }\n      },\n      perStremmaMax: 450,\n      season: 'Autumn or before flowering',\n      depth: 'From the trunk out to the edge of the canopy \u00b7 Mix in where possible down to 20 cm (new planting: mix with the soil of the planting hole)'\n    },\n    vineyard: {\n      name: 'Vineyard',\n      icon: '\ud83c\udf47',\n      mode: 'vine',\n      phases: {\n        'new': { label: '\ud83c\udf31 New planting', kg: 0.2, method: 'Mixed with the soil in the planting hole (200 g\/vine)' },\n        existing: { label: '\ud83c\udf47 Existing planting', kg: 1.2, method: 'Around the root, mixed with the soil' }\n      },\n      perStremmaMax: 450,\n      season: 'Autumn after the harvest',\n      depth: 'Around the root \u00b7 Mix in where possible down to 20 cm (new planting: mix with the soil of the planting hole)'\n    },\n    palm: {\n      name: 'Palm trees',\n      icon: '\ud83c\udf34',\n      mode: 'tree',\n      phases: {\n        'new': { label: '\ud83c\udf31 New planting', kg: 2, method: 'Mixed with the soil in the planting hole' },\n        existing: { label: '\ud83c\udf33 Existing planting', kg: 24, method: 'From the trunk out to the edge of the canopy' }\n      },\n      perStremmaMax: 0,\n      season: 'Spring',\n      depth: 'From the trunk out to the edge of the canopy \u00b7 Mix in where possible down to 20 cm (new planting: mix with the soil of the planting hole)'\n    },\n    cereals: {\n      name: 'Cereals \/ Maize',\n      icon: '\ud83c\udf3e',\n      mode: 'stremma',\n      perStremmaMax: 300,\n      season: 'Before sowing (autumn for winter crops, spring for spring crops)',\n      depth: '15-20 cm incorporation by ploughing'\n    },\n    melons: {\n      name: 'Watermelons \/ Melons',\n      icon: '\ud83c\udf49',\n      mode: 'stremma',\n      perStremmaMax: 450,\n      season: 'Before transplanting or sowing (late winter \u2013 spring)',\n      depth: '15-20 cm incorporation by ploughing or rotavating, ideally along the planting rows'\n    },\n    alfalfa: {\n      name: 'Alfalfa (lucerne)',\n      icon: '\ud83c\udf40',\n      mode: 'stremma',\n      perStremmaMax: 150,\n      season: 'Before establishing the alfalfa (autumn or spring sowing)',\n      depth: '15-20 cm incorporation by ploughing before sowing'\n    },\n    herbs: {\n      name: 'Aromatic herbs (oregano, thyme)',\n      icon: '\ud83c\udf3f',\n      mode: 'stremma',\n      \/\/ 300 kg\/stremma in total, based on Bulgarian-quality zeolite (IMERYS, \u226585%).\n      \/\/ Greek Thracian (80%) automatically gets +20% via doseModifier.\n      perStremmaMax: 300,\n      season: 'Before planting (autumn or early spring)',\n      depth: '15-20 cm incorporation by ploughing or rotavating, ideally along the planting rows'\n    },\n    lawn: {\n      name: 'Lawn \u2013 Turf',\n      icon: '\ud83c\udf3f',\n      mode: 'lawn',\n      \/\/ PERENNIAL CROP \u2014 a single application, no multi-year\/maintenance programme.\n      \/\/ Input is in m\u00b2 (friendlier for gardens\/yards). 1 stremma = 1,000 m\u00b2.\n      oneOff: true,\n      \/\/ Soil type does NOT affect lawns: always fine gravel 1-2.5mm (IMERYS: 0.8-2.5mm).\n      ignoreSoil: true,\n      fixedGran: 'fine',\n      smartBrand: 'imerys',\n      smartBrandLabel: 'lawns',\n      smartBrandReason: 'For lawns we recommend IMERYS 0.8-2.5 mm: the finest version of \"fine gravel\" \u2014 it passes easily between the grass blades when top-dressing and quickly reaches the roots.',\n      existingKg: 100,          \/\/ kg per stremma (existing lawn)\n      newKg: 300,               \/\/ kg per stremma (new planting)\n      existingKgPerSqm: 0.1,    \/\/ 100 kg\/stremma \u00f7 1,000 m\u00b2\n      newKgPerSqm: 0.3,         \/\/ 300 kg\/stremma \u00f7 1,000 m\u00b2\n      season: 'Spring or autumn \u2014 one-off application, just once',\n      depth: 'Existing lawn: on the surface as top-dressing (0.1 kg\/m\u00b2 = 10 kg per 100 m\u00b2), water well afterwards \u00b7 New planting: incorporate into the top 10-15 cm before sowing or laying turf (0.3 kg\/m\u00b2 = 30 kg per 100 m\u00b2)'\n    },\n    vegetable: {\n      name: 'Vegetable garden',\n      icon: '\ud83e\udd6c',\n      mode: 'area',\n      perSqmKg: 0.5,\n      season: 'Before planting\/sowing (autumn or early spring) \u2014 a one-off application that lasts a lifetime',\n      depth: 'Incorporate into the top 15-20 cm of soil by hoeing or rotavating \u00b7 one-off application (no need to repeat every year)'\n    },\n    ornamentals: {\n      name: 'Ornamental plants',\n      icon: '\ud83c\udf39',\n      mode: 'ornamental',\n      potPercent: 10,\n      potPercentMin: 5,\n      potPercentMax: 20,\n      gardenPerPlant: 60,\n      gardenPerPlantMin: 30,\n      gardenPerPlantMax: 120,\n      season: 'At planting or when renewing the soil',\n      depth: 'Mix thoroughly (pot) or 5-10 cm (garden)'\n    },\n    seedling: {\n      name: 'Seedling production',\n      icon: '\ud83c\udf31',\n      mode: 'soil_weight',\n      percent: 20,\n      season: 'Mix thoroughly before sowing',\n      depth: 'Mix evenly through the whole substrate'\n    },\n    succulents: {\n      name: 'Cacti \/ Succulents',\n      icon: '\ud83c\udf35',\n      mode: 'soil_weight',\n      percent: 20,\n      season: 'At planting or repotting',\n      depth: 'Mix thoroughly with soil + river sand'\n    }\n  };\n  var products = {\n    greek_thracian: {\n      label: 'Greek Thracian Zeolite',\n      purity: '80%',\n      doseModifier: 1.2,\n      powder: { name: 'Greek Thracian Zeolite 0-1mm (Powder)', url: 'https:\/\/shop.zeolife.gr\/en\/product\/greek-zeolite-zero-to-one-mm\/' },\n      fine: { name: 'Greek Thracian Zeolite 1-2.5mm (Fine gravel)', url: 'https:\/\/shop.zeolife.gr\/en\/product\/greek-zeolite-one-to-2point5mm\/' },\n      gravel: { name: 'Greek Thracian Zeolite 2.5-5mm (Gravel)', url: 'https:\/\/shop.zeolife.gr\/en\/product\/greek-zeolite-2point5-to-5mm\/' }\n    },\n    imerys: {\n      label: 'IMERYS Zeolite',\n      purity: '\u226585%',\n      doseModifier: 1.0,\n      powder: { name: 'IMERYS Zeolite up to 0.8mm (Powder)', url: 'https:\/\/shop.zeolife.gr\/en\/product\/zeolite-0point8mm\/' },\n      fine: { name: 'IMERYS Zeolite 0.8-2.5mm (Fine gravel)', url: 'https:\/\/shop.zeolife.gr\/en\/product\/zeolite-0point8-to-2point5mm\/' },\n      gravel: { name: 'IMERYS Zeolite 2.5-5mm (Gravel)', url: 'https:\/\/shop.zeolife.gr\/en\/product\/zeolite-2point5-to-5mm\/' }\n    },\n    zeocem: {\n      label: 'ZeoGravel\u00ae Activated ZEOCEM',\n      purity: '\u226585% + activation',\n      doseModifier: 1.0,\n      powder: null,\n      fine: { name: 'ZeoGravel\u00ae Activated ZEOCEM 1-2.5mm (Fine gravel)', url: 'https:\/\/shop.zeolife.gr\/en\/product\/zeogravel-activated-zeolite-1-to-2-5-millimetres-fine-gravel-ideal-for-agricultural-use-25-kg\/' },\n      gravel: { name: 'ZeoGravel\u00ae Activated ZEOCEM 2.5-5mm (Gravel)', url: 'https:\/\/shop.zeolife.gr\/en\/product\/zeogravel-activated-zeolite-2-5-to-5-millimetres-gravel-ideal-for-planting-young-trees-25-kilograms\/' }\n    }\n  };\n  \/\/ === IMERYS 5kg: variable product (all grain sizes on one product page) ===\n  \/\/ Recommended when the total dose is small (< 25 kg) \u2014 same grain-size logic per soil.\n  var imerys5kg = {\n    url: 'https:\/\/shop.zeolife.gr\/en\/product\/zeolite-for-domestic-use-5-kg\/',\n    powder: 'IMERYS Zeolite 5 kg \u2014 Powder (up to 0.8mm)',\n    fine: 'IMERYS Zeolite 5 kg \u2014 Fine gravel (0.8-2.5mm)',\n    gravel: 'IMERYS Zeolite 5 kg \u2014 Gravel (2.5-5mm)'\n  };\n  \/\/ 500g Greek Thracian \u2014 for VERY small\/trial applications (no 500g powder exists).\n  var greek500 = {\n    fine:   { name: 'Greek Thracian Zeolite 1-2.5mm (Fine gravel) \u2014 500g', url: 'https:\/\/shop.zeolife.gr\/en\/product\/greek-zeolite-1-to-2-5-millimetres-fine-gravel-ideal-for-use-in-small-scale-cultivation-and-in-medium-to-heavy-soils-500-grams\/' },\n    gravel: { name: 'Greek Thracian Zeolite 2.5-5mm (Gravel) \u2014 500g', url: 'https:\/\/shop.zeolife.gr\/en\/product\/greek-zeolite-2-5-to-5-millimetres-gravel-ideal-for-use-in-large-scale-cultivation-500-grams\/' }\n  };\n  \/\/ 20\/10\/2026 (proposal A): product IDs of the ENGLISH eShop products for \"Add to cart\" (zl_cart=ID:quantity). No German shop: DE uses the English one.\n  \/\/ 5 kg IMERYS: variations of the variable product 41447 per grain size.\n  var CART_URL = 'https:\/\/shop.zeolife.gr\/en\/cart\/';\n  var cartIds = {\n    bag25: {\n      greek_thracian: { powder: 31732, fine: 31733, gravel: 31734 },\n      imerys: { powder: 33663, fine: 33662, gravel: 33659 },\n      zeocem: { fine: 41840, gravel: 41841 }\n    },\n    kg5: { powder: 41454, fine: 41456, gravel: 41457 },\n    g500: { fine: 41773, gravel: 41783 }\n  };\n  function zaCartId(brandKey, gran, tier) {\n    if (tier === 'kg5') { return cartIds.kg5[gran] || 0; }\n    if (tier === 'g500') { return cartIds.g500[gran] || 0; }\n    var b = cartIds.bag25[brandKey];\n    return b ? (b[gran] || 0) : 0;\n  }\n  function zaDiscPct(sacks) {\n    if (sacks >= 40) return 40;\n    if (sacks >= 30) return 30;\n    if (sacks >= 20) return 20;\n    if (sacks >= 10) return 10;\n    return 0;\n  }\n  var AMPC = String.fromCharCode(38);\n  var zaCart = null;\n  var zaLast = null;\n  var TEST_QTY_KG = 1.5; \/\/ below 1.5 kg (trial) \u2192 recommend 500g (if that grain size exists)\n  var SMALL_QTY_KG = 25; \/\/ below 25 kg (1 bag) \u2192 recommend 5 kg\n  \/\/ 04\/10\/2026: NEVER powder for soil\/tree incorporation \u2014 light & medium soil \u2192 fine gravel (1-2.5 mm \/ IMERYS 0.8-2.5 mm), heavy \u2192 gravel 2.5-5 mm.\n  var soilToGran = { light: 'fine', medium: 'fine', heavy: 'gravel' };\n  var soilLabels = { light: 'Light (sandy)', medium: 'Medium (loamy)', heavy: 'Heavy (clay)' };\n  var granLabels = { powder: 'Powder', fine: 'Fine gravel', gravel: 'Gravel' };\n  var smartByS = { light: 'imerys', medium: 'zeocem', heavy: 'greek_thracian' };\n  var smartReason = {\n    light: 'IMERYS 0.8-2.5 mm is the finest \u201cfine gravel\u201d \u2014 ideal for light, sandy soils: it settles at the root zone without being washed or blown away, as powder would.',\n    medium: 'ZeoGravel\u00ae (ZEOCEM) is thermally activated \u2014 increased activity for medium soils.',\n    heavy: 'Greek Thracian Zeolite is locally produced (low carbon footprint) and ideal for heavy soils.'\n  };\n  \/\/ ===== ELEMENTS =====\n  var calc = document.getElementById('zaCalc');\n  var steps = calc.querySelectorAll('.step:not(#zaOtherStep)');\n  var otherStep = document.getElementById('zaOtherStep');\n  var actionsRow = calc.querySelector('.actions');\n  var progressBar = document.getElementById('zaProgress');\n  var calcBtn = document.getElementById('zaCalculate');\n  var resetBtn = document.getElementById('zaReset');\n  var resultBox = document.getElementById('zaResult');\n  var resultBody = document.getElementById('zaResultBody');\n  var qtyContainer = document.getElementById('zaQtyContainer');\n  var strategyOptions = document.getElementById('zaStrategyOptions');\n  var strategyNote = document.getElementById('zaStrategyNote');\n  var soilOptions = document.getElementById('zaSoilOptions');\n  var soilNote = document.getElementById('zaSoilNote');\n  \/\/ ===== HELPERS =====\n  function getChecked(name) {\n    var el = calc.querySelector('input[name=\"' + name + '\"]:checked');\n    return el ? el.value : null;\n  }\n  function getVal(id) {\n    var el = document.getElementById(id);\n    return el ? el.value : null;\n  }\n  function fmtKg(n) {\n    if (n >= 1000) return (n \/ 1000).toFixed(1).replace('.0','') + ' tonnes (' + Math.round(n).toLocaleString('en-GB') + ' kg)';\n    return Math.round(n).toLocaleString('en-GB') + ' kg';\n  }\n  function fmtNum(n) { return Math.round(n).toLocaleString('en-GB'); }\n  \/\/ Perennial crops with a SINGLE application (e.g. lawn \/ turf)\n  function isOneOff(crop) {\n    if (!crop) return false;\n    if (!cropData[crop]) return false;\n    return cropData[crop].oneOff === true;\n  }\n  \/\/ Crops where soil type does not affect grain size (e.g. lawn \/ turf)\n  function ignoresSoil(crop) {\n    if (!crop) return false;\n    if (!cropData[crop]) return false;\n    return cropData[crop].ignoreSoil === true;\n  }\n  \/\/ ===== \"OTHER CROP\" \u2014 REQUEST MODE =====\n  function updateOtherLinks() {\n    var cropEl = document.getElementById('zaOtherCrop');\n    var detEl = document.getElementById('zaOtherDetails');\n    var cropName = cropEl ? cropEl.value.trim() : '';\n    var details = detEl ? detEl.value.trim() : '';\n    var msg = 'Hello! I would like a personalised zeolite dosage recommendation for the crop: ' + (cropName || '[enter crop]');\n    if (details) { msg += '. Additional details: ' + details; }\n    var wa = document.getElementById('zaOtherWhatsapp');\n    var em = document.getElementById('zaOtherEmail');\n    if (wa) { wa.href = 'https:\/\/wa.me\/306985838343?text=' + encodeURIComponent(msg); }\n    if (em) { em.href = 'mailto:info@zeolife.gr?subject=' + encodeURIComponent('Zeolite dosage request' + (cropName ? (' \u2013 ' + cropName) : '')) + '&body=' + encodeURIComponent(msg); }\n  }\n  function enterOtherMode() {\n    for (var i = 0; i < steps.length; i++) { steps[i].style.display = 'none'; steps[i].classList.remove('active'); }\n    if (actionsRow) { actionsRow.style.display = 'none'; }\n    resultBox.classList.remove('show');\n    if (otherStep) {\n      otherStep.style.display = '';\n      otherStep.classList.add('active');\n      otherStep.scrollIntoView({ behavior: 'smooth', block: 'start' });\n    }\n    progressBar.style.width = '100%';\n    updateOtherLinks();\n  }\n  function exitOtherMode() {\n    for (var i = 0; i < steps.length; i++) { steps[i].style.display = ''; }\n    if (actionsRow) { actionsRow.style.display = ''; }\n    if (otherStep) { otherStep.style.display = 'none'; otherStep.classList.remove('active'); }\n  }\n  \/\/ ===== STEP 5: hide the options when the crop is one-off =====\n  function updateStrategyStep(crop) {\n    if (!strategyOptions) return;\n    if (!strategyNote) return;\n    if (isOneOff(crop)) {\n      strategyOptions.classList.add('hidden');\n      strategyNote.classList.remove('hidden');\n      calc.querySelectorAll('input[name=\"strategy\"]').forEach(function(r) { r.checked = false; });\n    } else {\n      strategyOptions.classList.remove('hidden');\n      strategyNote.classList.add('hidden');\n    }\n  }\n  \/\/ ===== STEP 3: hide the soil options when they don't affect the recommendation =====\n  function updateSoilStep(crop) {\n    if (!soilOptions) return;\n    if (!soilNote) return;\n    if (ignoresSoil(crop)) {\n      soilOptions.classList.add('hidden');\n      soilNote.classList.remove('hidden');\n      calc.querySelectorAll('input[name=\"soil\"]').forEach(function(r) { r.checked = false; });\n    } else {\n      soilOptions.classList.remove('hidden');\n      soilNote.classList.add('hidden');\n    }\n  }\n  \/\/ ===== STEP 2 RENDER =====\n  function renderQtyStep(crop) {\n    if (!crop || !cropData[crop]) {\n      qtyContainer.innerHTML = '<p style=\"color:var(--za-muted);font-style:italic;\">First choose a crop in Step 1.<\/p>';\n      return;\n    }\n    var data = cropData[crop];\n    var html = '';\n    if (data.mode === 'tree' || data.mode === 'vine') {\n      var unit = data.mode === 'tree' ? 'trees' : 'vines';\n      var unitSingular = data.mode === 'tree' ? 'tree' : 'vine';\n      var hasStremma = data.perStremmaMax > 0;\n      if (hasStremma) {\n        html += '<div class=\"qty-row\">';\n        html += '<div><label class=\"qty-label\">How many ' + unit + '?<\/label>';\n        html += '<input type=\"number\" id=\"zaQty\" class=\"qty-input\" min=\"1\" placeholder=\"e.g. 100\"><\/div>';\n        html += '<div><label class=\"qty-label\">Or how many stremmata? (1 stremma = 1,000 m\u00b2 \u00b7 existing planting only)<\/label>';\n        html += '<input type=\"number\" id=\"zaQtyStremma\" class=\"qty-input\" min=\"0\" step=\"0.1\" placeholder=\"e.g. 5\"><\/div>';\n        html += '<\/div>';\n      } else {\n        html += '<label class=\"qty-label\">How many ' + unit + '?<\/label>';\n        html += '<input type=\"number\" id=\"zaQty\" class=\"qty-input\" min=\"1\" placeholder=\"e.g. 20\">';\n      }\n      html += '<div class=\"sub-group\"><label class=\"qty-label\">Planting phase<\/label>';\n      html += '<div class=\"options\">';\n      var phases = data.phases;\n      for (var key in phases) {\n        html += '<label class=\"option\"><input type=\"radio\" name=\"phaseGroup\" value=\"' + key + '\">';\n        html += '<span class=\"opt-title\">' + phases[key].label + '<\/span>';\n        html += '<span class=\"opt-desc\">' + phases[key].kg + ' kg\/' + unitSingular + ' \u00b7 ' + phases[key].method + '<\/span>';\n        html += '<\/label>';\n      }\n      html += '<\/div><\/div>';\n    } else if (data.mode === 'stremma') {\n      html += '<label class=\"qty-label\">How many stremmata? (1 stremma = 1,000 m\u00b2)<\/label>';\n      html += '<input type=\"number\" id=\"zaQty\" class=\"qty-input\" min=\"0\" step=\"0.1\" placeholder=\"e.g. 10\">';\n      html += '<p class=\"sublabel\">Dosage: up to ' + data.perStremmaMax + ' kg\/stremma<\/p>';\n    } else if (data.mode === 'area') {\n      html += '<label class=\"qty-label\">How many square metres (m\u00b2)?<\/label>';\n      html += '<input type=\"number\" id=\"zaQty\" class=\"qty-input\" min=\"0\" step=\"0.1\" placeholder=\"e.g. 20\">';\n      html += '<p class=\"sublabel\">Dosage: ' + data.perSqmKg + ' kg\/m\u00b2 (' + Math.round(data.perSqmKg * 1000) + ' g\/m\u00b2) \u2014 one-off application that lasts a lifetime<\/p>';\n    } else if (data.mode === 'lawn') {\n      html += '<div class=\"qty-row\">';\n      html += '<div><label class=\"qty-label\">How many square metres (m\u00b2)?<\/label>';\n      html += '<input type=\"number\" id=\"zaQty\" class=\"qty-input\" min=\"0\" step=\"1\" placeholder=\"e.g. 100\">';\n      html += '<p class=\"sublabel\">Measure <strong>length \u00d7 width<\/strong> \u2014 e.g. 10 m \u00d7 10 m = <strong>100 m\u00b2<\/strong><\/p><\/div>';\n      html += '<div><label class=\"qty-label\">Lawn type<\/label>';\n      html += '<div class=\"options\">';\n      html += '<label class=\"option\"><input type=\"radio\" name=\"lawnType\" value=\"existing\">';\n      html += '<span class=\"opt-title\">\ud83c\udf3f Existing lawn<\/span><span class=\"opt-desc\">0.1 kg\/m\u00b2 \u00b7 10 kg per 100 m\u00b2 \u2014 one-off<\/span><\/label>';\n      html += '<label class=\"option\"><input type=\"radio\" name=\"lawnType\" value=\"new\">';\n      html += '<span class=\"opt-title\">\ud83c\udf31 New planting<\/span><span class=\"opt-desc\">0.3 kg\/m\u00b2 \u00b7 30 kg per 100 m\u00b2 \u2014 one-off<\/span><\/label>';\n      html += '<\/div><\/div><\/div>';\n      \/\/ Example table \u2014 helps the customer translate dimensions into m\u00b2.\n      html += '<div class=\"info-box\" style=\"margin-top:1rem\">';\n      html += '<strong>\ud83d\udcd0 How many m\u00b2 is your area? \u2014 examples<\/strong>';\n      html += '<table class=\"dose-table\" style=\"font-size:0.9rem;margin:0.5rem 0 0;\">';\n      html += '<tr><th>Dimensions<\/th><th>Area<\/th><th>\ud83c\udf3f Existing<\/th><th>\ud83c\udf31 New planting<\/th><\/tr>';\n      html += '<tr><td>5 \u00d7 10 m<\/td><td>50 m\u00b2<\/td><td>5 kg<\/td><td>15 kg<\/td><\/tr>';\n      html += '<tr><td>10 \u00d7 10 m<\/td><td><strong>100 m\u00b2<\/strong><\/td><td><strong>10 kg<\/strong><\/td><td><strong>30 kg<\/strong><\/td><\/tr>';\n      html += '<tr><td>10 \u00d7 20 m<\/td><td>200 m\u00b2<\/td><td>20 kg<\/td><td>60 kg<\/td><\/tr>';\n      html += '<tr><td>15 \u00d7 20 m<\/td><td>300 m\u00b2<\/td><td>30 kg<\/td><td>90 kg<\/td><\/tr>';\n      html += '<tr><td>20 \u00d7 25 m<\/td><td>500 m\u00b2<\/td><td>50 kg<\/td><td>150 kg<\/td><\/tr>';\n      html += '<tr><td>25 \u00d7 40 m<\/td><td>1,000 m\u00b2 <em>(1 stremma)<\/em><\/td><td>100 kg<\/td><td>300 kg<\/td><\/tr>';\n      html += '<\/table>';\n      html += '<p class=\"sublabel\" style=\"margin-top:0.6rem\">\ud83d\udca1 <strong>Irregular shape?<\/strong> Split it mentally into rectangles, calculate each one (length \u00d7 width) and add them up. For a circular area: radius \u00d7 radius \u00d7 3.14.<\/p>';\n      html += '<\/div>';\n      html += '<p class=\"sublabel\">\u2705 <strong>Just one application.<\/strong> Lawn is a perennial crop \u2014 no need to repeat it in the following years.<\/p>';\n    } else if (data.mode === 'ornamental') {\n      html += '<label class=\"qty-label\">Application type<\/label>';\n      html += '<div class=\"options\">';\n      html += '<label class=\"option\"><input type=\"radio\" name=\"ornType\" value=\"pot\">';\n      html += '<span class=\"opt-title\">\ud83e\udeb4 Pot<\/span><span class=\"opt-desc\">% by soil weight<\/span><\/label>';\n      html += '<label class=\"option\"><input type=\"radio\" name=\"ornType\" value=\"garden\">';\n      html += '<span class=\"opt-title\">\ud83c\udf3a Garden<\/span><span class=\"opt-desc\">Grams per plant<\/span><\/label>';\n      html += '<\/div>';\n      html += '<div id=\"zaOrnDetail\" class=\"sub-group hidden\"><\/div>';\n    } else if (data.mode === 'soil_weight') {\n      html += '<label class=\"qty-label\">How many kg of soil will you mix?<\/label>';\n      html += '<input type=\"number\" id=\"zaQty\" class=\"qty-input\" min=\"0\" step=\"1\" placeholder=\"e.g. 50\">';\n      html += '<p class=\"sublabel\">Dosage: ' + data.percent + '% by weight (mixed thoroughly)<\/p>';\n    }\n    qtyContainer.innerHTML = html;\n    var newInputs = qtyContainer.querySelectorAll('input');\n    for (var i = 0; i < newInputs.length; i++) {\n      newInputs[i].addEventListener('input', updateProgress);\n      newInputs[i].addEventListener('change', function(e) {\n        if (e.target.name === 'ornType') renderOrnDetail(e.target.value);\n        if (e.target.name === 'phaseGroup') handlePhaseChange(e.target.value);\n        updateProgress();\n      });\n    }\n  }\n  function handlePhaseChange(phaseValue) {\n    var stremmaInput = document.getElementById('zaQtyStremma');\n    if (!stremmaInput) return;\n    var wrapper = stremmaInput.parentElement;\n    if (phaseValue === 'new') {\n      stremmaInput.disabled = true;\n      stremmaInput.value = '';\n      stremmaInput.placeholder = 'Not applicable to new planting';\n      if (wrapper) wrapper.style.opacity = '0.4';\n    } else {\n      stremmaInput.disabled = false;\n      stremmaInput.placeholder = 'e.g. 5';\n      if (wrapper) wrapper.style.opacity = '1';\n    }\n  }\n  function renderOrnDetail(ornType) {\n    var detail = document.getElementById('zaOrnDetail');\n    if (!detail) return;\n    var html = '';\n    if (ornType === 'pot') {\n      html += '<label class=\"qty-label\">How many kg of potting soil?<\/label>';\n      html += '<input type=\"number\" id=\"zaQty\" class=\"qty-input\" min=\"0\" step=\"1\" placeholder=\"e.g. 10\">';\n      html += '<p class=\"sublabel\">Default 10% by weight (range 5-20%)<\/p>';\n    } else if (ornType === 'garden') {\n      html += '<label class=\"qty-label\">How many plants?<\/label>';\n      html += '<input type=\"number\" id=\"zaQty\" class=\"qty-input\" min=\"1\" placeholder=\"e.g. 50\">';\n      html += '<p class=\"sublabel\">Default 60 g\/plant (range 30-120 g)<\/p>';\n    }\n    detail.innerHTML = html;\n    detail.classList.remove('hidden');\n    var newInput = detail.querySelector('input');\n    if (newInput) newInput.addEventListener('input', updateProgress);\n  }\n  function isPositive(v) {\n    if (!v) return false;\n    if (Number(v) <= 0) return false;\n    return true;\n  }\n  function isStep2Valid(crop) {\n    if (!crop || !cropData[crop]) return false;\n    var data = cropData[crop];\n    if (data.mode === 'tree' || data.mode === 'vine') {\n      var qty = getVal('zaQty');\n      var stremma = getVal('zaQtyStremma');\n      var phaseVal = getChecked('phaseGroup');\n      if (!phaseVal) return false;\n      if (phaseVal === 'new') {\n        return isPositive(qty);\n      }\n      if (isPositive(qty)) return true;\n      if (isPositive(stremma)) return true;\n      return false;\n    }\n    if (data.mode === 'lawn') {\n      var qty2 = getVal('zaQty');\n      var lawnType = getChecked('lawnType');\n      if (!isPositive(qty2)) return false;\n      if (!lawnType) return false;\n      return true;\n    }\n    if (data.mode === 'ornamental') {\n      var ornType = getChecked('ornType');\n      var qty3 = getVal('zaQty');\n      if (!ornType) return false;\n      if (!isPositive(qty3)) return false;\n      return true;\n    }\n    var qty4 = getVal('zaQty');\n    return isPositive(qty4);\n  }\n  function updateProgress() {\n    var crop = getChecked('crop');\n    \/\/ \"Other crop\" \u2192 request mode, not a calculation. Progress\/buttons are handled by enterOtherMode().\n    if (crop === 'other') { return; }\n    var soil = getChecked('soil');\n    var brand = getChecked('brand');\n    var strategy = getChecked('strategy');\n    var step2OK = isStep2Valid(crop);\n    var filled = 0;\n    if (crop) filled++;\n    if (step2OK) filled++;\n    \/\/ Lawn: soil doesn't matter \u2014 Step 3 needs no selection.\n    if (ignoresSoil(crop)) {\n      filled++;\n    } else if (soil) {\n      filled++;\n    }\n    if (brand) filled++;\n    \/\/ One-off crops (lawn): Step 5 needs no selection.\n    if (isOneOff(crop)) {\n      filled++;\n    } else if (strategy) {\n      filled++;\n    }\n    progressBar.style.width = (filled \/ 5 * 100) + '%';\n    steps.forEach(function(s, i) {\n      var isActive = (i === filled) || (i === filled - 1);\n      s.classList.toggle('active', isActive);\n    });\n    calcBtn.disabled = filled < 5;\n  }\n  calc.querySelectorAll('input[name=\"crop\"]').forEach(function(r) {\n    r.addEventListener('change', function() {\n      if (r.value === 'other') {\n        enterOtherMode();\n      } else {\n        exitOtherMode();\n        renderQtyStep(r.value);\n        updateSoilStep(r.value);\n        updateStrategyStep(r.value);\n      }\n      updateProgress();\n    });\n  });\n  var excludedNames = ['crop', 'phaseGroup', 'lawnType', 'ornType'];\n  calc.querySelectorAll('input[type=\"radio\"]').forEach(function(r) {\n    if (excludedNames.indexOf(r.name) === -1) {\n      r.addEventListener('change', updateProgress);\n    }\n  });\n  \/\/ Live-update the WhatsApp\/Email links as the user types\n  ['zaOtherCrop', 'zaOtherDetails'].forEach(function(id) {\n    var el = document.getElementById(id);\n    if (el) { el.addEventListener('input', updateOtherLinks); }\n  });\n  resetBtn.addEventListener('click', function() {\n    zaClearState();\n    calc.querySelectorAll('input[type=\"radio\"]').forEach(function(r) { r.checked = false; });\n    calc.querySelectorAll('input[type=\"number\"]').forEach(function(r) { r.value = ''; });\n    var oc = document.getElementById('zaOtherCrop'); if (oc) oc.value = '';\n    var od = document.getElementById('zaOtherDetails'); if (od) od.value = '';\n    exitOtherMode();\n    updateSoilStep(null);\n    updateStrategyStep(null);\n    qtyContainer.innerHTML = '<p style=\"color:var(--za-muted);font-style:italic;\">First choose a crop in Step 1.<\/p>';\n    resultBox.classList.remove('show');\n    updateProgress();\n    steps[0].classList.add('active');\n    steps[0].scrollIntoView({ behavior: 'smooth', block: 'start' });\n  });\n  \/\/ \"\u2190 Back to the guide\" \u2014 return from request mode to the normal guide\n  var otherBackBtn = document.getElementById('zaOtherBack');\n  if (otherBackBtn) {\n    otherBackBtn.addEventListener('click', function() {\n      var otherRadio = calc.querySelector('input[name=\"crop\"][value=\"other\"]');\n      if (otherRadio) { otherRadio.checked = false; }\n      exitOtherMode();\n      updateProgress();\n      steps[0].classList.add('active');\n      steps[0].scrollIntoView({ behavior: 'smooth', block: 'start' });\n    });\n  }\n  \/\/ Print: only from the \"Keep your dosage\" box at the end of the result (as in the spray guide).\n  function doPrint() {\n    if (!resultBox.classList.contains('show')) { return; }\n    var dateEl = document.getElementById('zaPrintDate');\n    if (dateEl) {\n      var now = new Date();\n      dateEl.textContent = now.toLocaleDateString('en-GB', { day: '2-digit', month: 'long', year: 'numeric' });\n    }\n    window.print();\n  }\n  function calcBaseDose(crop, phaseGroup, qty, stremmaQty, lawnType, ornType) {\n    var data = cropData[crop];\n    if (data.mode === 'tree' || data.mode === 'vine') {\n      var unitLabel = data.mode === 'tree' ? 'trees' : 'vines';\n      var phaseLabel = '';\n      if (phaseGroup) {\n        if (data.phases[phaseGroup]) {\n          phaseLabel = data.phases[phaseGroup].label.replace(\/^[^\\s]+\\s\/, '');\n        }\n      }\n      if (isPositive(qty)) {\n        if (phaseGroup) {\n          var kgPerUnit = data.phases[phaseGroup].kg;\n          return { kg: Number(qty) * kgPerUnit, breakdown: fmtNum(qty) + ' ' + unitLabel + ' \u00d7 ' + kgPerUnit + ' kg (' + phaseLabel + ') = ' + fmtKg(Number(qty) * kgPerUnit) };\n        }\n      }\n      if (isPositive(stremmaQty)) {\n        if (data.perStremmaMax > 0) {\n          return { kg: Number(stremmaQty) * data.perStremmaMax, breakdown: fmtNum(stremmaQty) + ' stremmata \u00d7 ' + data.perStremmaMax + ' kg (existing planting) = ' + fmtKg(Number(stremmaQty) * data.perStremmaMax) };\n        }\n      }\n    }\n    if (data.mode === 'stremma') {\n      return { kg: Number(qty) * data.perStremmaMax, breakdown: fmtNum(qty) + ' stremmata \u00d7 ' + data.perStremmaMax + ' kg = ' + fmtKg(Number(qty) * data.perStremmaMax) };\n    }\n    if (data.mode === 'area') {\n      return { kg: Number(qty) * data.perSqmKg, breakdown: fmtNum(qty) + ' m\u00b2 \u00d7 ' + data.perSqmKg + ' kg\/m\u00b2 = ' + fmtKg(Number(qty) * data.perSqmKg) };\n    }\n    if (data.mode === 'lawn') {\n      \/\/ Input is in m\u00b2. 0.1 kg\/m\u00b2 (existing) or 0.3 kg\/m\u00b2 (new planting) \u2014 one-off.\n      var kgPerSqm = lawnType === 'new' ? data.newKgPerSqm : data.existingKgPerSqm;\n      var kgPerStr = lawnType === 'new' ? data.newKg : data.existingKg;\n      var lawnLabel = lawnType === 'new' ? 'new planting' : 'existing lawn';\n      var sqm = Number(qty);\n      var lawnKg = sqm * kgPerSqm;\n      var bd = fmtNum(sqm) + ' m\u00b2 \u00d7 ' + String(kgPerSqm) + ' kg\/m\u00b2 (' + lawnLabel + ', one-off) = <strong>' + lawnKg.toFixed(1).replace('.0', '') + ' kg<\/strong>';\n      bd += '<br><span style=\"font-size:0.88rem;color:var(--za-muted);\">Equivalent: ' + kgPerStr + ' kg\/stremma (1,000 m\u00b2) \u00b7 your area is ' + (sqm \/ 1000).toFixed(3).replace(\/0+$\/, '').replace(\/[.,]$\/, '') + ' stremmata<\/span>';\n      return { kg: lawnKg, breakdown: bd };\n    }\n    if (data.mode === 'ornamental') {\n      if (ornType === 'pot') {\n        var kg = Number(qty) * (data.potPercent \/ 100);\n        return { kg: kg, breakdown: fmtNum(qty) + ' kg soil \u00d7 ' + data.potPercent + '% = ' + kg.toFixed(2) + ' kg zeolite' };\n      }\n      var g = Number(qty) * data.gardenPerPlant;\n      return { kg: g \/ 1000, breakdown: fmtNum(qty) + ' plants \u00d7 ' + data.gardenPerPlant + ' g = ' + g + ' g (' + (g\/1000).toFixed(2) + ' kg)' };\n    }\n    if (data.mode === 'soil_weight') {\n      var kgS = Number(qty) * (data.percent \/ 100);\n      return { kg: kgS, breakdown: fmtNum(qty) + ' kg soil \u00d7 ' + data.percent + '% = ' + kgS.toFixed(2) + ' kg zeolite' };\n    }\n    return { kg: 0, breakdown: '' };\n  }\n  function getDiscount(kg) {\n    var sacks = Math.ceil(kg \/ 25);\n    if (sacks >= 40) return { sacks: sacks, percent: 40, label: '40+ bags', savings: '\ud83c\udf81 40% discount' };\n    if (sacks >= 30) return { sacks: sacks, percent: 30, label: '30-39 bags', savings: '\ud83c\udf81 30% discount' };\n    if (sacks >= 20) return { sacks: sacks, percent: 20, label: '20-29 bags', savings: '\ud83c\udf81 20% discount' };\n    if (sacks >= 10) return { sacks: sacks, percent: 10, label: '10-19 bags', savings: '\ud83c\udf81 10% discount' };\n    return { sacks: sacks, percent: 0, label: '< 10 bags', savings: '' };\n  }\n  function applyStrategy(baseDose, matureDose, strategy, phase, isTreeVine, oneOff) {\n    \/\/ ONE-OFF CROPS (lawn \/ turf): always a single application.\n    if (oneOff) {\n      return { display: baseDose, year1: baseDose, year2: 0, year3: 0, year4: 0, label: 'One-off application \u2014 just once (perennial crop)', is4Year: false, isOneOff: true };\n    }\n    if (isTreeVine) {\n      if (phase === 'new') {\n        if (strategy === 'year1') {\n          return { display: baseDose, year1: baseDose, year2: 0, year3: 0, year4: 0, label: 'New planting only (planting phase)', is4Year: false };\n        }\n        if (strategy === 'full3') {\n          var y1 = baseDose;\n          var y2 = matureDose * 0.4;\n          var remaining = matureDose - y1 - y2;\n          if (remaining < 0) remaining = 0;\n          var y3 = remaining \/ 2;\n          var y4 = remaining \/ 2;\n          return { display: y1 + y2 + y3 + y4, year1: y1, year2: y2, year3: y3, year4: y4, label: 'Full 4-year programme (new planting)', is4Year: true };\n        }\n        if (strategy === 'maintenance') {\n          var maintNew = matureDose * 0.15;\n          return { display: maintNew, year1: maintNew, year2: 0, year3: 0, year4: 0, label: 'Maintenance (15% of the mature-tree dose)', is4Year: false };\n        }\n      }\n    }\n    if (strategy === 'year1') {\n      return { display: baseDose * 0.4, year1: baseDose * 0.4, year2: 0, year3: 0, year4: 0, label: 'First year (40% of the total dose)', is4Year: false };\n    }\n    if (strategy === 'full3') {\n      return { display: baseDose, year1: baseDose * 0.4, year2: baseDose * 0.3, year3: baseDose * 0.3, year4: 0, label: 'Full 3-year programme', is4Year: false };\n    }\n    if (strategy === 'maintenance') {\n      return { display: baseDose * 0.15, year1: baseDose * 0.15, year2: 0, year3: 0, year4: 0, label: 'Maintenance (15% of the initial application dose)', is4Year: false };\n    }\n    return { display: baseDose, year1: baseDose, year2: 0, year3: 0, year4: 0, is4Year: false };\n  }\n  function calculate(noScroll) {\n    var crop = getChecked('crop');\n    var soil = getChecked('soil');\n    var brand = getChecked('brand');\n    var strategy = getChecked('strategy');\n    var phaseGroup = getChecked('phaseGroup');\n    var lawnType = getChecked('lawnType');\n    var ornType = getChecked('ornType');\n    var qty = getVal('zaQty');\n    var stremmaQty = getVal('zaQtyStremma');\n    var data = cropData[crop];\n    var oneOff = isOneOff(crop);\n    var base = calcBaseDose(crop, phaseGroup, qty, stremmaQty, lawnType, ornType);\n    var baseKg = base.kg;\n    var isTreeVine = (data.mode === 'tree' || data.mode === 'vine');\n    var matureKg = baseKg;\n    if (isTreeVine) {\n      if (phaseGroup === 'new') {\n        if (isPositive(qty)) {\n          matureKg = Number(qty) * data.phases.existing.kg;\n        }\n      }\n    }\n    \/\/ For crops where soil doesn't matter (lawn) there is no soil selection.\n    var soilKnown = !ignoresSoil(crop);\n    if (!soil) { soilKnown = false; }\n    var soilPhrase = soilKnown ? soilLabels[soil].toLowerCase() : 'all soil types';\n    var brandKey = brand;\n    var smartBrandNote = '';\n    if (brand === 'best_value') {\n      if (soilKnown) {\n        brandKey = smartByS[soil];\n        smartBrandNote = '\ud83d\udca1 <strong>Smart choice for ' + soilLabels[soil].toLowerCase() + ' soil:<\/strong> ' + smartReason[soil];\n      } else {\n        brandKey = data.smartBrand || 'imerys';\n        smartBrandNote = '\ud83d\udca1 <strong>Smart choice for ' + (data.smartBrandLabel || data.name.toLowerCase()) + ':<\/strong> ' + (data.smartBrandReason || 'The most suitable grain size for this use.');\n      }\n    }\n    var selectedBrand = products[brandKey];\n    var modifier = selectedBrand.doseModifier;\n    var finalKg = baseKg * modifier;\n    var finalMatureKg = matureKg * modifier;\n    \/\/ Fixed grain size where defined (lawn: always fine gravel), otherwise based on soil.\n    var gran = data.fixedGran ? data.fixedGran : soilToGran[soil];\n    var product = selectedBrand[gran];\n    var fallbackNote = '';\n    if (!product) {\n      fallbackNote = '\u26a0\ufe0f ' + selectedBrand.label + ' is not available as powder. We recommend instead:';\n      product = products.imerys.powder;\n      brandKey = 'imerys';\n      modifier = 1.0;\n      finalKg = baseKg * modifier;\n      finalMatureKg = matureKg * modifier;\n    }\n    var plan = applyStrategy(finalKg, finalMatureKg, strategy, phaseGroup, isTreeVine, oneOff);\n    var discount = getDiscount(plan.display);\n    var isWholesale = plan.display >= 23000;\n    \/\/ === PACKAGE SELECTION BY QUANTITY ===\n    \/\/ Very small\/trial (<1.5kg) \u2192 500g Thracian \u00b7 Small (<25kg) \u2192 5kg IMERYS \u00b7 Otherwise \u2192 25kg bags\n    var tier = 'bag25';\n    if (plan.display > 0) {\n      if (plan.display < SMALL_QTY_KG) {\n        tier = 'kg5';\n        if (plan.display < TEST_QTY_KG) {\n          if (greek500[gran]) { tier = 'g500'; }\n        }\n      }\n    }\n    var packKg = (tier === 'g500') ? 0.5 : (tier === 'kg5' ? 5 : 25);\n    var packWord = (tier === 'g500') ? ' \u00d7 500g' : (tier === 'kg5' ? ' \u00d7 5kg' : ' bags');\n    var recName = product.name;\n    var recUrl = product.url;\n    var recPurity = selectedBrand.purity;\n    var pack5Note = '';\n    if (tier === 'g500') {\n      recName = greek500[gran].name;\n      recUrl = greek500[gran].url;\n      recPurity = '80%';\n      pack5Note = 'Very small\/trial quantity \u2192 we recommend the <strong>500g pack (Greek Thracian)<\/strong> in <strong>' + granLabels[gran] + '<\/strong> grain size' + (soilKnown ? (' for ' + soilPhrase + ' soil.') : '.');\n    } else if (tier === 'kg5') {\n      recName = imerys5kg[gran];\n      recUrl = imerys5kg.url;\n      recPurity = '\u226585%';\n      pack5Note = 'Small quantity \u2192 we recommend the <strong>IMERYS 5 kg pack<\/strong> (variable product with all grain sizes). On the product page choose the <strong>' + granLabels[gran] + '<\/strong> grain size' + (soilKnown ? (' for ' + soilPhrase + ' soil.') : ' \u2014 the right one for this use.');\n    }\n    var html = '';\n    if (smartBrandNote) {\n      html += '<div class=\"info-box\"><strong>\ud83e\udd16 Smart Recommendation<\/strong>' + smartBrandNote + '<\/div>';\n    }\n    if (fallbackNote) {\n      html += '<div class=\"warning\"><strong>' + fallbackNote + '<\/strong><\/div>';\n    }\n    if (plan.isOneOff) {\n      html += '<div class=\"info-box\" style=\"background:#eef7e6;border-color:#d6e8c3;\">';\n      html += '<strong>\u2705 One-off application<\/strong>';\n      html += '<strong>' + data.name + '<\/strong> is a perennial crop: the quantity below is applied <strong>once and only once<\/strong>. No repeat application or maintenance dose is needed in the following years \u2014 the zeolite stays active in the soil.';\n      html += '<\/div>';\n    }\n    html += '<h4>\ud83c\udfaf Recommended product<\/h4>';\n    html += '<div class=\"product-card\">';\n    html += '<span class=\"product-name\">' + recName + '<\/span>';\n    html += '<span class=\"product-reason\">Purity: <strong>' + recPurity + ' clinoptilolite<\/strong>';\n    if (modifier > 1) { if (tier === 'bag25') {\n      html += ' \u00b7 Dosage adjusted +20% due to lower purity';\n    } }\n    if (soilKnown) {\n      html += '<br>Grain size: <strong>' + granLabels[gran] + '<\/strong> \u00b7 Ideal for <strong>' + soilPhrase + '<\/strong> soil.';\n    } else {\n      html += '<br>Grain size: <strong>' + granLabels[gran] + '<\/strong> (1\u20132.5 mm \u00b7 IMERYS 0.8\u20132.5 mm) \u00b7 Suitable for <strong>all soil types<\/strong> \u2014 for lawns the grain size does not depend on the soil.';\n    }\n    var pkgLabel = (tier === 'g500') ? '500 g (trial)' : (tier === 'kg5' ? '5 kg (variable)' : '25 kg bags');\n    html += '<br>Packaging: <strong>' + pkgLabel + '<\/strong><\/span>';\n    if (pack5Note) { html += '<span class=\"product-reason\" style=\"display:block;margin-top:0.5rem;\">' + pack5Note + '<\/span>'; }\n    html += '<\/div>';\n    html += '<h4>\ud83d\udcca Dosage calculation<\/h4>';\n    html += '<table class=\"dose-table\">';\n    html += '<tr><th style=\"width:40%;\">Crop<\/th><td>' + data.icon + ' ' + data.name + '<\/td><\/tr>';\n    html += '<tr><th>Base calculation<\/th><td>' + base.breakdown + '<\/td><\/tr>';\n    if (modifier > 1) {\n      html += '<tr><th>Brand adjustment (+20%)<\/th><td>' + fmtKg(baseKg) + ' \u00d7 1.2 = <strong>' + fmtKg(finalKg) + '<\/strong><\/td><\/tr>';\n    }\n    html += '<tr><th>Strategy<\/th><td>' + plan.label + '<\/td><\/tr>';\n    var doseRowLabel = plan.isOneOff ? 'Total dose (one-off)' : 'Dose to order now';\n    if (strategy === 'full3') { if (!plan.isOneOff) { doseRowLabel = plan.is4Year ? 'Total dose (4 years)' : 'Total dose (3 years)'; } }\n    html += '<tr><th>' + doseRowLabel + '<\/th><td><strong style=\"color:var(--za-brand-dark);font-size:1.1rem;\">' + fmtKg(plan.display) + '<\/strong><\/td><\/tr>';\n    if (tier === 'g500') {\n      html += '<tr><th>Packs (500 g)<\/th><td><strong>' + Math.ceil(plan.display \/ 0.5) + ' \u00d7 500 g<\/strong><\/td><\/tr>';\n    } else if (tier === 'kg5') {\n      html += '<tr><th>Packs (5 kg)<\/th><td><strong>' + Math.ceil(plan.display \/ 5) + ' \u00d7 5 kg<\/strong><\/td><\/tr>';\n    } else {\n      html += '<tr><th>Bags (25 kg)<\/th><td><strong>' + discount.sacks + ' bags<\/strong><\/td><\/tr>';\n    }\n    html += '<\/table>';\n    var cartId = isWholesale ? 0 : zaCartId(brandKey, gran, tier);\n    if (discount.percent > 0) { if (tier === 'bag25') { if (!cartId) {\n      html += '<div class=\"discount-banner\">';\n      html += '<strong>' + discount.savings + '<\/strong><br>';\n      html += 'With ' + discount.sacks + ' bags (' + discount.label + ') you get an automatic <strong>' + discount.percent + '%<\/strong> discount in the cart!';\n      html += '<\/div>';\n    } } }\n    if (strategy === 'full3') { if (!plan.isOneOff) {\n      if (plan.is4Year) {\n        html += '<h4>\ud83d\udcc5 4-year programme (New planting)<\/h4>';\n        html += '<p style=\"font-size:0.92rem;color:var(--za-muted);margin:0 0 0.5rem;\">A new planting starts with the planting dose and scales up to the full mature-plant dose over 4 years.<\/p>';\n        html += '<div class=\"timeline\" style=\"grid-template-columns:repeat(4,1fr);\">';\n        html += '<div class=\"year-card now\"><div class=\"year-label\">\ud83c\udf31 Year 1 (planting)<\/div>';\n        html += '<div class=\"year-kg\">' + fmtKg(plan.year1) + '<\/div>';\n        html += '<div class=\"year-sacks\">' + Math.ceil(plan.year1 \/ packKg) + packWord + '<\/div>';\n        html += '<div class=\"year-percent\">Planting dose<\/div><\/div>';\n        html += '<div class=\"year-card\"><div class=\"year-label\">\ud83d\udfe1 Year 2<\/div>';\n        html += '<div class=\"year-kg\">' + fmtKg(plan.year2) + '<\/div>';\n        html += '<div class=\"year-sacks\">' + Math.ceil(plan.year2 \/ packKg) + packWord + '<\/div>';\n        html += '<div class=\"year-percent\">40% of total<\/div><\/div>';\n        html += '<div class=\"year-card\"><div class=\"year-label\">\ud83d\udfe1 Year 3<\/div>';\n        html += '<div class=\"year-kg\">' + fmtKg(plan.year3) + '<\/div>';\n        html += '<div class=\"year-sacks\">' + Math.ceil(plan.year3 \/ packKg) + packWord + '<\/div>';\n        html += '<div class=\"year-percent\">Remainder \/ 2<\/div><\/div>';\n        html += '<div class=\"year-card\"><div class=\"year-label\">\ud83d\udfe1 Year 4<\/div>';\n        html += '<div class=\"year-kg\">' + fmtKg(plan.year4) + '<\/div>';\n        html += '<div class=\"year-sacks\">' + Math.ceil(plan.year4 \/ packKg) + packWord + '<\/div>';\n        html += '<div class=\"year-percent\">Remainder \/ 2<\/div><\/div>';\n        html += '<\/div>';\n      } else {\n        html += '<h4>\ud83d\udcc5 3-year programme<\/h4>';\n        html += '<div class=\"timeline\">';\n        html += '<div class=\"year-card now\"><div class=\"year-label\">\ud83d\udfe2 Year 1 (now)<\/div>';\n        html += '<div class=\"year-kg\">' + fmtKg(plan.year1) + '<\/div>';\n        html += '<div class=\"year-sacks\">' + Math.ceil(plan.year1 \/ packKg) + packWord + '<\/div>';\n        html += '<div class=\"year-percent\">40% of the dose<\/div><\/div>';\n        html += '<div class=\"year-card\"><div class=\"year-label\">\ud83d\udfe1 Year 2<\/div>';\n        html += '<div class=\"year-kg\">' + fmtKg(plan.year2) + '<\/div>';\n        html += '<div class=\"year-sacks\">' + Math.ceil(plan.year2 \/ packKg) + packWord + '<\/div>';\n        html += '<div class=\"year-percent\">30% of the dose<\/div><\/div>';\n        html += '<div class=\"year-card\"><div class=\"year-label\">\ud83d\udfe1 Year 3<\/div>';\n        html += '<div class=\"year-kg\">' + fmtKg(plan.year3) + '<\/div>';\n        html += '<div class=\"year-sacks\">' + Math.ceil(plan.year3 \/ packKg) + packWord + '<\/div>';\n        html += '<div class=\"year-percent\">30% of the dose<\/div><\/div>';\n        html += '<\/div>';\n      }\n    } }\n    html += '<h4>\u23f0 Application<\/h4>';\n    html += '<div class=\"info-box\">';\n    html += '<strong>\ud83d\udcc5 Best season:<\/strong>' + data.season + '<br>';\n    html += '<strong>\ud83d\udccf Depth \/ method:<\/strong>' + data.depth;\n    html += '<\/div>';\n    if (isWholesale) {\n      html += '<div class=\"wholesale-cta\">';\n      html += '<strong>\ud83d\ude9a Large quantity (>23 tonnes)<\/strong>';\n      html += 'For a special wholesale price, contact us:';\n      html += '<div class=\"wholesale-btns four\">';\n      html += '<a href=\"tel:+302311295520\">\ud83d\udcde +30 2311 29 55 20<\/a>';\n      html += '<a href=\"https:\/\/wa.me\/306985838343?text=' + encodeURIComponent('Hello! I am interested in a wholesale price for ' + fmtKg(plan.display) + ' of zeolite for ' + data.name + '.') + '\" target=\"_blank\">\ud83d\udcac WhatsApp<\/a>';\n      html += '<a href=\"viber:\/\/chat?number=306985838343\">\ud83d\udfe3 Viber<\/a>';\n      html += '<a href=\"mailto:info@zeolife.gr?subject=' + encodeURIComponent('Wholesale zeolite enquiry') + '\">\u2709\ufe0f Email<\/a>';\n      html += '<\/div><\/div>';\n    }\n    html += '<h4>\ud83d\udca1 Application tips<\/h4>';\n    html += '<ul style=\"line-height:1.8;\">';\n    html += '<li>Apply <strong>before rainfall<\/strong> or water well after application.<\/li>';\n    html += '<li>In <strong>organic farming<\/strong>, natural zeolite is 100% compatible.<\/li>';\n    html += '<li>Zeolite acts as a <strong>slow-release reservoir<\/strong>: it retains fertilisers, water and nutrients for many years.<\/li>';\n    html += '<li>Combine with <strong>regular fertilisation<\/strong> \u2014 zeolite does not replace fertilisers, it makes them more efficient.<\/li>';\n    if (soil === 'light') {\n      html += '<li>In <strong>light, sandy soil<\/strong> we do not recommend powder: it is easily washed or blown away. <strong>Fine gravel 1\u20132.5 mm<\/strong> (IMERYS 0.8\u20132.5 mm) stays in the root zone and keeps working for years.<\/li>';\n    }\n    if (crop === 'lawn') {\n      html += '<li>On an <strong>existing lawn<\/strong>: spread evenly (top-dressing) \u2014 ideally after aeration\/scarifying \u2014 and water well so it works down to the roots.<\/li>';\n      html += '<li>For a <strong>new planting<\/strong>: incorporate the zeolite into the soil before sowing or laying turf \u2014 it reduces water and fertiliser needs for years.<\/li>';\n    }\n    html += '<\/ul>';\n    \/\/ === 20\/10\/2026 (proposal A): \"What you need\" \u2192 one-click cart with the right packs ===\n    zaCart = null;\n    if (cartId) {\n      var packLabel = (tier === 'g500') ? '500 g' : (tier === 'kg5' ? '5 kg' : '25 kg');\n      var cartOpts = [];\n      if (strategy === 'full3') { if (!plan.isOneOff) { if (plan.display > plan.year1) {\n        cartOpts.push({ key: 'y1', title: (plan.is4Year ? '\ud83c\udf31 Year 1 (planting)' : '\ud83d\udfe2 Year 1 (now)'), kg: plan.year1 });\n        cartOpts.push({ key: 'all', title: (plan.is4Year ? '\ud83d\udcc5 All 4 years' : '\ud83d\udcc5 All 3 years'), kg: plan.display });\n      } } }\n      if (cartOpts.length === 0) { cartOpts.push({ key: 'all', title: '', kg: plan.display }); }\n      cartOpts.forEach(function(o) { o.n = Math.max(1, Math.ceil(o.kg \/ packKg - 0.000001)); });\n      zaCart = { id: cartId, opts: cartOpts, pack: packLabel, bag: (tier === 'bag25') };\n      html += '<h4>\ud83d\uded2 What you need<\/h4>';\n      if (cartOpts.length === 2) {\n        html += '<div class=\"options cols-2\" id=\"zaCartWhen\">';\n        cartOpts.forEach(function(o, i) {\n          html += '<label class=\"option\"><input type=\"radio\" name=\"zaCartWhen\" value=\"' + o.key + '\"' + (i === 0 ? ' checked' : '') + '>';\n          html += '<span class=\"opt-title\">' + o.title + '<\/span><span class=\"opt-desc\">' + fmtKg(o.kg) + ' \u00b7 ' + o.n + ' \u00d7 ' + packLabel + '<\/span><\/label>';\n        });\n        html += '<\/div>';\n      }\n      html += '<div class=\"zl-plist\" id=\"zaPlist\"><label class=\"zl-prow\"><input type=\"checkbox\" checked id=\"zaCartPick\">';\n      html += '<span><span class=\"zl-pn\">' + recName + '<\/span><span class=\"zl-pr\" id=\"zaCartWhy\"><\/span><\/span>';\n      html += '<span class=\"zl-pq\" id=\"zaCartQty\"><\/span><\/label><\/div>';\n      html += '<div class=\"zl-cartbox\"><div class=\"discount-banner\" id=\"zaDisc\" style=\"display:none\"><\/div>';\n      html += '<p>Untick it if you already have it. The product goes into the <strong>shop.zeolife.gr<\/strong> cart in the right quantity. There you see final prices and discounts.<\/p>';\n      html += '<a class=\"cta-btn\" id=\"zaCartBtn\" href=\"' + CART_URL + '\"><span>\ud83d\uded2 Add to cart (<span id=\"zaCartCnt\">0<\/span>) \u2192<\/span><\/a><\/div>';\n    }\n    html += '<div class=\"cta-row\">';\n    if (!cartId) { html += '<a href=\"' + recUrl + '\" class=\"btn\">\ud83d\uded2 Buy now<\/a>'; }\n    html += '<a href=\"https:\/\/zeolife.gr\/en\/zeolite-in-agriculture\/\" class=\"btn btn-secondary\">\ud83d\udcd6 Zeolite in agriculture<\/a>';\n    html += '<\/div>';\n    \/\/ --- 20\/10\/2026 (proposal B): Keep your dosage \u2014 email (+ reminders per year) \u00b7 calendar \u00b7 print ---\n    var zaStages = [];\n    if (strategy === 'full3') { if (!plan.isOneOff) {\n      if (plan.is4Year) {\n        zaStages.push({ key: 'y1', name: 'Year 1 (planting)', icon: '\ud83c\udf31', kg: plan.year1 });\n        zaStages.push({ key: 'y2', name: 'Year 2', icon: '\ud83d\udfe1', kg: plan.year2 });\n        zaStages.push({ key: 'y3', name: 'Year 3', icon: '\ud83d\udfe1', kg: plan.year3 });\n        zaStages.push({ key: 'y4', name: 'Year 4', icon: '\ud83d\udfe1', kg: plan.year4 });\n      } else {\n        zaStages.push({ key: 'y1', name: 'Year 1', icon: '\ud83d\udfe2', kg: plan.year1 });\n        zaStages.push({ key: 'y2', name: 'Year 2', icon: '\ud83d\udfe1', kg: plan.year2 });\n        zaStages.push({ key: 'y3', name: 'Year 3', icon: '\ud83d\udfe1', kg: plan.year3 });\n      }\n    } }\n    if (zaStages.length === 0) {\n      var oneName = plan.isOneOff ? 'One-off application' : (strategy === 'maintenance' ? 'Maintenance' : 'First phase');\n      zaStages.push({ key: 'y1', name: oneName, icon: '\ud83d\udfe2', kg: plan.display });\n    }\n    zaStages = zaStages.filter(function(st) { return st.kg > 0; });\n    zaStages.forEach(function(st) { st.n = Math.max(1, Math.ceil(st.kg \/ packKg - 0.000001)); });\n    var zaPack = (tier === 'g500') ? '500 g' : (tier === 'kg5' ? '5 kg' : '25 kg');\n    zaLast = { crop: crop, data: data, stages: zaStages, oneOff: plan.isOneOff === true, recName: recName, gran: granLabels[gran], pack: zaPack, packKg: packKg, cartId: cartId, qtyLabel: zaQtyLabel(crop, phaseGroup, qty, stremmaQty, ornType), t0: Date.now() };\n    var multi = zaStages.length > 1;\n    html += '<div class=\"zl-keep\" id=\"zaKeep\"><h4>\ud83d\udcec Keep your dosage<\/h4><p class=\"zl-keep-sub\">Choose how you want to keep it. You can pick all of them.<\/p>';\n    html += '<div class=\"zl-tiles\">';\n    html += '<button type=\"button\" class=\"zl-tile on\" data-za-tile=\"mail\"><b>\u2709\ufe0f Email it to me<\/b><span>' + (multi ? 'With reminders for every year' : (plan.isOneOff ? 'So you always have it' : 'With a maintenance reminder')) + '<\/span><\/button>';\n    html += '<button type=\"button\" class=\"zl-tile\" data-za-tile=\"ics\"><b>\ud83d\udcc5 To my calendar<\/b><span>.ics file for mobile, Google, Outlook<\/span><\/button>';\n    html += '<button type=\"button\" class=\"zl-tile\" data-za-tile=\"print\"><b>\ud83d\udda8\ufe0f Print<\/b><span>Only the dosage, on A4<\/span><\/button>';\n    html += '<\/div>';\n    html += '<form class=\"zl-mail\" id=\"zaMail\" novalidate>';\n    html += '<label class=\"qty-label\" for=\"zaEmail\">Your email<\/label>';\n    html += '<input type=\"email\" id=\"zaEmail\" class=\"qty-input\" placeholder=\"e.g. john@gmail.com\" autocomplete=\"email\" required>';\n    html += '<input type=\"text\" name=\"website\" id=\"zaHp\" class=\"zl-hp\" tabindex=\"-1\" autocomplete=\"off\" aria-hidden=\"true\">';\n    if (!plan.isOneOff) {\n      if (multi) {\n        html += '<label class=\"zl-chk\"><input type=\"checkbox\" id=\"zaRemind\" checked><span><strong>Remind me by email before each application<\/strong> \u00b7 free, for as long as the program runs<\/span><\/label>';\n        html += '<div class=\"zl-rem\" id=\"zaRemBox\"><div class=\"zl-rem-lead\">Send me the reminder <select id=\"zaLead\"><option value=\"7\">7 days<\/option><option value=\"14\" selected>14 days<\/option><option value=\"30\">30 days<\/option><\/select> before each application.<\/div>';\n        html += '<div class=\"zl-dates\"><span class=\"zl-dates-h\">Application dates \u2014 change them if you like:<\/span>';\n        zaStages.forEach(function(st, i) {\n          html += '<label class=\"zl-date\"><span>' + st.icon + ' ' + st.name + ' \u00b7 ' + zaKgTxt(st.kg) + ' \u00b7 ' + st.n + ' \u00d7 ' + zaPack + '<\/span><input type=\"date\" data-za-date=\"' + i + '\" value=\"' + zaIso(zaYearsFromNow(i)) + '\"><\/label>';\n        });\n        html += '<\/div><span class=\"zl-small\">Stop with one click from any email. The dates also go into the calendar file.<\/span><\/div>';\n      } else {\n        html += '<label class=\"zl-chk\"><input type=\"checkbox\" id=\"zaRemind\" checked><span><strong>Remind me in one year<\/strong> about the maintenance dose \u00b7 free<\/span><\/label>';\n      }\n    }\n    html += '<label class=\"zl-chk\"><input type=\"checkbox\" id=\"zaNews\"><span>I would also like the weekly Zeolife newsletter (tips, offers).<\/span><\/label>';\n    html += '<label class=\"zl-chk\"><input type=\"checkbox\" id=\"zaConsent\"><span>I agree that my email is used only to send the dosage and the reminders. <a href=\"https:\/\/shop.zeolife.gr\/en\/privacy-policy\/\" target=\"_blank\" rel=\"noopener\">Privacy policy<\/a><\/span><\/label>';\n    html += '<div class=\"zl-mail-row\"><button type=\"submit\" class=\"btn\" id=\"zaSend\">\u2709\ufe0f Send me the dosage<\/button><\/div>';\n    html += '<p class=\"zl-status\" id=\"zaStatus\" role=\"status\" aria-live=\"polite\"><\/p>';\n    html += '<\/form><\/div>';\n    \/\/ --- 20\/10\/2026 (proposal D): card to the spray guide, with crop and quantity already filled in ---\n    \/\/ Only for crops the spray guide has. Cereals, lawn, vegetable garden etc.: no card.\n    var sprayCrop = { olive: 'olive', walnut: 'nuts', pistachio: 'nuts', fruit: 'fruit', vineyard: 'vineyard' }[crop] || '';\n    if (sprayCrop) {\n      var AMP = String.fromCharCode(38);\n      var sprayUrl = 'https:\/\/zeolife.gr\/en\/foliar-spray-program-calculator\/?crop=' + sprayCrop;\n      var sprayWhat = '';\n      if (isPositive(qty)) {\n        sprayUrl += AMP + 'trees=' + Math.round(Number(qty)) + AMP + 'src=edafos';\n        sprayWhat = 'your <strong>' + fmtNum(qty) + ' ' + (crop === 'vineyard' ? 'vines' : 'trees') + '<\/strong>';\n      } else if (isPositive(stremmaQty)) {\n        sprayUrl += AMP + 'stremma=' + String(Number(stremmaQty)) + AMP + 'src=edafos';\n        sprayWhat = 'your <strong>' + String(Number(stremmaQty)) + ' stremmata<\/strong>';\n      }\n      html += '<div class=\"zl-soil\"><div class=\"zl-soil-ill\" aria-hidden=\"true\" style=\"background:linear-gradient(180deg,#dff1f1 0%,#dff1f1 55%,#e9f4ec 55%,#e9f4ec 100%)\">\ud83c\udf33<\/div><div><strong class=\"zl-soil-h\">\ud83d\udca8 The soil is ready. What about the foliage?<\/strong>';\n      html += '<p>4 sprays a year with 20-micron zeolite or ZeTe' + (sprayWhat ? ' for ' + sprayWhat : '') + ' \u2014 the guide opens with the crop' + (sprayWhat ? ' and the quantity already filled in' : ' already selected') + '.<\/p><\/div>';\n      html += '<a class=\"btn btn-secondary\" href=\"' + sprayUrl + '\">Create the spray program \u2192<\/a><\/div>';\n    }\n    html += '<p class=\"disclaimer\"><strong>Note:<\/strong> Dosages are indicative and based on official supplier guidelines for zeolite with \u226580% clinoptilolite. For special cases (organic certification, high salinity, unusual soil chemistry), consult an agronomist. Zeolife.gr provides technical support: +30 2311 29 55 20.<\/p>';\n    resultBody.innerHTML = html;\n    zaBindKeep();\n    \/\/ 20\/10\/2026 (proposal E): combined yearly program, if the customer also created a spray program in this tab.\n    if (window.zlYear) {\n      window.zlYear.save('soil', { crop: crop, name: data.name, icon: data.icon, qty: zaLast.qtyLabel, payload: zaPayload() });\n      window.zlYear.render(document.getElementById('zaKeep'), 'soil');\n    }\n    resultBox.classList.add('show');\n    zaBindCart();\n    zaSaveState();\n    if (noScroll !== true) { resultBox.scrollIntoView({ behavior: 'smooth', block: 'start' }); }\n  }\n  calcBtn.addEventListener('click', function() { calculate(); });\n\n  \/\/ ===== 20\/10\/2026 (proposal B): email & reminders (shop.zeolife.gr) \u00b7 .ics calendar =====\n  var PLAN_API = 'https:\/\/shop.zeolife.gr\/wp-json\/zt\/v1\/spray-plan';\n  function zaPad(n) { return (n > 9 ? '' : '0') + n; }\n  function zaIso(d) { return d.getFullYear() + '-' + zaPad(d.getMonth() + 1) + '-' + zaPad(d.getDate()); }\n  function zaToday() { var d = new Date(); return new Date(d.getFullYear(), d.getMonth(), d.getDate()); }\n  function zaYearsFromNow(k) { var t = zaToday(); return new Date(t.getFullYear() + k, t.getMonth(), t.getDate()); }\n  function zaQtyLabel(crop, phaseGroup, qty, stremmaQty, ornType) {\n    var data = cropData[crop];\n    var out = '';\n    if (data.mode === 'tree' || data.mode === 'vine') {\n      if (isPositive(qty)) { out = fmtNum(qty) + ' ' + (data.mode === 'tree' ? 'trees' : 'vines'); }\n      else if (isPositive(stremmaQty)) { out = String(Number(stremmaQty)) + ' stremmata'; }\n      if (phaseGroup) { if (data.phases[phaseGroup]) { out += ' \u00b7 ' + data.phases[phaseGroup].label.replace(\/^[^\\s]+\\s\/, ''); } }\n      return out;\n    }\n    if (data.mode === 'stremma') { return String(Number(qty)) + ' stremmata'; }\n    if (data.mode === 'area' || data.mode === 'lawn') { return fmtNum(qty) + ' m\u00b2'; }\n    if (data.mode === 'ornamental') { return ornType === 'pot' ? fmtNum(qty) + ' kg of soil (pot)' : fmtNum(qty) + ' plants (garden)'; }\n    return fmtNum(qty) + ' kg of soil';\n  }\n  function zaChosenDate(i) {\n    var el = calc.querySelector('input[data-za-date=\"' + i + '\"]');\n    if (!el) return null;\n    var m = \/^(\\d{4})-(\\d{2})-(\\d{2})$\/.exec(el.value || '');\n    return m ? new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3])) : null;\n  }\n  function zaStageDate(i) { return zaChosenDate(i) || zaYearsFromNow(i); }\n  function zaPayload() {\n    var L = zaLast;\n    var stages = [];\n    var prev = '';\n    var sum = 0, tot = 0;\n    L.stages.forEach(function(st, i) {\n      var iso = zaIso(zaStageDate(i));\n      if (prev) { if (prev > iso) { iso = prev; } }\n      prev = iso;\n      sum += st.n;\n      tot += st.kg;\n      stages.push({ key: st.key, name: st.name, icon: st.icon, win: L.data.season, tip: L.data.depth, date: iso,\n        rows: [[1, L.recName, L.gran, '', zaKgTxt(st.kg) + ' \u00b7 ' + st.n + ' \u00d7 ' + L.pack]],\n        items: L.cartId ? (L.cartId + ':' + st.n) : '' });\n    });\n    \/\/ Program total: bags for all the kilos together (same as \"All years\" in the cart).\n    sum = Math.max(1, Math.ceil(tot \/ L.packKg - 0.000001));\n    return {\n      kind: 'soil', renew: L.oneOff ? 0 : 1,\n      title: L.data.name, crop: L.crop, icon: L.data.icon, qty: L.qtyLabel, water: '', tank: '',\n      guide: window.location.origin + window.location.pathname,\n      year: (L.cartId ? (L.stages.length > 1 ? L.cartId + ':' + sum : '') : ''),\n      yearl: [L.recName + ': ' + zaKgTxt(tot) + ' \u00b7 ' + sum + ' \u00d7 ' + L.pack],\n      stages: stages\n    };\n  }\n  function zaStatus(msg, kind) {\n    var st = document.getElementById('zaStatus');\n    if (!st) return;\n    st.textContent = msg;\n    st.className = 'zl-status' + (kind ? ' is-' + kind : '');\n  }\n  function zaSend(e) {\n    e.preventDefault();\n    var em = document.getElementById('zaEmail');\n    var email = (em.value || '').trim();\n    if (!\/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\/.test(email)) { zaStatus('Please enter a valid email.', 'err'); em.focus(); return; }\n    if (!document.getElementById('zaConsent').checked) { zaStatus('Please tick the consent box so we can send you the dosage.', 'err'); return; }\n    var btn = document.getElementById('zaSend');\n    btn.disabled = true;\n    zaStatus('Sending\u2026', '');\n    var rem = document.getElementById('zaRemind');\n    var lead = document.getElementById('zaLead');\n    var body = new URLSearchParams();\n    body.append('kind', 'soil');\n    body.append('email', email);\n    body.append('lang', 'en');\n    body.append('consent', '1');\n    body.append('remind', rem ? (rem.checked ? '1' : '') : '');\n    body.append('lead', lead ? lead.value : '14');\n    body.append('newsletter', document.getElementById('zaNews').checked ? '1' : '');\n    body.append('website', document.getElementById('zaHp').value);\n    body.append('tm', String(Date.now() - (zaLast.t0 || Date.now())));\n    body.append('plan', JSON.stringify(zaPayload()));\n    fetch(PLAN_API, { method: 'POST', body: body })\n      .then(function(r) { return r.json().catch(function() { return { ok: false, message: '' }; }); })\n      .then(function(j) {\n        btn.disabled = false;\n        if (j.ok) { zaStatus(j.message || 'Sent!', 'ok'); } else { zaStatus(j.message || 'Something went wrong. Please try again or call us on +30 2311 29 55 20.', 'err'); }\n      })\n      .catch(function() { btn.disabled = false; zaStatus('Could not connect. Please try again shortly.', 'err'); });\n  }\n  function zaIcsEsc(s) { return String(s).replace(\/\\\\\/g, '\\\\\\\\').replace(\/,\/g, '\\\\,').replace(\/;\/g, '\\\\;').replace(\/\\n\/g, '\\\\n'); }\n  function zaIcsDate(d) { return d.getFullYear() + zaPad(d.getMonth() + 1) + zaPad(d.getDate()); }\n  function zaDownloadIcs() {\n    if (!zaLast) return;\n    var L = zaLast;\n    var lines = ['BEGIN:VCALENDAR', 'VERSION:2.0', 'PRODID:-\/\/Zeolife\/\/Soil Program\/\/EL', 'CALSCALE:GREGORIAN'];\n    var stamp = new Date();\n    L.stages.forEach(function(st, i) {\n      var d = zaStageDate(i);\n      var end = new Date(d.getFullYear(), d.getMonth(), d.getDate() + 1);\n      lines.push('BEGIN:VEVENT');\n      lines.push('UID:zeolife-soil-' + L.crop + '-' + i + '-' + zaIcsDate(d) + '@zeolife.gr');\n      lines.push('DTSTAMP:' + zaIcsDate(stamp) + 'T000000Z');\n      lines.push('DTSTART;VALUE=DATE:' + zaIcsDate(d));\n      lines.push('DTEND;VALUE=DATE:' + zaIcsDate(end));\n      lines.push('SUMMARY:' + zaIcsEsc('\ud83c\udf3e Zeolite in the soil \u2014 ' + st.name + ' (' + L.data.name + ')'));\n      lines.push('DESCRIPTION:' + zaIcsEsc(L.recName + ': ' + zaKgTxt(st.kg) + ' \u00b7 ' + st.n + ' \u00d7 ' + L.pack + '\\nQuantity: ' + L.qtyLabel + '\\nSeason: ' + L.data.season + '\\nMethod: ' + L.data.depth + '\\nGuide: ' + window.location.origin + window.location.pathname));\n      lines.push('BEGIN:VALARM');\n      lines.push('ACTION:DISPLAY');\n      lines.push('DESCRIPTION:' + zaIcsEsc('Zeolite in the soil \u2014 ' + st.name));\n      lines.push('TRIGGER:-P7D');\n      lines.push('END:VALARM');\n      lines.push('END:VEVENT');\n    });\n    lines.push('END:VCALENDAR');\n    var blob = new Blob([lines.join('\\r\\n')], { type: 'text\/calendar;charset=utf-8' });\n    var a = document.createElement('a');\n    a.href = URL.createObjectURL(blob);\n    a.download = 'zeolife-zeolithos-edafos.ics';\n    document.body.appendChild(a);\n    a.click();\n    setTimeout(function() { URL.revokeObjectURL(a.href); a.parentNode.removeChild(a); }, 1000);\n  }\n  function zaBindKeep() {\n    calc.querySelectorAll('[data-za-tile]').forEach(function(t) {\n      t.addEventListener('click', function() {\n        var k = t.getAttribute('data-za-tile');\n        if (k === 'ics') { zaDownloadIcs(); return; }\n        if (k === 'print') { doPrint(); return; }\n        var on = !t.classList.contains('on');\n        t.classList.toggle('on', on);\n        document.getElementById('zaMail').style.display = on ? '' : 'none';\n      });\n    });\n    var rem = document.getElementById('zaRemind');\n    var box = document.getElementById('zaRemBox');\n    if (rem) { if (box) { rem.addEventListener('change', function() { box.style.display = rem.checked ? '' : 'none'; }); } }\n    calc.querySelectorAll('input[data-za-date]').forEach(function(inp) {\n      inp.addEventListener('change', function() {\n        var all = calc.querySelectorAll('input[data-za-date]');\n        for (var i = 1; i !== all.length; i++) {\n          if (all[i].value) { if (all[i - 1].value) { if (all[i - 1].value > all[i].value) { all[i].value = all[i - 1].value; } } }\n        }\n      });\n    });\n    var f = document.getElementById('zaMail');\n    if (f) { f.addEventListener('submit', zaSend); }\n  }\n\n  \/\/ ===== 20\/10\/2026 (proposal A): eShop cart & return to the guide =====\n  function zaBackQuery() { return 'zl_back=' + encodeURIComponent(window.location.origin + window.location.pathname) + AMPC + 'zl_lang=en'; }\n  function zaCartOpt() {\n    if (!zaCart) return null;\n    var w = getChecked('zaCartWhen');\n    for (var i = 0; i !== zaCart.opts.length; i++) { if (zaCart.opts[i].key === w) { return zaCart.opts[i]; } }\n    return zaCart.opts[0];\n  }\n  \/\/ Small quantities: grams or one decimal (fmtKg rounds to whole kilos).\n  function zaKgTxt(n) {\n    if (1 > n) { return Math.round(n * 1000).toLocaleString('en-GB') + ' g'; }\n    if (10 > n) { return (Math.round(n * 10) \/ 10).toLocaleString('en-GB') + ' kg'; }\n    return fmtKg(n);\n  }\n  function zaUpdateCart() {\n    var btn = document.getElementById('zaCartBtn');\n    if (!btn) return;\n    var o = zaCartOpt();\n    var pick = document.getElementById('zaCartPick');\n    var on = pick ? pick.checked : true;\n    var n = on ? o.n : 0;\n    var why = document.getElementById('zaCartWhy');\n    if (why) { why.textContent = zaKgTxt(o.kg) + ' \u00b7 pack ' + zaCart.pack; }\n    var q = document.getElementById('zaCartQty');\n    if (q) { q.textContent = o.n + ' \u00d7 ' + zaCart.pack; }\n    var cnt = document.getElementById('zaCartCnt');\n    if (cnt) { cnt.textContent = String(n); }\n    var d = document.getElementById('zaDisc');\n    if (d) {\n      var pct = zaCart.bag ? zaDiscPct(n) : 0;\n      if (pct > 0) {\n        var nextAt = (pct === 10) ? 20 : (pct === 20 ? 30 : (pct === 30 ? 40 : 0));\n        var more = nextAt ? nextAt - n : 0;\n        d.innerHTML = '<strong>\ud83c\udf81 ' + pct + '% discount \u2014 already in the cart.<\/strong><br>With ' + n + ' bags the quantity discount applies automatically.' + (more > 0 ? (more > 3 ? '' : ' Just <strong>' + more + (more === 1 ? ' more bag' : ' more bags') + '<\/strong> and you get ' + (pct + 10) + '%.') : '');\n        d.style.display = '';\n      } else {\n        if (zaCart.bag ? (n >= 7) : false) {\n          d.innerHTML = '<strong>\ud83c\udf81 Just ' + (10 - n) + (10 - n === 1 ? ' more bag' : ' more bags') + ' and you get a 10% discount.<\/strong>';\n          d.style.display = '';\n        } else { d.style.display = 'none'; }\n      }\n    }\n    if (n === 0) { btn.setAttribute('aria-disabled', 'true'); btn.href = CART_URL; return; }\n    btn.removeAttribute('aria-disabled');\n    btn.href = CART_URL + '?zl_cart=' + zaCart.id + ':' + n + AMPC + zaBackQuery();\n  }\n  function zaBindCart() {\n    if (!zaCart) return;\n    resultBody.querySelectorAll('input[name=\"zaCartWhen\"], #zaCartPick').forEach(function(el) {\n      el.addEventListener('change', function() { zaUpdateCart(); zaSaveState(); });\n    });\n    var btn = document.getElementById('zaCartBtn');\n    if (btn) { btn.addEventListener('click', function() { zaUpdateCart(); zaSaveState(); }); }\n    zaUpdateCart();\n  }\n\n  \/\/ ===== 20\/10\/2026 (proposal C): the choices are kept in this tab (sessionStorage), for the return from the eShop =====\n  var ZA_STATE = 'zaState';\n  function zaStore() { try { return window.sessionStorage; } catch (e) { return null; } }\n  function zaSaveState() {\n    var st = zaStore();\n    if (!st) return;\n    var crop = getChecked('crop');\n    if (!crop) return;\n    if (crop === 'other') return;\n    var o = { t: Date.now(), crop: crop, phase: getChecked('phaseGroup'), lawn: getChecked('lawnType'), orn: getChecked('ornType'),\n      qty: getVal('zaQty'), str: getVal('zaQtyStremma'), soil: getChecked('soil'), brand: getChecked('brand'), strategy: getChecked('strategy'),\n      res: resultBox.classList.contains('show'), when: getChecked('zaCartWhen'), off: false, y: window.pageYOffset || 0 };\n    var pk = document.getElementById('zaCartPick');\n    if (pk) { o.off = !pk.checked; }\n    try { st.setItem(ZA_STATE, JSON.stringify(o)); } catch (e) {}\n  }\n  function zaClearState() { var st = zaStore(); if (st) { try { st.removeItem(ZA_STATE); } catch (e) {} } }\n  function zaSetRadio(name, val) {\n    if (val === null || val === undefined) return null;\n    var el = calc.querySelector('input[name=\"' + name + '\"][value=\"' + val + '\"]');\n    if (el) { el.checked = true; }\n    return el;\n  }\n  function zaRestoreState() {\n    var st = zaStore();\n    if (!st) return;\n    var o = null;\n    try { o = JSON.parse(st.getItem(ZA_STATE) || 'null'); } catch (e) { o = null; }\n    if (!o) return;\n    if (Date.now() - (o.t || 0) > 6 * 3600 * 1000) { zaClearState(); return; }\n    if (!cropData[o.crop]) return;\n    if (!zaSetRadio('crop', o.crop)) return;\n    exitOtherMode();\n    renderQtyStep(o.crop);\n    updateSoilStep(o.crop);\n    updateStrategyStep(o.crop);\n    if (zaSetRadio('phaseGroup', o.phase)) { handlePhaseChange(o.phase); }\n    zaSetRadio('lawnType', o.lawn);\n    if (zaSetRadio('ornType', o.orn)) { renderOrnDetail(o.orn); }\n    var qi = document.getElementById('zaQty'); if (qi) { if (o.qty) { qi.value = o.qty; } }\n    var si = document.getElementById('zaQtyStremma'); if (si) { if (o.str) { if (!si.disabled) { si.value = o.str; } } }\n    zaSetRadio('soil', o.soil);\n    zaSetRadio('brand', o.brand);\n    zaSetRadio('strategy', o.strategy);\n    updateProgress();\n    if (o.res) { if (!calcBtn.disabled) {\n      calculate(true);\n      zaSetRadio('zaCartWhen', o.when);\n      var pk = document.getElementById('zaCartPick'); if (pk) { if (o.off) { pk.checked = false; } }\n      zaUpdateCart();\n    } }\n    if (o.y) {\n      var go = function() { window.scrollTo(0, o.y); };\n      if (document.readyState === 'complete') { setTimeout(go, 80); } else { window.addEventListener('load', function() { setTimeout(go, 80); }); }\n    }\n  }\n  calc.querySelectorAll('a[data-za-more]').forEach(function(a) {\n    a.addEventListener('click', function(e) {\n      e.stopPropagation();\n      zaSaveState();\n      a.href = a.getAttribute('data-za-more') + '?' + zaBackQuery();\n    });\n  });\n  window.addEventListener('pagehide', zaSaveState);\n  \/\/ ===== STICKY PROGRESS BAR (JS-driven position:fixed) =====\n  \/\/ More reliable than CSS position:sticky, which breaks when a parent element\n  \/\/ of the theme (WordPress\/Kadence\/WPBakery) has overflow. Also accounts for the\n  \/\/ WP admin bar height so it shows correctly for logged-in users.\n  var progressEl = calc.querySelector('.progress');\n  var progressSpacer = document.getElementById('zaProgressSpacer');\n  var progFlowHeight = 0;\n  function zaMeasure() {\n    if (!progressEl) return;\n    var mb = parseFloat(window.getComputedStyle(progressEl).marginBottom) || 0;\n    progFlowHeight = progressEl.offsetHeight + mb;\n  }\n  \/\/ How high the pinned elements sit at the top: WP admin bar + Kadence sticky\n  \/\/ menu. Measured DYNAMICALLY on every scroll, so the bar always sits EXACTLY\n  \/\/ below the menu \u2014 on desktop and mobile, with or without the admin bar.\n  var ZA_EXTRA_OFFSET = 0; \/\/ optional extra gap in px (e.g. 6) if you want some breathing room\n  function zaFixedTopBottom(el) {\n    if (!el) return 0;\n    var cs = window.getComputedStyle(el);\n    if (cs.position !== 'fixed') return 0;\n    if (cs.display === 'none') return 0;\n    if (cs.visibility === 'hidden') return 0;\n    var r = el.getBoundingClientRect();\n    if (r.height === 0) return 0;\n    if (r.top > 300) return 0;   \/\/ must sit at the top, not somewhere lower\n    if (r.bottom <= 0) return 0;\n    return r.bottom;\n  }\n  function zaTopOffset() {\n    var offset = 0;\n    var ab = zaFixedTopBottom(document.getElementById('wpadminbar'));\n    if (ab > offset) { offset = ab; }\n    var heads = document.querySelectorAll('.kadence-sticky-header');\n    for (var i = 0; i < heads.length; i++) {\n      var hb = zaFixedTopBottom(heads[i]);\n      if (hb > offset) { offset = hb; }\n    }\n    return offset + ZA_EXTRA_OFFSET;\n  }\n  var zaPinned = false;\n  function zaUpdateSticky() {\n    if (!progressEl) return;\n    var offset = zaTopOffset();\n    var rect = calc.getBoundingClientRect();\n    \/\/ WordPress-safe: keep the comparison without less-than and without logical-AND\n    \/\/ on the same line, so the WP editor doesn't mistake it for an HTML tag.\n    var shouldPin = false;\n    if (offset >= rect.top) {\n      if (rect.bottom > (offset + 24)) { shouldPin = true; }\n    }\n    if (shouldPin) {\n      var s = progressEl.style;\n      s.position = 'fixed'; s.top = offset + 'px'; s.left = rect.left + 'px';\n      s.width = rect.width + 'px'; s.zIndex = '99999';\n      progressEl.classList.add('za-stuck');\n      if (progressSpacer) progressSpacer.style.height = progFlowHeight + 'px';\n      zaPinned = true;\n    } else if (zaPinned || progressEl.style.position === 'fixed') {\n      var s2 = progressEl.style;\n      s2.position = ''; s2.top = ''; s2.left = ''; s2.width = ''; s2.zIndex = '';\n      progressEl.classList.remove('za-stuck');\n      if (progressSpacer) progressSpacer.style.height = '0px';\n      zaPinned = false;\n    }\n  }\n  zaMeasure();\n  window.addEventListener('load', function() { zaMeasure(); zaUpdateSticky(); });\n  window.addEventListener('scroll', zaUpdateSticky, { passive: true });\n  window.addEventListener('resize', function() { zaMeasure(); zaUpdateSticky(); });\n  zaUpdateSticky();\n  updateProgress();\n  \/\/ ===== 20\/10\/2026 (proposal D): opened from the spray guide \u2192 ?crop=olive + trees=100 (or stremma=5) =====\n  function zaPrefill() {\n    var q;\n    try { q = new URLSearchParams(window.location.search); } catch (e) { return false; }\n    var ck = q.get('crop');\n    if (!ck) return false;\n    if (!cropData[ck]) return false;\n    var radio = calc.querySelector('input[name=\"crop\"][value=\"' + ck + '\"]');\n    if (!radio) return false;\n    radio.checked = true;\n    zaClearState();\n    exitOtherMode();\n    renderQtyStep(ck);\n    updateSoilStep(ck);\n    updateStrategyStep(ck);\n    var trees = Math.round(Number(q.get('trees') || q.get('qty') || 0));\n    var str = Number(String(q.get('stremma') || '0').replace(',', '.'));\n    var data = cropData[ck];\n    var unit = (ck === 'vineyard') ? 'vines' : 'trees';\n    var said = '';\n    if (data.mode === 'tree' || data.mode === 'vine') {\n      if (trees > 0) {\n        var qi = document.getElementById('zaQty');\n        if (qi) { qi.value = String(trees); said = fmtNum(trees) + ' ' + unit; }\n      } else if (str > 0) {\n        var si = document.getElementById('zaQtyStremma');\n        if (si) { si.value = String(str); said = String(str) + ' stremmata'; }\n      }\n    }\n    if (q.get('src') === 'psekasmos') {\n      var note = document.createElement('div');\n      note.className = 'info-box';\n      note.innerHTML = '\u2705 From the spray guide: <strong>' + data.name + (said ? ' \u00b7 ' + said : '') + '<\/strong>. Choose the planting phase and the soil.';\n      qtyContainer.insertBefore(note, qtyContainer.firstChild);\n    }\n    updateProgress();\n    return true;\n  }\n  \/\/ From the spray guide (URL) \u2192 prefill; otherwise whatever the customer left before going to the eShop.\n  if (!zaPrefill()) { zaRestoreState(); }\n})();\n<\/script>\n<!-- ==== ZL PRINT: \u03b5\u03ba\u03c4\u03c5\u03c0\u03ce\u03bd\u03b5\u03b9 \u039c\u039f\u039d\u039f \u03c4\u03bf \u03b1\u03c0\u03bf\u03c4\u03ad\u03bb\u03b5\u03c3\u03bc\u03b1 \u03c4\u03bf\u03c5 \u03bf\u03b4\u03b7\u03b3\u03bf\u03cd (\u03c7\u03c9\u03c1\u03af\u03c2 header\/\u03bc\u03b5\u03bd\u03bf\u03cd\/\u03c4\u03af\u03c4\u03bb\u03bf\/footer\/newsletter\/ZeoBot) ==== -->\n<script>\n(function(){\n  if (window.zlPrintOnlyResult) { return; }\n  window.zlPrintOnlyResult = true;\n  var zlHidden = null;\n  function zlHide(el) {\n    if (el.tagName === 'SCRIPT') { return; }\n    if (el.tagName === 'STYLE') { return; }\n    if (el.tagName === 'LINK') { return; }\n    zlHidden.push([el, el.style.getPropertyValue('display'), el.style.getPropertyPriority('display')]);\n    el.style.setProperty('display', 'none', 'important');\n  }\n  function zlStyle(el, prop, val) {\n    zlHidden.push([el, el.style.getPropertyValue(prop), el.style.getPropertyPriority(prop), prop]);\n    el.style.setProperty(prop, val, 'important');\n  }\n  function zlPrintPrep() {\n    if (zlHidden) { return; }\n    var res = document.querySelector('.zlcalc .result.show');\n    if (!res) { return; }\n    zlHidden = [];\n    var node = res;\n    while (node.parentElement) {\n      var parent = node.parentElement;\n      var sibs = parent.children;\n      for (var i = 0; i !== sibs.length; i++) {\n        if (sibs[i] !== node) { zlHide(sibs[i]); }\n      }\n      if (parent === document.body) { break; }\n      zlStyle(parent, 'margin', '0');\n      zlStyle(parent, 'padding', '0');\n      zlStyle(parent, 'border', '0');\n      zlStyle(parent, 'box-shadow', 'none');\n      zlStyle(parent, 'max-width', 'none');\n      node = parent;\n    }\n  }\n  function zlPrintRestore() {\n    if (!zlHidden) { return; }\n    for (var i = zlHidden.length - 1; i !== -1; i--) {\n      var h = zlHidden[i];\n      var prop = h[3] ? h[3] : 'display';\n      if (h[1]) { h[0].style.setProperty(prop, h[1], h[2]); } else { h[0].style.removeProperty(prop); }\n    }\n    zlHidden = null;\n  }\n  window.addEventListener('beforeprint', zlPrintPrep);\n  window.addEventListener('afterprint', zlPrintRestore);\n  if (window.matchMedia) {\n    var mq = window.matchMedia('print');\n    var onChange = function(e) { if (e.matches) { zlPrintPrep(); } else { zlPrintRestore(); } };\n    if (mq.addEventListener) { mq.addEventListener('change', onChange); } else if (mq.addListener) { mq.addListener(onChange); }\n  }\n})();\n<\/script>\n\n\n\n<script id=\"zl-deeplink\">\n\/* zl-deeplink v2 \u00b7 Zeolife \u00b7 \u03c0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u03b1\u03c0\u03b1\u03bd\u03c4\u03ae\u03c3\u03b5\u03c9\u03bd \u03b1\u03c0\u03cc \u03c4\u03bf URL (\u03c0.\u03c7. ?crop=olive \u03ba\u03b1\u03b9 soil=light) + \u03ba\u03bf\u03c5\u03bc\u03c0\u03af \u00ab\u03a0\u03af\u03c3\u03c9 \u03c3\u03c4\u03bf \u03c0\u03c1\u03bf\u03ca\u03cc\u03bd\u00bb. \u03a7\u03c9\u03c1\u03af\u03c2 ampersand \u03c3\u03c4\u03bf\u03bd \u03ba\u03ce\u03b4\u03b9\u03ba\u03b1: \u03c4\u03bf WordPress \u03c4\u03bf\u03bd \u03bc\u03b5\u03c4\u03b1\u03c4\u03c1\u03ad\u03c0\u03b5\u03b9 \u03c3\u03b5 HTML entity. *\/\n(function () {\n  if (window.__zlDeeplink) { return; }\n  window.__zlDeeplink = 1;\n  var en = location.pathname.indexOf('\/en\/') === 0;\n  var qs;\n  try { qs = new URLSearchParams(location.search); } catch (e) { return; }\n  var SKIP = \/^(utm_[a-z_]+|from|fbclid|gclid|_ga|ref|lang)$\/;\n\n  function esc(s) {\n    if (window.CSS) { if (CSS.escape) { return CSS.escape(s); } }\n    return String(s).replace(\/[\"\\\\]\/g, function (c) { return '\\\\' + c; });\n  }\n\n  function backButton() {\n    var target = '';\n    var from = qs.get('from') || '';\n    if (\/^\\\/(en\\\/)?product\\\/[a-z0-9%\\-_.\\\/]+$\/i.test(from)) {\n      target = 'https:\/\/shop.zeolife.gr' + from;\n    } else if (\/^https:\\\/\\\/shop\\.zeolife\\.gr\\\/(en\\\/)?product\\\/\/.test(document.referrer || '')) {\n      target = document.referrer.split('#')[0];\n    }\n    if (!target) { return; }\n    var a = document.createElement('a');\n    a.href = target;\n    a.className = 'zl-back-to-product';\n    a.textContent = en ? '\u2190 Back to the product' : '\u2190 \u03a0\u03af\u03c3\u03c9 \u03c3\u03c4\u03bf \u03c0\u03c1\u03bf\u03ca\u03cc\u03bd';\n    a.setAttribute('style', 'position:fixed;left:16px;bottom:calc(16px + env(safe-area-inset-bottom,0px));z-index:99990;' +\n      'display:inline-flex;align-items:center;gap:6px;padding:11px 18px;border-radius:999px;text-decoration:none;' +\n      'background:linear-gradient(120deg,#0098d2 0%,#2a9ca0 52%,#7ba341 100%);color:#fff;' +\n      \"font:700 14px\/1.2 'Manrope',system-ui,sans-serif;box-shadow:0 12px 26px -10px rgba(0,152,210,.6)\");\n    document.body.appendChild(a);\n  }\n\n  function preselect() {\n    var pairs = [];\n    qs.forEach(function (v, k) {\n      if (SKIP.test(k)) { return; }\n      if (v === '') { return; }\n      pairs.push([k, v]);\n    });\n    if (!pairs.length) { return; }\n    var applied = 0, i = 0;\n    function next(tries) {\n      if (i >= pairs.length) { finish(); return; }\n      var k = pairs[i][0], v = pairs[i][1];\n      var el = document.querySelector('input[name=\"' + esc(k) + '\"][value=\"' + esc(v) + '\"]');\n      if (!el) {\n        if (tries < 10) { setTimeout(function () { next(tries + 1); }, 80); return; }\n      }\n      i++;\n      if (el) {\n        if (!el.checked) { el.click(); }\n        applied++;\n      }\n      setTimeout(function () { next(0); }, 80);\n    }\n    next(0);\n\n    function finish() {\n      if (!applied) { return; }\n      var steps = document.querySelectorAll('.step');\n      var target = null;\n      for (var s = 0; s < steps.length; s++) {\n        var st = steps[s];\n        if (st.offsetParent === null) { continue; }\n        if (!st.querySelector('input[type=\"radio\"]')) { continue; }\n        if (!st.querySelector('input[type=\"radio\"]:checked')) { target = st; break; }\n      }\n      if (!target) { target = document.querySelector('.actions'); }\n      if (target) {\n        var y = target.getBoundingClientRect().top + window.pageYOffset - 110;\n        window.scrollTo({ top: Math.max(0, y), behavior: 'smooth' });\n      }\n    }\n  }\n\n  function start() { backButton(); setTimeout(preselect, 150); }\n  if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', start); } else { start(); }\n})();\n<\/script>\n\n<!-- ==== ZL STEPPER: \u03ba\u03bf\u03c5\u03bc\u03c0\u03b9\u03ac \u2212 \/ + \u03c3\u03c4\u03b1 \u03b1\u03c1\u03b9\u03b8\u03bc\u03b7\u03c4\u03b9\u03ba\u03ac \u03c0\u03b5\u03b4\u03af\u03b1, \u03c7\u03c9\u03c1\u03af\u03c2 \u03b1\u03bb\u03bb\u03b1\u03b3\u03ae \u03c4\u03b9\u03bc\u03ae\u03c2 \u03bc\u03b5 \u03c4\u03b7 \u03c1\u03bf\u03b4\u03ad\u03bb\u03b1 \u03c4\u03bf\u03c5 \u03c0\u03bf\u03bd\u03c4\u03b9\u03ba\u03b9\u03bf\u03cd ==== -->\n<script>\n(function () {\n  if (window.zlStepperInit) { return; }\n  window.zlStepperInit = 1;\n  var EN = String(document.documentElement.lang || '').indexOf('en') === 0;\n  function toNum(v) { var n = parseFloat(String(v === null ? '' : v).replace(',', '.')); return isNaN(n) ? null : n; }\n  function decs(n) { var p = String(n).split('.'); return p[1] ? p[1].length : 0; }\n  function fire(el) {\n    ['input', 'change'].forEach(function (t) {\n      var ev;\n      try { ev = new Event(t, { bubbles: true }); } catch (x) { ev = document.createEvent('Event'); ev.initEvent(t, true, true); }\n      el.dispatchEvent(ev);\n    });\n  }\n  function bump(inp, dir) {\n    if (inp.disabled) { return; }\n    if (inp.readOnly) { return; }\n    var st = toNum(inp.getAttribute('data-zl-step'));\n    if (!st) { st = toNum(inp.step); }\n    if (!st) { st = 1; }\n    var mn = toNum(inp.getAttribute('min'));\n    var mx = toNum(inp.getAttribute('max'));\n    var cur = toNum(inp.value);\n    var v;\n    if (cur === null) {\n      v = dir > 0 ? st : 0;\n      if (mn !== null) { v = Math.max(v, mn); }\n    } else {\n      var k = cur \/ st;\n      var kr = Math.round(k);\n      if (Math.abs(k - kr) > 1e-9) { k = dir > 0 ? Math.floor(k) : Math.ceil(k); } else { k = kr; }\n      v = (k + dir) * st;\n    }\n    if (mn !== null) { v = Math.max(v, mn); }\n    if (mx !== null) { v = Math.min(v, mx); }\n    v = parseFloat(v.toFixed(Math.min(6, decs(st))));\n    inp.value = String(v);\n    fire(inp);\n  }\n  function wrap(inp) {\n    if (inp.getAttribute('data-zl-stepper')) { return; }\n    if (inp.type !== 'number') { return; }\n    inp.setAttribute('data-zl-stepper', '1');\n    var st = toNum(inp.getAttribute('data-zl-step')) || toNum(inp.step) || 1;\n    if (!inp.getAttribute('inputmode')) { inp.setAttribute('inputmode', decs(st) ? 'decimal' : 'numeric'); }\n    var box = document.createElement('span');\n    box.className = 'zl-step';\n    var minus = document.createElement('button');\n    minus.type = 'button'; minus.className = 'zl-step-btn'; minus.textContent = '\u2212';\n    minus.setAttribute('aria-label', EN ? 'Decrease' : '\u039b\u03b9\u03b3\u03cc\u03c4\u03b5\u03c1\u03bf');\n    var plus = document.createElement('button');\n    plus.type = 'button'; plus.className = 'zl-step-btn'; plus.textContent = '+';\n    plus.setAttribute('aria-label', EN ? 'Increase' : '\u03a0\u03b5\u03c1\u03b9\u03c3\u03c3\u03cc\u03c4\u03b5\u03c1\u03bf');\n    inp.parentNode.insertBefore(box, inp);\n    box.appendChild(minus);\n    box.appendChild(inp);\n    var ph = inp.getAttribute('placeholder') || '';\n    if (ph.length > 8) { var w = Math.min(ph.length + 2, 22) + 'ch'; inp.style.setProperty('width', w, 'important'); inp.style.setProperty('flex-basis', w, 'important'); }\n    var u = inp.getAttribute('data-unit');\n    if (u) { var us = document.createElement('span'); us.className = 'zl-step-unit'; us.textContent = u; box.appendChild(us); }\n    box.appendChild(plus);\n    minus.addEventListener('click', function () { bump(inp, -1); });\n    plus.addEventListener('click', function () { bump(inp, 1); });\n    inp.addEventListener('wheel', function () { if (document.activeElement === inp) { inp.blur(); } }, { passive: true });\n  }\n  function scan(root) {\n    var list = root.querySelectorAll('input[type=\"number\"]');\n    for (var i = 0; i !== list.length; i++) { wrap(list[i]); }\n  }\n  function init() {\n    var roots = document.querySelectorAll('.zlcalc');\n    for (var i = 0; i !== roots.length; i++) {\n      (function (r) {\n        scan(r);\n        if (window.MutationObserver) { new MutationObserver(function () { scan(r); }).observe(r, { childList: true, subtree: true }); }\n      })(roots[i]);\n    }\n  }\n  if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); }\n})();\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>\ud83c\udf3e Zeolite Dosage Guide for Agricultural Use Give us 5 pieces of information and we&#8217;ll recommend the right product from our 3 ranges (Greek Thracian, IMERYS, ZeoGravel\u00ae ZEOCEM) with exact dosage, a 3-year programme and automatic discount calculation. \ud83d\udccb 5-step guide 15 crops 3 brands \u00d7 9 products 3-year programme Auto-discount up to 40% 1Choose&#8230;<\/p>\n","protected":false},"author":7,"featured_media":13886,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"content-type":"","_kad_blocks_custom_css":"","_kad_blocks_head_custom_js":"","_kad_blocks_body_custom_js":"","_kad_blocks_footer_custom_js":"","_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"hide","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"class_list":["post-17926","page","type-page","status-publish","has-post-thumbnail","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Zeolite Agricultural Dosage Guide<\/title>\n<meta name=\"description\" content=\"Interactive dosage guide for agricultural zeolite use: olive trees, vineyard, walnut, fruit trees, cereals, lawn, ornamentals.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Zeolite Agricultural Dosage Guide\" \/>\n<meta property=\"og:description\" content=\"Interactive dosage guide for agricultural zeolite use: olive trees, vineyard, walnut, fruit trees, cereals, lawn, ornamentals.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/\" \/>\n<meta property=\"og:site_name\" content=\"Greek Zeolite, Zeolite products and industrial minerals | Zeolife.gr\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/zeolifegr\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-20T17:50:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/zeolife.gr\/wp-content\/uploads\/2014\/11\/amp-header-buy-zeolite-zeolifegr-600x413px.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"600\" \/>\n\t<meta property=\"og:image:height\" content=\"413\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:site\" content=\"@ZeolifeGr\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/zeolite-agriculture-dosage-calculator\\\/\",\"url\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/zeolite-agriculture-dosage-calculator\\\/\",\"name\":\"Zeolite Agricultural Dosage Calculator\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/zeolite-agriculture-dosage-calculator\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/zeolite-agriculture-dosage-calculator\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/zeolife.gr\\\/wp-content\\\/uploads\\\/2014\\\/11\\\/amp-header-buy-zeolite-zeolifegr-600x413px.jpg\",\"datePublished\":\"2026-06-09T15:18:51+00:00\",\"dateModified\":\"2026-10-20T17:50:38+00:00\",\"description\":\"Interactive dosage calculator for agricultural zeolite use: olive trees, vineyard, walnut, fruit trees, cereals, lawn, ornamentals.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/zeolite-agriculture-dosage-calculator\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/zeolife.gr\\\/en\\\/zeolite-agriculture-dosage-calculator\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/zeolite-agriculture-dosage-calculator\\\/#primaryimage\",\"url\":\"https:\\\/\\\/zeolife.gr\\\/wp-content\\\/uploads\\\/2014\\\/11\\\/amp-header-buy-zeolite-zeolifegr-600x413px.jpg\",\"contentUrl\":\"https:\\\/\\\/zeolife.gr\\\/wp-content\\\/uploads\\\/2014\\\/11\\\/amp-header-buy-zeolite-zeolifegr-600x413px.jpg\",\"width\":600,\"height\":413},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/zeolite-agriculture-dosage-calculator\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Zeolite Agricultural Dosage Guide\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/\",\"name\":\"Greek Zeolite & Industrial Minerals \u2013 Applications & Information | Zeolife.gr\",\"description\":\"Applications and purchase of Greek zeolite, zeolite products and industrial minerals | Zeolife.gr\",\"publisher\":{\"@id\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/#organization\"},\"alternateName\":\"Greek Zeolite: Properties, Uses & Products | Zeolife.gr\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/#organization\",\"name\":\"Zeolite | Diatomite | Zeolife.gr\",\"alternateName\":\"Zeolife.gr\",\"url\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/zeolife.gr\\\/wp-content\\\/uploads\\\/2019\\\/11\\\/icon-color-square.png\",\"contentUrl\":\"https:\\\/\\\/zeolife.gr\\\/wp-content\\\/uploads\\\/2019\\\/11\\\/icon-color-square.png\",\"width\":1200,\"height\":1200,\"caption\":\"Zeolite | Diatomite | Zeolife.gr\"},\"image\":{\"@id\":\"https:\\\/\\\/zeolife.gr\\\/en\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/zeolifegr\",\"https:\\\/\\\/x.com\\\/ZeolifeGr\",\"https:\\\/\\\/www.instagram.com\\\/zeolife.gr\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/zeolifegr\",\"https:\\\/\\\/www.pinterest.com\\\/zeolifegr\\\/\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UCUR1v-vb6vutCU3uvnu98WQ\",\"https:\\\/\\\/zeolifegr.tumblr.com\\\/\",\"https:\\\/\\\/www.tiktok.com\\\/@zeolifegr\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Zeolite Agricultural Dosage Guide","description":"Interactive dosage guide for agricultural zeolite use: olive trees, vineyard, walnut, fruit trees, cereals, lawn, ornamentals.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/","og_locale":"en_US","og_type":"article","og_title":"Zeolite Agricultural Dosage Guide","og_description":"Interactive dosage guide for agricultural zeolite use: olive trees, vineyard, walnut, fruit trees, cereals, lawn, ornamentals.","og_url":"https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/","og_site_name":"Greek Zeolite, Zeolite products and industrial minerals | Zeolife.gr","article_publisher":"https:\/\/www.facebook.com\/zeolifegr","article_modified_time":"2026-10-20T17:50:38+00:00","og_image":[{"width":600,"height":413,"url":"https:\/\/zeolife.gr\/wp-content\/uploads\/2014\/11\/amp-header-buy-zeolite-zeolifegr-600x413px.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_site":"@ZeolifeGr","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/","url":"https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/","name":"Zeolite Agricultural Dosage Calculator","isPartOf":{"@id":"https:\/\/zeolife.gr\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/#primaryimage"},"image":{"@id":"https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/#primaryimage"},"thumbnailUrl":"https:\/\/zeolife.gr\/wp-content\/uploads\/2014\/11\/amp-header-buy-zeolite-zeolifegr-600x413px.jpg","datePublished":"2026-06-09T15:18:51+00:00","dateModified":"2026-10-20T17:50:38+00:00","description":"Interactive dosage calculator for agricultural zeolite use: olive trees, vineyard, walnut, fruit trees, cereals, lawn, ornamentals.","breadcrumb":{"@id":"https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/#primaryimage","url":"https:\/\/zeolife.gr\/wp-content\/uploads\/2014\/11\/amp-header-buy-zeolite-zeolifegr-600x413px.jpg","contentUrl":"https:\/\/zeolife.gr\/wp-content\/uploads\/2014\/11\/amp-header-buy-zeolite-zeolifegr-600x413px.jpg","width":600,"height":413},{"@type":"BreadcrumbList","@id":"https:\/\/zeolife.gr\/en\/zeolite-agriculture-dosage-calculator\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/zeolife.gr\/en\/"},{"@type":"ListItem","position":2,"name":"Zeolite Agricultural Dosage Guide"}]},{"@type":"WebSite","@id":"https:\/\/zeolife.gr\/en\/#website","url":"https:\/\/zeolife.gr\/en\/","name":"Greek Zeolite & Industrial Minerals \u2013 Applications & Information | Zeolife.gr","description":"Applications and purchase of Greek zeolite, zeolite products and industrial minerals | Zeolife.gr","publisher":{"@id":"https:\/\/zeolife.gr\/en\/#organization"},"alternateName":"Greek Zeolite: Properties, Uses & Products | Zeolife.gr","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/zeolife.gr\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/zeolife.gr\/en\/#organization","name":"Zeolite | Diatomite | Zeolife.gr","alternateName":"Zeolife.gr","url":"https:\/\/zeolife.gr\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/zeolife.gr\/en\/#\/schema\/logo\/image\/","url":"https:\/\/zeolife.gr\/wp-content\/uploads\/2019\/11\/icon-color-square.png","contentUrl":"https:\/\/zeolife.gr\/wp-content\/uploads\/2019\/11\/icon-color-square.png","width":1200,"height":1200,"caption":"Zeolite | Diatomite | Zeolife.gr"},"image":{"@id":"https:\/\/zeolife.gr\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/zeolifegr","https:\/\/x.com\/ZeolifeGr","https:\/\/www.instagram.com\/zeolife.gr\/","https:\/\/www.linkedin.com\/in\/zeolifegr","https:\/\/www.pinterest.com\/zeolifegr\/","https:\/\/www.youtube.com\/channel\/UCUR1v-vb6vutCU3uvnu98WQ","https:\/\/zeolifegr.tumblr.com\/","https:\/\/www.tiktok.com\/@zeolifegr"]}]}},"taxonomy_info":[],"featured_image_src_large":["https:\/\/zeolife.gr\/wp-content\/uploads\/2014\/11\/amp-header-buy-zeolite-zeolifegr-600x413px.jpg",600,413,false],"author_info":{"display_name":"Chrysovalantis Chatzigeorgiou","author_link":"https:\/\/zeolife.gr\/en\/author\/valantis\/"},"comment_info":0,"_links":{"self":[{"href":"https:\/\/zeolife.gr\/en\/wp-json\/wp\/v2\/pages\/17926","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zeolife.gr\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/zeolife.gr\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/zeolife.gr\/en\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/zeolife.gr\/en\/wp-json\/wp\/v2\/comments?post=17926"}],"version-history":[{"count":14,"href":"https:\/\/zeolife.gr\/en\/wp-json\/wp\/v2\/pages\/17926\/revisions"}],"predecessor-version":[{"id":20791,"href":"https:\/\/zeolife.gr\/en\/wp-json\/wp\/v2\/pages\/17926\/revisions\/20791"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/zeolife.gr\/en\/wp-json\/wp\/v2\/media\/13886"}],"wp:attachment":[{"href":"https:\/\/zeolife.gr\/en\/wp-json\/wp\/v2\/media?parent=17926"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}