{
  "data": {
    "slug": "16c488d0",
    "url": "https://eponeshop.sk",
    "domain": "eponeshop.sk",
    "overall_score": 75,
    "scores_json": {
      "seo": {
        "score": 89,
        "checks": [
          {
            "i18n": {
              "key": "seo.meta-title.pass",
              "params": {
                "chars": 31,
                "title": "Vitajte v eshope - Eponeshop.sk"
              }
            },
            "name": "Meta Title",
            "value": "31 chars — \"Vitajte v eshope - Eponeshop.sk\"",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.meta-desc.warning-short",
              "params": {
                "chars": 77
              }
            },
            "name": "Meta Description",
            "value": "77 chars (optimal: 120-160)",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Expand your description to at least 120 characters. Include benefits, a CTA, and your target keyword.",
            "whyMatters": "Short descriptions waste SERP real estate and miss the chance to persuade searchers to click."
          },
          {
            "i18n": {
              "key": "seo.h1.pass",
              "params": {
                "text": "Vitajte v eshope"
              }
            },
            "name": "H1 Heading",
            "value": "\"Vitajte v eshope\"",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.h2.pass",
              "params": {
                "count": 6
              }
            },
            "name": "Content Structure (H2 Headings)",
            "value": "6 H2 subheadings found",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.og.pass",
              "params": {
                "tags": "og:title, og:description, og:image, og:type"
              }
            },
            "name": "Open Graph Tags",
            "value": "og:title, og:description, og:image, og:type",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.og-format.pass",
              "params": {
                "contentType": "image/png"
              }
            },
            "name": "Open Graph Image Format",
            "value": "image/png",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.twitter.warning"
            },
            "name": "Twitter/X Cards",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add <meta name='twitter:card' content='summary_large_image'>, twitter:title, and twitter:image tags.",
            "whyMatters": "Twitter Cards make your links stand out in X/Twitter feeds. Without them, shared links appear as plain text URLs."
          },
          {
            "i18n": {
              "key": "seo.canonical.pass",
              "params": {
                "url": "https://www.eponeshop.sk/"
              }
            },
            "name": "Canonical URL",
            "value": "https://www.eponeshop.sk/",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.jsonld.pass",
              "params": {
                "count": 1,
                "types": "Organization"
              }
            },
            "name": "Structured Data (JSON-LD)",
            "value": "1 block(s): Organization",
            "status": "pass",
            "evidence": {
              "source": "schema"
            }
          },
          {
            "i18n": {
              "key": "seo.jsonld-valid.pass",
              "params": {
                "count": 1
              }
            },
            "name": "JSON-LD Validity",
            "value": "1 block(s) parse cleanly",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.robots.pass-sitemap"
            },
            "name": "robots.txt",
            "value": "Present, references sitemap",
            "status": "pass",
            "evidence": {
              "source": "file-probe"
            }
          },
          {
            "i18n": {
              "key": "seo.sitemap.pass-count",
              "params": {
                "count": 27
              }
            },
            "name": "XML Sitemap",
            "value": "Found with 27 URLs",
            "status": "pass",
            "evidence": {
              "source": "file-probe"
            }
          },
          {
            "i18n": {
              "key": "seo.html-lang.pass",
              "params": {
                "lang": "sk"
              }
            },
            "name": "HTML Language Attribute",
            "value": "lang=\"sk\"",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.img-alt.pass",
              "params": {
                "rate": 100,
                "total": 4
              }
            },
            "name": "Image Alt Attributes",
            "value": "100% of 4 images have alt text",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.meta-robots.pass",
              "params": {
                "value": "index,follow"
              }
            },
            "name": "Meta Robots Tag",
            "value": "index,follow",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.text-ratio.warning",
              "params": {
                "ratio": 4,
                "words": 304
              }
            },
            "name": "Text-to-HTML Ratio",
            "value": "4% — low content density (304 words)",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add more unique text content, and move inline <script>/<style>/SVG to external files to lift the ratio. Block-builder markup (Gutenberg/Elementor) inflates HTML size — most of this is markup weight, not a content gap.",
            "whyMatters": "A low text-to-HTML ratio can signal thin content, but with a reasonable word count it usually just means bulky template markup. Focus on real content depth first."
          },
          {
            "i18n": {
              "key": "seo.favicon.pass"
            },
            "name": "Favicon",
            "value": "Favicon detected",
            "status": "pass",
            "evidence": {
              "source": "file-probe"
            }
          },
          {
            "i18n": {
              "key": "seo.img-format.warning-none",
              "params": {
                "jpg": 0,
                "png": 1
              }
            },
            "name": "Image Format Optimization",
            "value": "0% next-gen formats — 0 JPEG, 1 PNG images",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Convert all images to WebP format. Most CMS platforms have plugins for automatic WebP conversion. Use AVIF for even better compression.",
            "whyMatters": "Your images use legacy formats only. Switching to WebP typically reduces page weight by 30-50% — one of the highest-impact performance optimizations."
          },
          {
            "i18n": {
              "key": "seo.semantic.pass",
              "params": {
                "used": "<nav>, <main>, <header>, <footer>, <aside>",
                "count": 5
              }
            },
            "name": "Semantic HTML Structure",
            "value": "5/6 semantic elements: <nav>, <main>, <header>, <footer>, <aside>",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.canonical-consistency.warning",
              "params": {
                "url": "https://www.eponeshop.sk/"
              }
            },
            "name": "Canonical URL Consistency",
            "value": "Canonical points to different URL: https://www.eponeshop.sk/",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Your canonical URL doesn't match the current page URL. Ensure the canonical points to the preferred version (with or without trailing slash, www vs non-www). Inconsistent canonicals confuse search engines.",
            "whyMatters": "A mismatched canonical tells Google this page is a duplicate of another URL. If unintentional, Google may ignore this page entirely in favor of the canonical target."
          },
          {
            "i18n": {
              "key": "seo.content-depth.pass",
              "params": {
                "words": 304
              }
            },
            "name": "Content Depth",
            "value": "304 words — sufficient content",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.deep-heading.pass",
              "params": {
                "h2": 6,
                "h3": 10
              }
            },
            "name": "Deep Heading Hierarchy",
            "value": "H2: 6, H3: 10 — well-structured content",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.internal-links.warning",
              "params": {
                "count": 6,
                "threshold": 10
              }
            },
            "name": "Internal Linking",
            "value": "Only 6 internal links",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add more internal links to related content. Target 10+ internal links per page for strong site crawlability.",
            "whyMatters": "Internal links help Google discover and rank your pages. Pages with more internal links receive higher PageRank and are crawled more frequently."
          },
          {
            "i18n": {
              "key": "seo.dead-links.pass",
              "params": {
                "total": 4
              }
            },
            "name": "Empty/Dead Links",
            "value": "4 minor dead link(s) — acceptable",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "seo.a11y.pass",
              "params": {
                "detail": "79 ARIA roles, 7 ARIA labels, skip link, lang=\"sk\"",
                "signals": 4
              }
            },
            "name": "Accessibility Fundamentals",
            "value": "4/4 a11y signals: 79 ARIA roles, 7 ARIA labels, skip link, lang=\"sk\"",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          }
        ]
      },
      "gdpr": {
        "score": 64,
        "checks": [
          {
            "i18n": {
              "key": "gdpr.cmp.pass",
              "params": {
                "provider": "Cookiebot"
              }
            },
            "name": "Cookie Consent Banner (CMP)",
            "value": "Cookiebot detected",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "legalRefs": {
              "gdpr": [
                "Art. 6(1)(a)",
                "Art. 7"
              ],
              "skLaw": [
                "§ 14"
              ],
              "verified": [
                {
                  "title": "Zákonnosť spracúvania",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 6 — Zákonnosť spracúvania 1. Spracúvanie je zákonné iba vtedy a iba v tom rozsahu, keď je splnená aspoň jedna z týchto podmienok: Písmeno f) prvého pododseku sa nevzťahuje na spracúvanie vykonávané orgánmi verejnej moci pri výkone i",
                  "citation": "čl. 6 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "title": "Podmienky vyjadrenia súhlasu",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 7 — Podmienky vyjadrenia súhlasu 1. Ak je spracúvanie založené na súhlase, prevádzkovateľ musí vedieť preukázať, že dotknutá osoba vyjadrila súhlas so spracúvaním svojich osobných údajov. 2. Ak dá dotknutá osoba súhlas v rámci písom",
                  "citation": "čl. 7 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "act": "18/2018",
                  "title": "Podmienky poskytnutia súhlasu so spracúvaním osobných údajov",
                  "excerpt": "§ 14 Podmienky poskytnutia súhlasu so spracúvaním osobných údajov (1) Ak je spracúvanie osobných údajov založené na súhlase dotknutej osoby, prevádzkovateľ je povinný kedykoľvek vedieť preukázať, že dotknutá osoba poskytla súhlas so spracúv",
                  "citation": "§14 zákona č. 18/2018 Z.z.",
                  "jurisdiction": "sk"
                }
              ]
            }
          },
          {
            "i18n": {
              "key": "gdpr.tracking.pass-none"
            },
            "name": "Tracking Scripts & Consent",
            "value": "No tracking scripts detected",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "legalRefs": {
              "gdpr": [
                "Art. 6(1)(a)",
                "Art. 7",
                "EDPB Opinion 5/2019"
              ],
              "skLaw": [
                "§ 14"
              ],
              "verified": [
                {
                  "title": "Zákonnosť spracúvania",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 6 — Zákonnosť spracúvania 1. Spracúvanie je zákonné iba vtedy a iba v tom rozsahu, keď je splnená aspoň jedna z týchto podmienok: Písmeno f) prvého pododseku sa nevzťahuje na spracúvanie vykonávané orgánmi verejnej moci pri výkone i",
                  "citation": "čl. 6 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "title": "Podmienky vyjadrenia súhlasu",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 7 — Podmienky vyjadrenia súhlasu 1. Ak je spracúvanie založené na súhlase, prevádzkovateľ musí vedieť preukázať, že dotknutá osoba vyjadrila súhlas so spracúvaním svojich osobných údajov. 2. Ak dá dotknutá osoba súhlas v rámci písom",
                  "citation": "čl. 7 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "act": "18/2018",
                  "title": "Podmienky poskytnutia súhlasu so spracúvaním osobných údajov",
                  "excerpt": "§ 14 Podmienky poskytnutia súhlasu so spracúvaním osobných údajov (1) Ak je spracúvanie osobných údajov založené na súhlase dotknutej osoby, prevádzkovateľ je povinný kedykoľvek vedieť preukázať, že dotknutá osoba poskytla súhlas so spracúv",
                  "citation": "§14 zákona č. 18/2018 Z.z.",
                  "jurisdiction": "sk"
                }
              ]
            }
          },
          {
            "i18n": {
              "key": "gdpr.privacy-policy.fail"
            },
            "name": "Privacy Policy Page",
            "status": "fail",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Create a comprehensive privacy policy covering: what data you collect, why (legal basis), how long you store it, who you share it with, and how users can exercise their GDPR rights (access, deletion, portability).",
            "legalRefs": {
              "gdpr": [
                "Art. 12",
                "Art. 13",
                "Art. 14"
              ],
              "skLaw": [
                "§ 19",
                "§ 20"
              ],
              "verified": [
                {
                  "title": "Transparentnosť informácií, oznámenia a postupy výkonu práv dotknutej osoby",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 12 — Transparentnosť informácií, oznámenia a postupy výkonu práv dotknutej osoby 3. Prevádzkovateľ poskytne dotknutej osobe informácie o opatreniach, ktoré sa prijali na základe žiadosti podľa článkov 15 až 22, bez zbytočného odklad",
                  "citation": "čl. 12 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "title": "Informácie, ktoré sa majú poskytovať pri získavaní osobných údajov od dotknutej osoby",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 13 — Informácie, ktoré sa majú poskytovať pri získavaní osobných údajov od dotknutej osoby 2. Okrem informácií, ktoré sa uvádzajú v odseku 1, prevádzkovateľ poskytne dotknutej osobe pri získavaní osobných údajov tieto ďalšie informá",
                  "citation": "čl. 13 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "title": "Informácie, ktoré sa majú poskytnúť, ak osobné údaje neboli získané od dotknutej osoby",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 14 — Informácie, ktoré sa majú poskytnúť, ak osobné údaje neboli získané od dotknutej osoby 2. Okrem informácií uvedených v odseku 1 prevádzkovateľ poskytne dotknutej osobe tieto ďalšie informácie potrebné na zabezpečenie spravodliv",
                  "citation": "čl. 14 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "act": "18/2018",
                  "title": "Poskytované informácie, ak osobné údaje sú získané od dotknutej osoby",
                  "excerpt": "§ 19 Poskytované informácie, ak osobné údaje sú získané od dotknutej osoby (4) Odseky 1 až 3 sa neuplatňujú v rozsahu, v akom boli informácie dotknutej osobe poskytnuté pred spracúvaním osobných údajov.",
                  "citation": "§19 ods. 4 zákona č. 18/2018 Z.z.",
                  "jurisdiction": "sk"
                },
                {
                  "act": "18/2018",
                  "title": "Poskytované informácie, ak osobné údaje nie sú získané od dotknutej osoby",
                  "excerpt": "§ 20 Poskytované informácie, ak osobné údaje nie sú získané od dotknutej osoby (5) d) ak osobné údaje musia zostať dôverné na základe povinnosti mlčanlivosti podľa osobitného predpisu. 15 )",
                  "citation": "§20 ods. 5 písm. d) zákona č. 18/2018 Z.z.",
                  "jurisdiction": "sk"
                }
              ]
            },
            "whyMatters": "A missing privacy policy is one of the most frequently cited GDPR violations. Every EU data protection authority considers it a basic requirement."
          },
          {
            "i18n": {
              "key": "gdpr.cookie-policy.warning"
            },
            "name": "Cookie Policy",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Create a separate cookie policy page listing every cookie by: name, provider, purpose, category (necessary/analytics/marketing), and expiration. Most CMPs auto-generate this.",
            "legalRefs": {
              "gdpr": [
                "Art. 12",
                "Art. 13(1)(c)-(e)"
              ],
              "skLaw": [
                "§ 19"
              ],
              "verified": [
                {
                  "title": "Transparentnosť informácií, oznámenia a postupy výkonu práv dotknutej osoby",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 12 — Transparentnosť informácií, oznámenia a postupy výkonu práv dotknutej osoby 3. Prevádzkovateľ poskytne dotknutej osobe informácie o opatreniach, ktoré sa prijali na základe žiadosti podľa článkov 15 až 22, bez zbytočného odklad",
                  "citation": "čl. 12 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "title": "Informácie, ktoré sa majú poskytovať pri získavaní osobných údajov od dotknutej osoby",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 13 — Informácie, ktoré sa majú poskytovať pri získavaní osobných údajov od dotknutej osoby 2. Okrem informácií, ktoré sa uvádzajú v odseku 1, prevádzkovateľ poskytne dotknutej osobe pri získavaní osobných údajov tieto ďalšie informá",
                  "citation": "čl. 13 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "act": "18/2018",
                  "title": "Poskytované informácie, ak osobné údaje sú získané od dotknutej osoby",
                  "excerpt": "§ 19 Poskytované informácie, ak osobné údaje sú získané od dotknutej osoby (4) Odseky 1 až 3 sa neuplatňujú v rozsahu, v akom boli informácie dotknutej osobe poskytnuté pred spracúvaním osobných údajov.",
                  "citation": "§19 ods. 4 zákona č. 18/2018 Z.z.",
                  "jurisdiction": "sk"
                }
              ]
            },
            "whyMatters": "The ePrivacy Directive requires transparent cookie disclosure. Vague statements like 'we use cookies for functionality' don't meet the specificity requirement."
          },
          {
            "i18n": {
              "key": "gdpr.imprint.warning"
            },
            "name": "Legal Contact / Imprint Page",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add an imprint/about-us page with: company name, registered address, contact email, VAT number, and trade register info. In Germany/Austria/Switzerland this is legally required (Impressumspflicht).",
            "whyMatters": "In DACH countries, a missing Impressum can trigger fines and competitor cease-and-desist letters. For all EU stores, identifying the data controller is a GDPR Article 13 requirement."
          },
          {
            "i18n": {
              "key": "gdpr.terms.pass",
              "params": {
                "url": "/obchodne-podmienky/"
              }
            },
            "name": "Terms & Conditions Page",
            "value": "/obchodne-podmienky/",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "gdpr.mixed-content.pass"
            },
            "name": "Data Encryption (No Mixed Content)",
            "value": "All resources loaded over HTTPS",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "gdpr.third-party.pass",
              "params": {
                "count": 2
              }
            },
            "name": "Third-party Data Sharing",
            "value": "2 third-party domain(s)",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "gdpr.forms.warning",
              "params": {
                "count": 5
              }
            },
            "name": "Forms Without Privacy Notice",
            "value": "5 form(s) on page with no privacy policy link",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add a link to your privacy policy next to or below every form that collects personal data (contact, registration, newsletter). Include a checkbox for consent where required.",
            "legalRefs": {
              "gdpr": [
                "Art. 13",
                "Art. 14"
              ],
              "skLaw": [
                "§ 19",
                "§ 20"
              ],
              "verified": [
                {
                  "title": "Informácie, ktoré sa majú poskytovať pri získavaní osobných údajov od dotknutej osoby",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 13 — Informácie, ktoré sa majú poskytovať pri získavaní osobných údajov od dotknutej osoby 2. Okrem informácií, ktoré sa uvádzajú v odseku 1, prevádzkovateľ poskytne dotknutej osobe pri získavaní osobných údajov tieto ďalšie informá",
                  "citation": "čl. 13 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "title": "Informácie, ktoré sa majú poskytnúť, ak osobné údaje neboli získané od dotknutej osoby",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 14 — Informácie, ktoré sa majú poskytnúť, ak osobné údaje neboli získané od dotknutej osoby 2. Okrem informácií uvedených v odseku 1 prevádzkovateľ poskytne dotknutej osobe tieto ďalšie informácie potrebné na zabezpečenie spravodliv",
                  "citation": "čl. 14 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "act": "18/2018",
                  "title": "Poskytované informácie, ak osobné údaje sú získané od dotknutej osoby",
                  "excerpt": "§ 19 Poskytované informácie, ak osobné údaje sú získané od dotknutej osoby (4) Odseky 1 až 3 sa neuplatňujú v rozsahu, v akom boli informácie dotknutej osobe poskytnuté pred spracúvaním osobných údajov.",
                  "citation": "§19 ods. 4 zákona č. 18/2018 Z.z.",
                  "jurisdiction": "sk"
                },
                {
                  "act": "18/2018",
                  "title": "Poskytované informácie, ak osobné údaje nie sú získané od dotknutej osoby",
                  "excerpt": "§ 20 Poskytované informácie, ak osobné údaje nie sú získané od dotknutej osoby (5) d) ak osobné údaje musia zostať dôverné na základe povinnosti mlčanlivosti podľa osobitného predpisu. 15 )",
                  "citation": "§20 ods. 5 písm. d) zákona č. 18/2018 Z.z.",
                  "jurisdiction": "sk"
                }
              ]
            },
            "whyMatters": "GDPR Article 13 requires informing users about data processing at the point of collection. Forms without privacy notices violate the transparency principle."
          },
          {
            "i18n": {
              "key": "gdpr.erasure.warning"
            },
            "name": "Right to Erasure (Data Deletion)",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Provide a clear mechanism for users to request data deletion — either a dedicated page, a form, or explicit instructions in your privacy policy. Include a 'Delete my account' option in user settings.",
            "legalRefs": {
              "gdpr": [
                "Art. 17"
              ],
              "skLaw": [
                "§ 23"
              ],
              "verified": [
                {
                  "title": "Právo na vymazanie (právo „na zabudnutie“)",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 17 — Právo na vymazanie (právo „na zabudnutie“) 1. Dotknutá osoba má tiež právo dosiahnuť u prevádzkovateľa bez zbytočného odkladu vymazanie osobných údajov, ktoré sa jej týkajú, a prevádzkovateľ je povinný bez zbytočného odkladu vy",
                  "citation": "čl. 17 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "act": "18/2018",
                  "title": "Právo na výmaz osobných údajov",
                  "excerpt": "§ 23 Právo na výmaz osobných údajov (1) Dotknutá osoba má právo na to, aby prevádzkovateľ bez zbytočného odkladu vymazal osobné údaje, ktoré sa jej týkajú.",
                  "citation": "§23 ods. 1 zákona č. 18/2018 Z.z.",
                  "jurisdiction": "sk"
                }
              ]
            },
            "whyMatters": "GDPR Article 17 gives users the 'right to be forgotten.' EU regulators expect a clear, accessible process, and obstructing erasure requests is a documented enforcement finding."
          },
          {
            "i18n": {
              "key": "gdpr.newsletter.pass"
            },
            "name": "Newsletter Consent",
            "value": "Newsletter form with consent mechanism detected",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "legalRefs": {
              "gdpr": [
                "Art. 6(1)(a)",
                "Art. 7",
                "ePrivacy Art. 13"
              ],
              "skLaw": [
                "§ 14",
                "§ 109 zák. 452/2021"
              ],
              "verified": [
                {
                  "title": "Zákonnosť spracúvania",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 6 — Zákonnosť spracúvania 1. Spracúvanie je zákonné iba vtedy a iba v tom rozsahu, keď je splnená aspoň jedna z týchto podmienok: Písmeno f) prvého pododseku sa nevzťahuje na spracúvanie vykonávané orgánmi verejnej moci pri výkone i",
                  "citation": "čl. 6 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "title": "Podmienky vyjadrenia súhlasu",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 7 — Podmienky vyjadrenia súhlasu 1. Ak je spracúvanie založené na súhlase, prevádzkovateľ musí vedieť preukázať, že dotknutá osoba vyjadrila súhlas so spracúvaním svojich osobných údajov. 2. Ak dá dotknutá osoba súhlas v rámci písom",
                  "citation": "čl. 7 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "act": "18/2018",
                  "title": "Podmienky poskytnutia súhlasu so spracúvaním osobných údajov",
                  "excerpt": "§ 14 Podmienky poskytnutia súhlasu so spracúvaním osobných údajov (1) Ak je spracúvanie osobných údajov založené na súhlase dotknutej osoby, prevádzkovateľ je povinný kedykoľvek vedieť preukázať, že dotknutá osoba poskytla súhlas so spracúv",
                  "citation": "§14 zákona č. 18/2018 Z.z.",
                  "jurisdiction": "sk"
                },
                {
                  "act": "452/2021",
                  "title": "—",
                  "excerpt": "§ 109 — (8) Každý, kto ukladá alebo získava prístup k informáciám uloženým v koncovom zariadení užívateľa, je na to oprávnený iba ak užívateľ udelil preukázateľný súhlas spĺňajúci náležitosti podľa osobitného predpisu. 126 ) Povinnosť získa",
                  "citation": "§109 ods. 8 zákona č. 452/2021 Z.z.",
                  "jurisdiction": "sk"
                }
              ]
            }
          },
          {
            "i18n": {
              "key": "gdpr.dpo.pass"
            },
            "name": "Data Protection Officer Contact",
            "value": "DPO / data protection contact found",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "gdpr.withdrawal.warning"
            },
            "name": "Withdrawal of Consent Mechanism",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Provide a clear way to withdraw consent: an 'unsubscribe' link in emails, a 'cookie settings' button in the footer, and a 'revoke consent' section in your privacy policy.",
            "legalRefs": {
              "gdpr": [
                "Art. 7(3)"
              ],
              "skLaw": [
                "§ 14(4)"
              ],
              "verified": [
                {
                  "title": "Podmienky vyjadrenia súhlasu",
                  "source": "Zdroj: EUR-Lex (eur-lex.europa.eu), © Európska únia, 1998–2026. Autentické je iba znenie publikované v elektronickom Úradnom vestníku Európskej únie.",
                  "excerpt": "Article 7 — Podmienky vyjadrenia súhlasu 1. Ak je spracúvanie založené na súhlase, prevádzkovateľ musí vedieť preukázať, že dotknutá osoba vyjadrila súhlas so spracúvaním svojich osobných údajov. 2. Ak dá dotknutá osoba súhlas v rámci písom",
                  "citation": "čl. 7 nariadenia (EÚ) 2016/679",
                  "jurisdiction": "eu"
                },
                {
                  "act": "18/2018",
                  "title": "Podmienky poskytnutia súhlasu so spracúvaním osobných údajov",
                  "excerpt": "§ 14 Podmienky poskytnutia súhlasu so spracúvaním osobných údajov (1) Ak je spracúvanie osobných údajov založené na súhlase dotknutej osoby, prevádzkovateľ je povinný kedykoľvek vedieť preukázať, že dotknutá osoba poskytla súhlas so spracúv",
                  "citation": "§14 zákona č. 18/2018 Z.z.",
                  "jurisdiction": "sk"
                }
              ]
            },
            "whyMatters": "GDPR Article 7(3): 'It shall be as easy to withdraw as to give consent.' If users can subscribe in one click, unsubscribing must be equally simple. Missing this is a common regulatory finding."
          },
          {
            "i18n": {
              "key": "gdpr.dispute-resolution.fail"
            },
            "name": "Consumer Dispute Resolution Links",
            "value": "No EU ODR platform or supervisory-authority link found",
            "status": "fail",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add the EU ODR platform link (https://ec.europa.eu/consumers/odr) and your national authority (SK: Slovenská obchodná inšpekcia / soi.sk, CZ: Česká obchodní inspekce / coi.cz) to the footer and Terms & Conditions.",
            "legalRefs": {
              "gdpr": [
                "Nariadenie (EÚ) 524/2013 (ODR)",
                "Smernica 2013/11/EÚ (ADR)"
              ],
              "czLaw": [
                "zák. 634/1992 Sb. § 14"
              ],
              "skLaw": [
                "zák. 391/2015 Z.z."
              ]
            },
            "whyMatters": "EU Regulation 524/2013 makes the ODR link mandatory for every online trader; national law requires naming the supervisory authority. ŠOI/ČOI inspect for exactly this, and its absence is a common consumer-law breach."
          },
          {
            "i18n": {
              "key": "gdpr.withdrawal-complaints.pass"
            },
            "name": "Withdrawal & Complaints Policy",
            "value": "Withdrawal right + complaints procedure referenced",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "legalRefs": {
              "gdpr": [
                "Smernica 2011/83/EÚ čl. 6(1)(h),(9)"
              ],
              "czLaw": [
                "zák. 89/2012 Sb. § 1829"
              ],
              "skLaw": [
                "zák. 108/2024 Z.z."
              ]
            }
          },
          {
            "i18n": {
              "key": "gdpr.withdrawal-function.info"
            },
            "name": "Online Withdrawal Function",
            "value": "No explicit online withdrawal button in the server HTML — it may live in the logged-in account/order area, which this scan can't reach. Verify it's present.",
            "status": "info",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add a clearly labelled withdrawal function to your online interface (SK label: 'odstúpiť od zmluvy tu'), easy to find and continuously available during the 14-day withdrawal window — e.g. in the customer account / order detail plus a footer link. A logged-in customer must be able to submit a withdrawal declaration without re-identifying.",
            "confidence": "low",
            "whyMatters": "Directive (EU) 2023/2673 (amending 2011/83/EU), transposed in SK as § 20a zák. 108/2024, requires online traders to provide an easy-to-use withdrawal function — a clearly labelled button, continuously available during the withdrawal period — effective 19 June 2026 for all distance contracts with a right of withdrawal. Orientation only — verify placement manually."
          },
          {
            "i18n": {
              "key": "gdpr.guarantee-notice.info"
            },
            "name": "Legal Guarantee Notice",
            "value": "No harmonised notice on the legal guarantee was found on the pages we scanned — it may be on a page this scan does not open. Verify it is shown.",
            "status": "info",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Show the EU harmonised notice on the legal guarantee of conformity as a general reminder on your website (e.g. in the footer or on every product page), using the official design and wording for your language from the Commission implementing act. A 'záruka 24 mesiacov' line on the product is not the same thing — the notice is about the statutory guarantee.",
            "confidence": "low",
            "whyMatters": "Directive (EU) 2024/825 (amending 2011/83/EU) requires traders to remind consumers, in a harmonised notice prominently displayed on the website, that the legal guarantee of conformity exists and lasts at least 2 years. National rules apply from 27 September 2026."
          }
        ]
      },
      "nis2": {
        "score": -1,
        "checks": [
          {
            "i18n": {
              "key": "nis2.scope.none"
            },
            "name": "NIS2 Compliance",
            "value": "Not in scope — your business is below NIS2 thresholds (Annex I/II sector + 50+ employees / €10M+ turnover).",
            "status": "info",
            "howToFix": "",
            "whyMatters": ""
          }
        ]
      },
      "mobile": {
        "score": 70,
        "checks": [
          {
            "i18n": {
              "key": "mob.viewport.pass"
            },
            "name": "Viewport Configuration",
            "value": "width=device-width, initial-scale=1",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "mob.perf.warning",
              "params": {
                "score": 74
              }
            },
            "name": "Mobile Performance Score",
            "value": "74/100 (target: 90+)",
            "status": "warning",
            "evidence": {
              "source": "PSI-lab"
            },
            "howToFix": "Optimize for mobile: compress images to WebP, defer non-critical JS, reduce CSS file size. Mobile CPUs are several times slower than desktop — what's fast on desktop is slow on mobile.",
            "whyMatters": "Most e-commerce traffic is mobile. Google ranks based on mobile performance, not desktop."
          },
          {
            "i18n": {
              "key": "mob.taptarget.warning",
              "params": {
                "detail": "Some tappable targets are too small or too close together (Lighthouse tap-targets audit)"
              }
            },
            "name": "Touch Target Size",
            "value": "Some tappable targets are too small or too close together (Lighthouse tap-targets audit)",
            "status": "warning",
            "evidence": {
              "source": "PSI-lab",
              "measured": "Some tappable targets are too small or too close together (Lighthouse tap-targets audit)"
            },
            "howToFix": "Ensure ALL interactive elements (buttons, links, form fields) are at least 48×48px with 8px minimum spacing between them. Pay special attention to: navigation menus, filter buttons, product variant selectors, and footer links.",
            "whyMatters": "Small tap targets cause mis-taps on mobile. In e-commerce, a mis-tap on 'Remove from cart' instead of 'Checkout' directly loses revenue."
          },
          {
            "i18n": {
              "key": "mob.fontsize.warning",
              "params": {
                "detail": "Some text renders below the 12px legibility threshold (Lighthouse font-size audit)"
              }
            },
            "name": "Font Size Readability",
            "value": "Some text renders below the 12px legibility threshold (Lighthouse font-size audit)",
            "status": "warning",
            "evidence": {
              "source": "PSI-lab",
              "measured": "Some text renders below the 12px legibility threshold (Lighthouse font-size audit)"
            },
            "howToFix": "Google's font-size audit flags text under 12px. Find the small text (often footer fine-print, captions, or cookie notices) and raise it; aim for a 16px+ body base with relative units (rem/em) so all text scales legibly on mobile.",
            "whyMatters": "Text below the legibility threshold forces mobile users to pinch-zoom. This measures the actual rendered page (Lighthouse), so it catches sub-12px nodes even when the base font looks fine."
          },
          {
            "i18n": {
              "key": "mob.contentwidth.pass"
            },
            "name": "Content Fits Viewport",
            "value": "No horizontal scrolling needed",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "mob.responsive.pass",
              "params": {
                "techniques": "Media queries"
              }
            },
            "name": "Responsive Design Techniques",
            "value": "Media queries detected",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "mob.pwa.warning"
            },
            "name": "PWA Features",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Consider adding Progressive Web App features: 1) Create manifest.json with app name, icons, and theme color, 2) Register a service worker for offline caching. This makes your store installable on mobile.",
            "whyMatters": "PWAs combine the best of web and native apps. For e-commerce, PWAs enable push notifications, offline browsing, and home screen access."
          },
          {
            "i18n": {
              "key": "mob.themecolor.warning"
            },
            "name": "Theme Color",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add <meta name='theme-color' content='#your-brand-color'> to match your brand. Browsers use this to color the address bar, task switcher, and PWA chrome.",
            "whyMatters": "Theme-color creates a polished, branded mobile experience. It makes your site look native and professional."
          },
          {
            "i18n": {
              "key": "mob.nav.pass"
            },
            "name": "Mobile Navigation (Semantic)",
            "value": "<nav> element present — proper navigation landmark",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "mob.srcset.warning",
              "params": {
                "count": 4
              }
            },
            "name": "Responsive Images (srcset)",
            "value": "4 images without responsive sizing",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add srcset and sizes attributes to <img> tags to serve appropriately sized images for each screen. Mobile devices shouldn't download 1920px desktop images.",
            "whyMatters": "Without srcset, mobile users download full-size desktop images, wasting bandwidth. Responsive images are the single biggest mobile performance win for image-heavy sites."
          },
          {
            "i18n": {
              "key": "mob.inputtypes.pass",
              "params": {
                "optimized": "2 email, 2 search"
              }
            },
            "name": "Form Input Types",
            "value": "Optimized: 2 email, 2 search",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "mob.stickycta.warning"
            },
            "name": "Mobile Sticky CTA",
            "value": "Add-to-cart button found but no sticky/fixed positioning detected",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add a sticky add-to-cart bar at the bottom of mobile screens. Use position: sticky or position: fixed with bottom: 0. The CTA should always be visible without scrolling.",
            "whyMatters": "Mobile users scroll extensively. A sticky add-to-cart bar keeps the primary action visible. Without it, users must scroll back up to purchase — many won't."
          },
          {
            "i18n": {
              "key": "mob.textoverflow.warning"
            },
            "name": "Text Overflow Handling",
            "value": "No word-break/overflow-wrap CSS detected",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add 'overflow-wrap: break-word' to your body or main content container. Without it, long URLs, product SKUs, or German compound words can break mobile layouts.",
            "whyMatters": "Long strings without word-break cause horizontal overflow on mobile — a common cause of 'content wider than viewport' failures. Compound words and URLs are frequent culprits."
          },
          {
            "i18n": {
              "key": "mob.print.warning"
            },
            "name": "Print Stylesheet",
            "value": "Order/invoice page without print styles",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add @media print CSS rules to hide navigation, ads, and non-essential elements. Ensure order details, prices, and company info are visible when printed.",
            "whyMatters": "Customers print order confirmations and invoices. Without print styles, they get navigation bars, cookie banners, and broken layouts. This is a common usability complaint for e-commerce."
          },
          {
            "i18n": {
              "key": "mob.payments.info"
            },
            "name": "Payment Methods Detected",
            "value": "Žiadna známa platobná brána nedetekovaná na homepage",
            "status": "info",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Payment gateway detection scanuje iba homepage. Ak sú platby na /checkout alebo sú načítané JS-om až po interakcii, neuvidíme ich. Zváž pridať platobné ikony do footer-u.",
            "whyMatters": "Viditeľné platobné ikony (Apple Pay, Google Pay, Klarna, Tatra Pay) v headeri/footeri zvyšujú conversion. Trust signal pred checkoutom."
          },
          {
            "i18n": {
              "key": "mob.express.info"
            },
            "name": "Express Checkout (Apple Pay + Google Pay)",
            "value": "Apple Pay / Google Pay nedetekované na homepage — express checkout sa zvyčajne zobrazí až v košíku/checkoute",
            "status": "info",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Ak express checkout nemáš, pridaj Apple Pay + Google Pay cez Stripe/Adyen/Mollie. Biometric auth = -1 click checkout = vyšší conversion.",
            "whyMatters": "Mobile conversion pri express checkout je vyšší oproti klasickej karte. V SK/CZ rastúci trend. (Sken vidí iba homepage, takže toto je hint, nie verdikt.)"
          },
          {
            "i18n": {
              "key": "mob.skczpay.info"
            },
            "name": "SK/CZ Local Payment Methods",
            "value": "Žiadna SK/CZ local payment metóda nedetekovaná na homepage — bankové tlačidlá/QR sa zvyčajne zobrazia až v checkoute",
            "status": "info",
            "fixLink": {
              "url": "https://www.inger.sk/#contact",
              "label": "Integrovať SK payments — Inger"
            },
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Ak SK/CZ local platby nemáš, integruj GoPay alebo ComGate — obe podporujú Tatra Pay, VÚB Pay, ČSOB Pay, Raiffeisen, QR platba v jednom API. Alternatívne Barion pre CZ trh.",
            "whyMatters": "SK/CZ shop bez bankových tlačidiel a QR platby = masívny cart abandonment. Priemerný SK e-shop má viacero payment metód. (Sken vidí iba homepage — over manuálne v checkoute.)"
          },
          {
            "i18n": {
              "key": "mob.wcaglabels.fail",
              "params": {
                "rate": 75,
                "total": 8,
                "missing": 2,
                "withLabel": 6
              }
            },
            "name": "Form Input Labels (WCAG 3.3.2)",
            "value": "Iba 6/8 inputs má label (75%)",
            "status": "fail",
            "fixLink": {
              "url": "https://www.inger.sk/#contact",
              "label": "Accessibility audit — Inger"
            },
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "2 input elementov nemá label. Každý input musí mať priradený <label for=\"id\">Text</label> alebo aria-label. Placeholder NIE je label (WCAG 3.3.2). Ak je checkout/registrácia formulár — toto znižuje konverziu a porušuje EN 301 549 (EAA 2026).",
            "whyMatters": "EAA 2026 (European Accessibility Act) vstupuje do platnosti 28.6.2025. E-shopy nad 10 zamestnancov alebo €2M obrat musia byť WCAG 2.1 AA kompatibilné — chýbajúce labely sú jedna z najčastejších žalovateľných chýb."
          },
          {
            "i18n": {
              "key": "mob.wcagheading.warning",
              "params": {
                "skips": "h1→h3"
              }
            },
            "name": "Heading Hierarchy (WCAG 1.3.1)",
            "value": "Preskočené úrovne: h1→h3",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Dodržuj poradie nadpisov h1 → h2 → h3 → h4 bez preskočenia. Screen readers používajú hierarchiu nadpisov na navigáciu. Ak potrebuješ menšie písmo ale rovnakú úroveň, použi CSS triedu, nie nižší heading tag.",
            "whyMatters": "Preskočené heading levely (napr. h1 priamo na h3) zlomia navigáciu pre screen reader používateľov a signalizujú Googlu zlú štruktúru dokumentu. Aj SEO je negatívne ovplyvnené."
          },
          {
            "i18n": {
              "key": "mob.wcaglinks.warning",
              "params": {
                "count": 1
              }
            },
            "name": "Link Text Quality (WCAG 2.4.4)",
            "value": "1 odkazov má generický text (\"click here\", \"more\", \"tu\"...)",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Nahraď 'Click here' / 'Read more' / 'Viac' popisným textom: 'Prečítaj si viac o GDPR', 'Pozri cenník modulov'. Screen readers čítajú odkazy mimo kontextu — samostatné 'viac' nemá význam.",
            "whyMatters": "WCAG 2.4.4: Účel odkazu musí byť zrejmý z textu. Vágne odkazy zhoršujú UX, konverziu aj SEO (Google anchor text relevancia)."
          }
        ]
      },
      "company": {
        "nis2": {
          "annex": null,
          "sector": null,
          "category": "none",
          "in_scope": false,
          "priority_tier": null,
          "priority_score": null
        },
        "financials": {
          "year": 2025,
          "equity": 1297155,
          "profit": 365663,
          "turnover": 3500670
        },
        "percentile": {
          "metrics": {
            "equity": 38,
            "turnover": 29,
            "net_profit": 39,
            "credit_limit": 42,
            "credit_score": 87,
            "total_assets": 38,
            "debt_to_equity": 14,
            "employee_count": 97
          },
          "nace_section": "G",
          "peer_group_size": 119079
        },
        "in_insolvency": false,
        "credit_grade_full": "A+"
      },
      "modules": [],
      "security": {
        "score": 60,
        "checks": [
          {
            "i18n": {
              "key": "sec.ssl.pass"
            },
            "name": "SSL/TLS Certificate",
            "value": "Valid HTTPS connection established",
            "status": "pass",
            "evidence": {
              "source": "SSL"
            }
          },
          {
            "i18n": {
              "key": "sec.dnssec.pass"
            },
            "name": "DNSSEC",
            "value": "Zone is DNSSEC-signed (DNSKEY published)",
            "status": "pass",
            "evidence": {
              "source": "DNS"
            },
            "whyMatters": "DNSSEC protects against DNS cache poisoning and on-path attackers redirecting your domain. Required by some sector regulators for NIS2 essential/important entities."
          },
          {
            "i18n": {
              "key": "sec.caa.warning"
            },
            "name": "CAA DNS Record",
            "value": "No CAA records — any CA can issue certificates for this domain",
            "status": "warning",
            "evidence": {
              "source": "DNS"
            },
            "howToFix": "Publish CAA TXT records pinning your CA. For Let's Encrypt: `0 issue \"letsencrypt.org\"`. For multiple CAs add additional `0 issue \"...\"` records. Add `0 iodef \"mailto:security@yourdomain.tld\"` for misissuance reports.",
            "whyMatters": "CAA records limit which Certificate Authorities can issue certificates for your domain. Without CAA, a compromised or rogue CA can issue valid certs that browsers will trust — a documented breach pattern (DigiNotar 2011, Symantec 2017)."
          },
          {
            "i18n": {
              "key": "sec.https-redirect.warning"
            },
            "name": "HTTP → HTTPS Redirect",
            "status": "warning",
            "evidence": {
              "source": "HTTP-header"
            },
            "howToFix": "Configure a 301 redirect from http:// to https:// for all pages. In Apache: RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]",
            "whyMatters": "Without a redirect, users can access the insecure HTTP version. Google also treats http and https as separate URLs, splitting your SEO signals."
          },
          {
            "i18n": {
              "key": "sec.hsts.fail"
            },
            "name": "HSTS (Strict-Transport-Security)",
            "status": "fail",
            "evidence": {
              "source": "HTTP-header"
            },
            "howToFix": "Add header: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload — then submit to hstspreload.org.",
            "whyMatters": "Without HSTS, attackers can intercept the first HTTP request and downgrade the connection to steal session cookies on public WiFi."
          },
          {
            "i18n": {
              "key": "sec.csp.fail"
            },
            "name": "Content-Security-Policy (CSP)",
            "status": "fail",
            "fixLink": {
              "url": "https://www.inger.sk/#contact",
              "label": "Get Security Hardening →"
            },
            "evidence": {
              "source": "HTTP-header"
            },
            "howToFix": "Implement a CSP header. Start with: Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: — then gradually tighten.",
            "whyMatters": "CSP is a strong defense against XSS attacks. Without it, any injected script runs with full privileges. CSP blocks inline script injection."
          },
          {
            "i18n": {
              "key": "sec.clickjacking.pass",
              "params": {
                "detail": "SAMEORIGIN, SAMEORIGIN"
              }
            },
            "name": "Clickjacking Protection",
            "value": "X-Frame-Options: SAMEORIGIN, SAMEORIGIN",
            "status": "pass",
            "evidence": {
              "source": "HTTP-header"
            }
          },
          {
            "i18n": {
              "key": "sec.x-content-type.pass"
            },
            "name": "X-Content-Type-Options",
            "value": "nosniff",
            "status": "pass",
            "evidence": {
              "source": "HTTP-header"
            }
          },
          {
            "i18n": {
              "key": "sec.referrer-policy.warning"
            },
            "name": "Referrer-Policy",
            "status": "warning",
            "evidence": {
              "source": "HTTP-header"
            },
            "howToFix": "Add header: Referrer-Policy: strict-origin-when-cross-origin — this is the best balance between functionality and privacy.",
            "whyMatters": "Without a referrer policy, browsers send the full URL to third parties. This can leak sensitive data like session tokens in URLs or internal page paths."
          },
          {
            "i18n": {
              "key": "sec.permissions-policy.warning"
            },
            "name": "Permissions-Policy",
            "status": "warning",
            "evidence": {
              "source": "HTTP-header"
            },
            "howToFix": "Add: Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=() — disable APIs your site doesn't need.",
            "whyMatters": "Without Permissions-Policy, any third-party script (ads, analytics, chat widgets) can access camera, microphone, and geolocation without your knowledge."
          },
          {
            "i18n": {
              "key": "sec.cookie-flags.warning",
              "params": {
                "count": 3,
                "missing": "2 missing HttpOnly, 2 missing SameSite"
              }
            },
            "name": "Cookie Security Flags",
            "value": "3 cookie(s): 2 missing HttpOnly, 2 missing SameSite",
            "status": "warning",
            "evidence": {
              "source": "HTTP-header"
            },
            "howToFix": "Set all cookies with: Secure (HTTPS only), HttpOnly (no JS access), SameSite=Lax or Strict (CSRF protection). Session cookies MUST have all three.",
            "whyMatters": "Missing Secure flag = cookies sent over HTTP (stealable on WiFi). Missing HttpOnly = cookies readable by XSS. Missing SameSite = vulnerable to CSRF attacks."
          },
          {
            "i18n": {
              "key": "sec.tech-disclosure.pass",
              "params": {
                "detail": "openresty"
              }
            },
            "name": "Technology Disclosure",
            "value": "Server: openresty (no version)",
            "status": "pass",
            "evidence": {
              "source": "HTTP-header"
            }
          },
          {
            "i18n": {
              "key": "sec.sri.warning",
              "params": {
                "eligible": 6,
                "exemptNote": " (1 auto-updating provider script(s) excluded — SRI not applicable)",
                "withIntegrity": 0
              }
            },
            "name": "Subresource Integrity (SRI)",
            "value": "Only 0/6 SRI-eligible third-party scripts have integrity hashes (1 auto-updating provider script(s) excluded — SRI not applicable)",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add integrity='sha384-...' and crossorigin='anonymous' to version-pinned third-party <script> tags (use srihash.org). Auto-updating provider scripts (analytics, payment SDKs, consent tools) are correctly excluded — they can't use SRI.",
            "whyMatters": "Without SRI, if a version-pinned third-party CDN is compromised, attackers can inject malicious code into your site — the same vector as the British Airways Magecart breach."
          },
          {
            "i18n": {
              "key": "sec.security-txt.pass"
            },
            "name": "security.txt (RFC 9116)",
            "value": "Present at /.well-known/security.txt",
            "status": "pass",
            "evidence": {
              "source": "file-probe"
            }
          },
          {
            "i18n": {
              "key": "sec.server-version.pass",
              "params": {
                "name": "openresty"
              }
            },
            "name": "Server Version Disclosure",
            "value": "openresty — version hidden",
            "status": "pass",
            "evidence": {
              "source": "HTTP-header"
            }
          },
          {
            "i18n": {
              "key": "sec.cdn.warning"
            },
            "name": "CDN / WAF Protection",
            "status": "warning",
            "evidence": {
              "source": "HTTP-header"
            },
            "howToFix": "Add a CDN/WAF like Cloudflare (free tier), Sucuri, or Fastly. They provide DDoS protection, bot filtering, and SSL management.",
            "whyMatters": "Without a CDN/WAF, your origin server is directly exposed to DDoS attacks, bot traffic, and brute-force attempts."
          },
          {
            "i18n": {
              "key": "sec.password-autocomplete.pass",
              "params": {
                "count": 2
              }
            },
            "name": "Password Field Security",
            "value": "2 password field(s) — allow password manager autofill",
            "status": "pass",
            "evidence": {
              "source": "HTTP-header"
            }
          },
          {
            "i18n": {
              "key": "sec.cookie-prefix.info",
              "params": {
                "count": 1
              }
            },
            "name": "Cookie Prefix Security",
            "value": "1 session cookie(s) already have Secure + HttpOnly + SameSite; adding the __Host- prefix is a cosmetic hardening nicety",
            "status": "info",
            "evidence": {
              "source": "HTTP-header",
              "measured": "1 session cookie(s), all with Secure+HttpOnly+SameSite"
            },
            "howToFix": "Optional: rename to __Host-session (Secure; Path=/; no Domain) for defence-in-depth against subdomain cookie injection.",
            "confidence": "low",
            "whyMatters": "With Secure, HttpOnly and SameSite already set, the prefix adds only host-only enforcement — low marginal benefit."
          }
        ]
      },
      "tech_stack": [
        {
          "cves": [
            "CVE-2011-4969",
            "CVE-2012-6708",
            "CVE-2015-9251",
            "CVE-2020-11022",
            "CVE-2020-11023"
          ],
          "name": "jQuery",
          "version": "1.11.3",
          "category": "js-library",
          "outdated": true
        },
        {
          "name": "openresty",
          "category": "server"
        }
      ],
      "performance": {
        "score": 88,
        "checks": [
          {
            "i18n": {
              "key": "perf.ttfb.pass",
              "params": {
                "ms": 7
              }
            },
            "name": "Server Response Time (TTFB)",
            "value": "7ms",
            "status": "pass",
            "evidence": {
              "source": "PSI-lab"
            }
          },
          {
            "i18n": {
              "key": "perf.fcp.pass",
              "params": {
                "s": "0.85"
              }
            },
            "name": "First Contentful Paint (FCP)",
            "value": "0.85s",
            "status": "pass",
            "evidence": {
              "source": "PSI-lab"
            }
          },
          {
            "i18n": {
              "key": "perf.lcp.pass",
              "params": {
                "s": "0.85"
              }
            },
            "name": "Largest Contentful Paint (LCP)",
            "value": "0.85s — Core Web Vital ✓",
            "status": "pass",
            "evidence": {
              "source": "PSI-lab"
            }
          },
          {
            "i18n": {
              "key": "perf.tbt.pass",
              "params": {
                "ms": 130
              }
            },
            "name": "Total Blocking Time (TBT)",
            "value": "130ms",
            "status": "pass",
            "evidence": {
              "source": "PSI-lab"
            }
          },
          {
            "i18n": {
              "key": "perf.cls.pass",
              "params": {
                "cls": "0.023"
              }
            },
            "name": "Cumulative Layout Shift (CLS)",
            "value": "0.023 — Core Web Vital ✓",
            "status": "pass",
            "evidence": {
              "source": "PSI-lab"
            }
          },
          {
            "i18n": {
              "key": "perf.speed-index.pass",
              "params": {
                "s": "0.87"
              }
            },
            "name": "Speed Index",
            "value": "0.87s",
            "status": "pass",
            "evidence": {
              "source": "PSI-lab"
            }
          },
          {
            "i18n": {
              "key": "perf.page-weight.fail",
              "params": {
                "mb": "4.2",
                "requests": 85
              }
            },
            "name": "Total Page Weight",
            "value": "4.2 MB, 85 requests — too heavy!",
            "status": "fail",
            "fixLink": {
              "url": "https://www.inger.sk/#contact",
              "label": "Get Performance Optimization →"
            },
            "evidence": {
              "source": "PSI-lab"
            },
            "howToFix": "Critical: your page is over 3 MB. 1) Convert all images to WebP/AVIF, 2) Lazy load everything below the fold, 3) Remove unused plugins, 4) Combine and minify CSS/JS, 5) Enable brotli compression.",
            "whyMatters": "Pages over 3 MB take 12+ seconds on 3G. The average e-commerce page is around 2 MB — you're well above that. Even small latency increases measurably reduce sales."
          },
          {
            "i18n": {
              "key": "perf.js-budget.warning",
              "params": {
                "kb": 860
              }
            },
            "name": "JavaScript Budget",
            "value": "860 KB — over the 600 KB budget, but below the 1270 KB median of the award-winning shops we benchmarked",
            "status": "warning",
            "evidence": {
              "source": "PSI-lab",
              "measured": "860 KB JavaScript"
            },
            "howToFix": "Split the bundle so a product page doesn't load checkout and account code. Defer third-party scripts until interaction. Drop unused plugin bundles — on most shops these outweigh your own code.",
            "confidence": "high",
            "whyMatters": "Measured on a first load with no interaction, so scripts gated behind cookie consent don't count against you here. The 600 KB bar is best practice, not the cohort average: the shops we benchmarked have a median of 1 270 KB, and the best of them (a category winner that won on mobile) ships 410 KB."
          },
          {
            "i18n": {
              "key": "perf.request-budget.warning",
              "params": {
                "count": 85
              }
            },
            "name": "Request Budget",
            "value": "85 requests — over the budget of 80, but at or below the median of the award-winning shops we benchmarked (140)",
            "status": "warning",
            "evidence": {
              "source": "PSI-lab",
              "measured": "85 requests"
            },
            "howToFix": "Bundle CSS/JS that always loads together, serve icons as a sprite or font rather than individual files, and lazy-load below-fold images so they aren't requested on load.",
            "confidence": "high",
            "whyMatters": "The 80-request bar is best practice; the benchmarked cohort median is 140 and the best shop manages 37. Being under the median is not the same as being fast."
          },
          {
            "i18n": {
              "key": "perf.third-party-budget.info"
            },
            "name": "Third-party Services",
            "value": "Not measured — PageSpeed did not return the third-party audit for this URL",
            "status": "info",
            "evidence": {
              "source": "PSI-lab"
            },
            "howToFix": "Re-run the scan, or check the third-party summary directly at PageSpeed Insights.",
            "whyMatters": "We report this as unmeasured rather than as zero third parties, because those are very different findings."
          },
          {
            "i18n": {
              "key": "perf.render-blocking.info"
            },
            "name": "Render-blocking Resources",
            "value": "Not measured — PageSpeed did not return the render-blocking audit for this URL",
            "status": "info",
            "evidence": {
              "source": "PSI-lab"
            },
            "howToFix": "Re-run the scan, or test directly at PageSpeed Insights. This metric needs a successful Lighthouse lab run."
          },
          {
            "i18n": {
              "key": "perf.unused-code.warning",
              "params": {
                "kb": 176,
                "jsKb": 126,
                "cssKb": 50
              }
            },
            "name": "Unused Code (CSS + JS)",
            "value": "176 KB unused (CSS: 50 KB, JS: 126 KB)",
            "status": "warning",
            "evidence": {
              "source": "PSI-lab"
            },
            "howToFix": "Remove unused CSS with PurgeCSS or UnCSS. Code-split JavaScript so only needed code loads per page. Audit plugins — each adds CSS/JS.",
            "whyMatters": "Unused code is downloaded and parsed but never executed — pure waste. Removing it speeds up parse time and reduces bandwidth."
          },
          {
            "i18n": {
              "key": "perf.text-compression.pass"
            },
            "name": "Text Compression (gzip/brotli)",
            "value": "All text resources properly compressed",
            "status": "pass",
            "evidence": {
              "source": "HTTP-header"
            }
          },
          {
            "i18n": {
              "key": "perf.resource-hints.pass",
              "params": {
                "preload": 1,
                "preconnect": 1
              }
            },
            "name": "Resource Hints (Preload/Preconnect)",
            "value": "1 preload, 1 preconnect hint(s)",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "perf.lazy-load.warning",
              "params": {
                "total": 4
              }
            },
            "name": "Lazy Loading",
            "value": "4 images without lazy loading",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add loading='lazy' to all images below the fold. Keep the hero/LCP image eager-loaded. Native lazy loading is supported by all modern browsers.",
            "whyMatters": "Without lazy loading, ALL images download on page load — even those never scrolled to. On a product page with 20 images, lazy loading can save most of the initial download."
          },
          {
            "i18n": {
              "key": "perf.cache-control.warning",
              "params": {
                "header": "no-store, no-cache, must-revalidate, no-cache, private"
              }
            },
            "name": "Cache-Control Strategy",
            "value": "no-store, no-cache, must-revalidate, no-cache, private",
            "status": "warning",
            "evidence": {
              "source": "HTTP-header"
            },
            "howToFix": "Set appropriate cache headers: static assets should have max-age=31536000 with versioned filenames. HTML pages can use max-age=0 with ETag for revalidation.",
            "whyMatters": "no-cache/no-store forces browsers to re-download resources on every visit. Repeat visitors load your entire site from scratch every time."
          },
          {
            "i18n": {
              "key": "perf.http3.pass"
            },
            "name": "HTTP/3 (QUIC) Support",
            "value": "HTTP/3 enabled via Alt-Svc header",
            "status": "pass",
            "evidence": {
              "source": "HTTP-header"
            }
          },
          {
            "i18n": {
              "key": "perf.script-strategy.fail",
              "params": {
                "rate": 29,
                "total": 7,
                "blocking": 5
              }
            },
            "name": "Script Loading Strategy",
            "value": "Only 29% of 7 scripts optimized — most are render-blocking",
            "status": "fail",
            "fixLink": {
              "url": "https://www.inger.sk/#contact",
              "label": "Get Performance Optimization →"
            },
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add defer or async to all <script src='...'> tags. Render-blocking scripts are a leading cause of slow FCP. Defer maintains execution order, async does not.",
            "whyMatters": "5 render-blocking scripts can add 1-3 seconds to page load. Each synchronous script creates a sequential download-parse-execute chain."
          },
          {
            "i18n": {
              "key": "perf.css-count.pass",
              "params": {
                "count": 5
              }
            },
            "name": "CSS File Count",
            "value": "5 CSS file(s) — well consolidated",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          }
        ]
      },
      "ai_readiness": {
        "score": 55,
        "checks": [
          {
            "i18n": {
              "key": "air.bot-access.pass",
              "params": {
                "detail": "No AI bot restrictions (allowed by default)"
              }
            },
            "name": "AI Bot Access Policy",
            "value": "No AI bot restrictions (allowed by default)",
            "status": "pass",
            "evidence": {
              "source": "file-probe"
            }
          },
          {
            "i18n": {
              "key": "air.agent-live.pass"
            },
            "name": "AI Agent Access (live)",
            "value": "ChatGPT-User and PerplexityBot get the same page as a browser",
            "status": "pass",
            "weight": 2,
            "evidence": {
              "source": "file-probe",
              "measured": "ChatGPT-User, PerplexityBot: same page as a browser",
              "probedUrl": "https://eponeshop.sk"
            }
          },
          {
            "i18n": {
              "key": "air.llms-txt.fail"
            },
            "name": "llms.txt (AI Site Descriptor)",
            "value": "Not present — not required for AI visibility",
            "status": "info",
            "fixLink": {
              "url": "https://llmstxt.org",
              "label": "About llms.txt →"
            },
            "evidence": {
              "source": "file-probe"
            },
            "howToFix": "Optional: /llms.txt (a Markdown site descriptor per llmstxt.org) is future-proofing, mainly consumed by coding/IDE agents. It does NOT affect whether ChatGPT/Perplexity/Gemini cite your store. Prioritize AI-crawler access, server-rendered content, statistics and cited sources instead.",
            "whyMatters": "No answer engine consumes llms.txt for AI-search citation today (2026) — adoption is ~8.7% and Google declined to support it. It's optional future-proofing, mainly read by coding/IDE agents. Prioritize AI-crawler access, server-rendered content, statistics and cited sources instead. See /ai-readiness-methodology.md."
          },
          {
            "i18n": {
              "key": "air.llms-full.warning"
            },
            "name": "llms-full.txt (Complete AI Content)",
            "value": "Not present — not required for AI visibility",
            "status": "info",
            "evidence": {
              "source": "file-probe"
            },
            "whyMatters": "No answer engine consumes llms.txt for AI-search citation today (2026) — adoption is ~8.7% and Google declined to support it. It's optional future-proofing, mainly read by coding/IDE agents. Prioritize AI-crawler access, server-rendered content, statistics and cited sources instead. See /ai-readiness-methodology.md."
          },
          {
            "i18n": {
              "key": "air.content-access.pass",
              "params": {
                "ratio": "3.7",
                "words": 304
              }
            },
            "name": "Content Accessibility for AI",
            "value": "304 words in raw HTML (3.7% text ratio) — readable by AI crawlers without executing JS",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "air.schema-foundation.warning-single",
              "params": {
                "note": "",
                "type": "BusinessEntity"
              }
            },
            "name": "Structured Data Foundation",
            "value": "Only 1 distinct schema type (BusinessEntity) — insufficient for AI visibility",
            "status": "warning",
            "evidence": {
              "source": "schema"
            },
            "howToFix": "One schema type is not enough. Add at minimum: Organization (identity), Product (commerce), BreadcrumbList (navigation), WebSite+SearchAction (discoverability), FAQPage (Q&A answering).",
            "whyMatters": "Single-schema sites get minimal AI coverage. AI models need multiple data signals to confidently recommend your store."
          },
          {
            "i18n": {
              "key": "air.product-schema.info",
              "params": {
                "pageType": "homepage"
              }
            },
            "name": "Product Schema Completeness",
            "value": "No Product schema on this homepage — Product schema lives on product detail pages, and we couldn't identify one to sample",
            "status": "info",
            "evidence": {
              "source": "schema"
            },
            "howToFix": "To audit Product schema, run the scan on a product detail URL. On product pages add: name, description, image, offers (price, priceCurrency, availability), brand, sku, aggregateRating.",
            "whyMatters": "Product schema only belongs on product pages, so its absence on this page is expected — not a defect. Scan a product URL to evaluate it."
          },
          {
            "i18n": {
              "key": "air.search-recovery.pass"
            },
            "name": "Zero-results Recovery",
            "value": "A search with no matches still offers products, suggestions or a way to get help",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic",
              "measured": "60319 B response",
              "probedUrl": "https://eponeshop.sk/action/ProductSearch/prepareString/?string=xyzqwerty-nezmysel"
            },
            "confidence": "low"
          },
          {
            "i18n": {
              "key": "air.search-typo.info-similar",
              "params": {
                "typo": 60319,
                "baseline": 60319
              }
            },
            "name": "Search Typo Handling (measurement)",
            "value": "A correctly spelled query and the same query with a typo return similarly sized pages (60319 B vs 60319 B) — consistent with typo tolerance",
            "status": "info",
            "evidence": {
              "source": "HTML-heuristic",
              "measured": "60319 B response",
              "probedUrl": "https://eponeshop.sk/action/ProductSearch/prepareString/?string=xyzqwerty-nezmysel"
            },
            "howToFix": "Verify by hand: search for a product, then search again with one letter transposed. If the second search finds nothing, a search engine with fuzzy matching and synonyms will recover those sales.",
            "confidence": "low",
            "whyMatters": "This is a raw measurement, not a verdict, and it is never scored: page size is only a proxy for result count and themes differ. It is here so you can see what we saw."
          },
          {
            "i18n": {
              "key": "air.org-schema.warning"
            },
            "name": "Organization Schema + Entity Linking",
            "value": "Organization schema found but no sameAs links",
            "status": "warning",
            "evidence": {
              "source": "schema"
            },
            "howToFix": "Add sameAs array to your Organization schema linking to Wikipedia, LinkedIn, Facebook, Instagram, and other official profiles. This creates a Knowledge Graph entity for your brand.",
            "whyMatters": "sameAs links tell AI that this is the same entity across the web. It's how Google builds Knowledge Panels and how AI attributes information to your brand."
          },
          {
            "i18n": {
              "key": "air.faq-schema.warning"
            },
            "name": "FAQ Schema (Direct AI Answers)",
            "status": "warning",
            "evidence": {
              "source": "schema"
            },
            "howToFix": "Add FAQPage schema to every product page and category page. Include 3-5 Q&As per page covering: product specifications, shipping, returns, usage instructions. Format: question (full sentence) + answer (75-150 words).",
            "whyMatters": "ChatGPT, Perplexity, and Google AI Overviews pull FAQ answers verbatim. FAQ schema is one of the fastest ways to get your content cited by AI."
          },
          {
            "i18n": {
              "key": "air.breadcrumb.warning"
            },
            "name": "Breadcrumb Schema",
            "status": "warning",
            "evidence": {
              "source": "schema"
            },
            "howToFix": "Add BreadcrumbList schema reflecting your category hierarchy: Home → Category → Subcategory → Product. Each item needs name and URL.",
            "whyMatters": "AI assistants use breadcrumbs to understand product categorization and site structure. Without it, AI can't contextualize where products fit in your catalog — e.g., 'Running Shoes' under 'Sports > Footwear > Running'."
          },
          {
            "i18n": {
              "key": "air.sitesearch.warning"
            },
            "name": "Site Search Schema (SearchAction)",
            "status": "warning",
            "evidence": {
              "source": "schema"
            },
            "howToFix": "Add WebSite schema with potentialAction: SearchAction. Define your search URL template so AI assistants and Google can search your store programmatically.",
            "whyMatters": "SearchAction enables Google's sitelinks search box and allows AI shopping assistants to search your catalog directly. It's how AI agents find specific products in your store."
          },
          {
            "i18n": {
              "key": "air.content-depth.warning",
              "params": {
                "words": 304
              }
            },
            "name": "Content Depth for AI",
            "value": "304 words — add more for better AI citations",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Expand to 500+ words: add detailed product descriptions, use cases, benefits, specifications, comparison info, and buying guides. AI needs substantial content to summarize and cite.",
            "whyMatters": "AI assistants skip thin pages in favor of content-rich competitors. Aim for the depth that makes your page the definitive resource."
          },
          {
            "i18n": {
              "key": "air.answer-first.warning"
            },
            "name": "Answer-First Content Format",
            "value": "Content doesn't start with a strong summary paragraph",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Place your most important information in the first 100 words of the page. Use the BLUF method (Bottom Line Up Front): start with what the product IS and why it matters, then elaborate.",
            "whyMatters": "AI assistants extract content from the first 100 words to generate summaries. Most AI systems read top-down, so answer-first pages get cited more often."
          },
          {
            "i18n": {
              "key": "air.headings.pass",
              "params": {
                "h2": 6,
                "h3": 10
              }
            },
            "name": "Heading Hierarchy for AI",
            "value": "Proper structure: 1 H1 → 6 H2s → 10 H3s — clear content outline",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "air.semantic-html.pass",
              "params": {
                "count": 5,
                "elements": "<nav>, <main>, <header>, <footer>, <aside>"
              }
            },
            "name": "Semantic HTML Structure",
            "value": "5/6 semantic elements: <nav>, <main>, <header>, <footer>, <aside>",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "air.structured-content.warning-partial",
              "params": {
                "what": "14 lists",
                "missing": "comparison tables"
              }
            },
            "name": "Structured Content (Lists & Tables)",
            "value": "14 lists found — consider adding comparison tables",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add comparison tables to your content. Use <ul>/<ol> for feature lists, specifications, and benefits. Use <table> for product comparisons, pricing tiers, and specifications. AI extracts structured content much faster than paragraphs.",
            "whyMatters": "AI models are biased toward extracting data from HTML lists and tables. Perplexity and ChatGPT pull bullet points and table data with higher accuracy than paragraph text."
          },
          {
            "i18n": {
              "key": "air.freshness.fail"
            },
            "name": "Content Freshness Signals",
            "status": "fail",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add dateModified and datePublished to your JSON-LD schema, and display a visible 'Last updated' date on the page. Update content quarterly at minimum. AI heavily favors fresh, maintained content.",
            "whyMatters": "With no freshness signals, AI assumes your content is stale. ChatGPT and Perplexity both weight recency in their citation algorithms. Competitors who show recent updates will be cited instead of your static pages."
          },
          {
            "i18n": {
              "key": "air.entity-clarity.warning-nosameAs",
              "params": {
                "count": 0
              }
            },
            "name": "Entity Clarity & Brand Signals",
            "value": "OG tags complete but no sameAs entity links",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "For full entity clarity: 1) Complete Open Graph tags (og:title, og:description, og:image, og:type), 2) Add sameAs in Organization schema linking to Wikipedia, LinkedIn, Facebook, and other profiles.",
            "whyMatters": "AI needs to confidently identify your brand entity. Open Graph and sameAs together create a cross-platform identity that AI models recognize."
          },
          {
            "i18n": {
              "key": "air.eeat.warning-noarticle"
            },
            "name": "Author Expertise Signals (E-E-A-T)",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "For content pages (blog, guides, about): add Article/BlogPosting schema with author property linking to Person schema. Include the author's jobTitle, credentials, and social profiles.",
            "whyMatters": "AI models weight author expertise heavily. Pages from identified experts get cited more than anonymous content. This is especially important for product guides, reviews, and advice content."
          },
          {
            "i18n": {
              "key": "air.review-schema.info",
              "params": {
                "pageType": "homepage"
              }
            },
            "name": "Reviews & Ratings Schema",
            "value": "No review schema on this homepage — review/rating schema typically lives on product pages",
            "status": "info",
            "evidence": {
              "source": "schema"
            },
            "howToFix": "Scan a product URL to audit review schema. On product pages add AggregateRating (ratingValue, reviewCount, bestRating) and individual Review schemas.",
            "whyMatters": "Review schema is product-page-specific, so its absence here is expected, not a defect."
          },
          {
            "i18n": {
              "key": "air.ai-plugin.warning"
            },
            "name": "AI Plugin Manifest",
            "value": "Not present — not required (the ChatGPT-plugins manifest was retired in 2024)",
            "status": "info",
            "evidence": {
              "source": "file-probe"
            },
            "whyMatters": "ai-plugin.json belonged to the retired ChatGPT-plugins system. Modern agent integration uses MCP / tool APIs — see the WebMCP / Agent-Commerce Readiness signals instead."
          },
          {
            "i18n": {
              "key": "air.product-feed.warning"
            },
            "name": "Product Feed (AI Commerce)",
            "status": "warning",
            "fixLink": {
              "url": "https://audit.mergado.com/",
              "label": "Free feed audit — Mergado"
            },
            "evidence": {
              "sample": "probed /feed/products.xml, /google-shopping.xml, /export/google-shopping.xml — none returned a product feed",
              "source": "file-probe"
            },
            "howToFix": "Create a Google Merchant Center / product feed (XML or CSV). Expose it at a consistent URL and reference it in your sitemap. AI shopping assistants and comparison engines use product feeds for catalog discovery. Tip: validate your Heureka / Zboží / Glami / Merchant feeds for free with Mergado's audit.",
            "whyMatters": "Product feeds power Google Shopping, Bing Shopping, and increasingly AI commerce. Without a structured product feed, AI agents can't efficiently index your full catalog for product recommendations."
          },
          {
            "i18n": {
              "key": "air.gtin-coverage.info-nofeed"
            },
            "name": "GTIN/EAN Coverage",
            "value": "No product feed was sampled — GTIN/EAN coverage could not be verified",
            "status": "info",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Publish a Google Merchant or Heureka product feed with GTIN/EAN populated, then re-scan to measure coverage.",
            "whyMatters": "GTIN is how an AI shopping agent matches your product to the same product in other shops. Without a feed we cannot measure it — this is not a finding against you."
          },
          {
            "i18n": {
              "key": "air.heureka-feed.warning-missing"
            },
            "name": "Heureka XML Feed",
            "status": "warning",
            "fixLink": {
              "url": "https://www.inger.sk/#contact",
              "label": "Setup Heureka Feed — Inger"
            },
            "evidence": {
              "source": "file-probe"
            },
            "howToFix": "Vygeneruj Heureka XML feed na /feed/heureka.xml (alebo /export/heureka.xml). PrestaShop má modul Heureka.cz, WooCommerce má pluginy. Štruktúra: <SHOP><SHOPITEM>...</SHOPITEM></SHOP> s ITEM_ID/PRODUCTNAME/URL/PRICE_VAT/CATEGORYTEXT (povinné) + EAN/PARAM/DELIVERY_DATE (highly recommended pre ranking).",
            "whyMatters": "Heureka.sk a Heureka.cz sú dominantné cenové porovnávače na SK/CZ trhu. Bez XML feedu nie ste viditeľní na hlavnom trhovisku. Žiaden generický audit tool toto nekontroluje."
          },
          {
            "i18n": {
              "key": "air.speakable.warning"
            },
            "name": "Speakable Content (Voice AI)",
            "value": "Not present — optional; SpeakableSpecification has limited assistant adoption",
            "status": "info",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "air.extractable.fail"
            },
            "name": "Extractable Answer Blocks",
            "value": "Too few content paragraphs for AI to extract",
            "status": "fail",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add structured content with clear, focused paragraphs (40-80 words each). Each paragraph should answer one question or make one claim that AI can quote directly.",
            "whyMatters": "AI assistants extract individual paragraphs as citations. Without clear, self-contained content blocks, your page can't be quoted in AI-generated answers."
          },
          {
            "i18n": {
              "key": "air.statistics.warning-few",
              "params": {
                "count": 2
              }
            },
            "name": "Statistics & Data Presence",
            "value": "Only 2 data point(s) — add more",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add specific statistics, percentages, dollar amounts, and quantified claims. E.g., '93% of customers report...', 'saves an average of €200/year', '3x faster than...' Data makes content citable.",
            "whyMatters": "AI assistants prefer content with verifiable data points and quantified claims — they're the most quotable parts of a page."
          },
          {
            "i18n": {
              "key": "air.section-length.warning",
              "params": {
                "avg": 115,
                "ratio": 14
              }
            },
            "name": "Section Length Optimization",
            "value": "Avg section: 115 words — only 14% in 80-200 word optimal range",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Restructure content into sections of 120-180 words between H2/H3 headings. Each section should cover one topic completely. Split sections over 300 words, expand sections under 80 words.",
            "whyMatters": "For Google AI Overviews, 100-150 words per section is the sweet spot — long sections get skipped and very short ones lack substance."
          },
          {
            "i18n": {
              "key": "air.qa-headings.warning-some",
              "params": {
                "count": 1
              }
            },
            "name": "Q&A Format Headings",
            "value": "1 question heading(s) — add more",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Phrase H2/H3 headings as questions: 'How does...?', 'What is...?', 'Why should...?' followed by a direct 1-2 sentence answer. This is a leading format AI assistants use to generate responses.",
            "whyMatters": "AI search engines like Perplexity and ChatGPT match user questions to heading-answer pairs. Q&A format headings are directly extractable by AI and trigger FAQ-style rich results."
          },
          {
            "i18n": {
              "key": "air.question-coverage.fail",
              "params": {
                "n": 1,
                "labels": ": returns/refunds"
              }
            },
            "name": "Common Question Coverage",
            "value": "Answers only 1/5 key shopper questions: returns/refunds",
            "status": "fail",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Your page barely addresses core shopper questions. Add sections covering price, shipping (options + cost), returns/refunds, availability, and payment methods — as visible text, not just in schema. Link to a dedicated FAQ, Shipping, and Returns page.",
            "whyMatters": "AI assistants answer shopping queries by fanning out into price/shipping/returns/availability/payment sub-questions. A page that answers none of them is invisible in AI shopping answers and reads as untrustworthy to buyers."
          },
          {
            "i18n": {
              "key": "air.internal-links.pass",
              "params": {
                "rate": 20
              }
            },
            "name": "Internal Link Density",
            "value": "20 contextual internal links per 1,000 words — strong knowledge graph signal",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "air.canonical.warning-different",
              "params": {
                "url": "https://www.eponeshop.sk/"
              }
            },
            "name": "Canonical Tag for AI Deduplication",
            "value": "Canonical points to different URL: https://www.eponeshop.sk/",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Verify this canonical is intentional. AI models cluster near-duplicate URLs and choose one representative page. If canonical points to a different URL, AI will only index that target URL, not this page.",
            "whyMatters": "AI search engines (ChatGPT, Perplexity, Bing Copilot) use canonicals to deduplicate content. A wrong canonical means AI may cite the wrong page version or ignore this page entirely."
          },
          {
            "i18n": {
              "key": "air.return-policy.warning"
            },
            "name": "Return Policy Schema",
            "status": "warning",
            "evidence": {
              "source": "schema"
            },
            "howToFix": "Add MerchantReturnPolicy schema with: returnPolicyCategory (e.g., MerchantReturnFiniteReturnWindow), merchantReturnDays, returnMethod, returnFees. Link it from Product/Offer via hasMerchantReturnPolicy.",
            "whyMatters": "AI shopping agents (Google Shopping, ChatGPT, Bing Copilot) filter by return flexibility. Products with return policy schema get priority placement in AI product comparisons."
          },
          {
            "i18n": {
              "key": "air.shipping-schema.warning"
            },
            "name": "Shipping Details Schema",
            "status": "warning",
            "evidence": {
              "source": "schema"
            },
            "howToFix": "Add OfferShippingDetails schema with: shippingRate, shippingDestination, deliveryTime (handlingTime + transitTime). AI agents deprioritize products without shipping info.",
            "whyMatters": "Fulfillment speed factors into AI product recommendations. Complete shipping schema means AI can show 'Free shipping, delivers in 2-3 days' — a strong conversion driver."
          },
          {
            "i18n": {
              "key": "air.kg-readiness.warning",
              "params": {
                "count": 2,
                "missing": "@id in JSON-LD, sameAs links (Wikipedia, LinkedIn)"
              }
            },
            "name": "Knowledge Graph Readiness",
            "value": "2/4 signals — missing: @id in JSON-LD, sameAs links (Wikipedia, LinkedIn)",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add: @id in JSON-LD, sameAs links (Wikipedia, LinkedIn). Use @id in JSON-LD to create a unique node identifier. Ensure your brand name is identical in title, schema, and OG tags. Link to Wikipedia/Wikidata via sameAs.",
            "whyMatters": "@id creates a persistent entity identifier that connects your schema across pages and platforms, which is how AI builds a verified brand entity."
          },
          {
            "i18n": {
              "key": "air.readability.warning-high-technical",
              "params": {
                "grade": 20
              }
            },
            "name": "Content Readability for AI",
            "value": "Grade 20 — too complex for broad AI citation (technical threshold: 14)",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Simplify sentences (target 15-20 words average), use common words, break complex ideas into shorter paragraphs. AI extracts content for general audiences — if it's too academic, AI skips it.",
            "whyMatters": "Content above grade 12 readability is harder for AI to extract as clear, concise answers. Pages using clear headers and approachable language are cited more often."
          },
          {
            "i18n": {
              "key": "air.alt-text.warning",
              "params": {
                "pct": 50,
                "poor": 2,
                "missing": 0
              }
            },
            "name": "Image Alt Text Quality for AI",
            "value": "50% good, 2 poor, 0 missing",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Improve alt text: use 3-15 descriptive words per image. Include product name, key feature, and context. Bad: 'image1' or 'photo'. Good: 'Red leather wallet with RFID protection — front view'.",
            "whyMatters": "AI uses alt text to understand images for visual search (Google Lens, Bing Visual Search), product recommendations, and accessibility. Quality alt text opens more discovery channels."
          },
          {
            "i18n": {
              "key": "air.expert-quotes.warning-one"
            },
            "name": "Expert Quotations & Citations",
            "value": "1 quotation found — add more for authority",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add expert quotes, customer testimonials, or industry citations using <blockquote> elements.",
            "whyMatters": "AI assistants weight content with expert quotes and citations higher. Blockquotes signal that your content is backed by authoritative sources — a key E-E-A-T signal."
          },
          {
            "i18n": {
              "key": "air.ai-txt.warning"
            },
            "name": "ai.txt (AI Permissions)",
            "value": "Not present — optional; AI-bot permissions are enforced via robots.txt, not ai.txt",
            "status": "info",
            "evidence": {
              "source": "file-probe"
            },
            "whyMatters": "ai.txt is an emerging fine-grained AI-permissions proposal not yet honored by the major engines. The robots.txt AI-bot rules are the signal that actually gates crawler access."
          },
          {
            "i18n": {
              "key": "air.webmcp.warning"
            },
            "name": "WebMCP Agentic Readiness",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "WebMCP (W3C Community Group standard, Chrome 146+) lets pages declare structured tools for AI agents. Add toolname and tooldescription attributes to <form> elements, or include a <script type='application/webmcp+json'> manifest.",
            "whyMatters": "WebMCP is how AI agents will interact with your store (search products, add to cart, check availability). Google and Microsoft are co-developing this standard."
          },
          {
            "i18n": {
              "key": "air.boilerplate.fail",
              "params": {
                "ratio": 9
              }
            },
            "name": "Content-to-Boilerplate Ratio",
            "value": "Only 9% in main content — mostly boilerplate",
            "status": "fail",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Wrap your primary content in <main> or <article> tags. AI extracts content from these semantic containers — without them, your product descriptions are mixed with navigation and footer text.",
            "whyMatters": "Token density measures useful content vs noise. Pages with under 30% content ratio are hard for AI to parse — it can't find your content in the boilerplate."
          },
          {
            "i18n": {
              "key": "air.trust-widget.warning"
            },
            "name": "Trust Widget",
            "value": "Žiaden trust widget (Heureka / Trustpilot / AggregateRating) nedetekovaný",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Pre SK/CZ shopy: inštaluj Heureka Ověřeno zákazníky widget (zadarmo pre overených predajcov — https://sluzby.heureka.sk). Alternatívne: Trustpilot, Google Reviews s AggregateRating schema. Trust widget na product + kategória + footer.",
            "whyMatters": "SK/CZ kupujúci majú vyššiu dôveru k Heureka Ověřeno ako k iným trust signálom. LLM-y (ChatGPT, Perplexity) a Google SGE citujú shopy s AggregateRating schema prednostne."
          },
          {
            "i18n": {
              "key": "agc.summary.partial",
              "params": {
                "parts": "Access 100 · Understand 50 · Discover 50 · Transact 50",
                "score": 63
              }
            },
            "name": "Agent-Commerce Readiness",
            "value": "63/100 — partly ready (Access 100 · Understand 50 · Discover 50 · Transact 50)",
            "status": "info",
            "whyMatters": "Whether an autonomous shopping agent (a ChatGPT operator, Perplexity, the assistants coming next) can do four things on your shop: get in, read and understand the products, discover the whole catalogue, and act (cart, terms). Almost nobody measures this, and for SK/CZ shops nobody does. The score folds AI-bot access, Product schema, product feeds (Merchant/Heureka/Zboží), WebMCP and purchase terms into one agent-first view. It feeds the public MCP connector now in preparation (\"scan this shop\")."
          },
          {
            "i18n": {
              "key": "agc.cap.access.info",
              "params": {
                "score": 100,
                "present": 2
              }
            },
            "name": "Agent: Access",
            "value": "100/100 (2 signals)",
            "status": "info"
          },
          {
            "i18n": {
              "key": "agc.cap.understand.info",
              "params": {
                "score": 50,
                "present": 2
              }
            },
            "name": "Agent: Understand",
            "value": "50/100 (2 signals)",
            "status": "info"
          },
          {
            "i18n": {
              "key": "agc.cap.discover.info",
              "params": {
                "score": 50,
                "present": 3
              }
            },
            "name": "Agent: Discover",
            "value": "50/100 (3 signals)",
            "status": "info"
          },
          {
            "i18n": {
              "key": "agc.cap.transact.info",
              "params": {
                "score": 50,
                "present": 3
              }
            },
            "name": "Agent: Transact",
            "value": "50/100 (3 signals)",
            "status": "info"
          }
        ]
      },
      "phaseTimings": {
        "tail": 561,
        "total": 1601,
        "phase1": 564,
        "preflight": 197,
        "phase1.dns": 312,
        "phase1.html": 289,
        "phase1.files": 504,
        "phase1.zbozi": 220,
        "phase1.headers": 170,
        "phase1.heureka": 221,
        "phase1.aiAgents": 558,
        "phase1.merchant": 168
      },
      "accessibility": {
        "score": 86,
        "checks": [
          {
            "i18n": {
              "key": "a11y.lang.pass",
              "params": {
                "lang": "sk"
              }
            },
            "name": "Page Language",
            "value": "<html lang=\"sk\"> is set",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "a11y.alt.pass",
              "params": {
                "total": 4
              }
            },
            "name": "Image Alt Text",
            "value": "All 4 images have alt attributes",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "a11y.forms.warning",
              "params": {
                "total": 8,
                "unlabeled": 2
              }
            },
            "name": "Form Labels",
            "value": "2 of 8 form inputs missing a label",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Add a <label for> or aria-label to the remaining inputs.",
            "legalRefs": {
              "gdpr": [],
              "czLaw": [
                "§ 4 zák. 424/2023"
              ],
              "skLaw": [
                "§ 4 zák. 351/2022"
              ],
              "verified": [
                {
                  "act": "351/2022",
                  "excerpt": "§ 4 — (1) Ak odseky 2 až 4 neustanovujú inak, poskytovaná služba musí spĺňať ustanovené požiadavky na prístupnosť služby pre osoby so zdravotným postihnutím; ak ide o výrobky použité na poskytnutie služby, požiadavky na prístupnosť výrobkov",
                  "citation": "§4 zákona č. 351/2022 Z.z.",
                  "jurisdiction": "sk"
                },
                {
                  "act": "424/2023",
                  "title": "Požadavky na přístupnost a volný pohyb",
                  "excerpt": "§ 4 Požadavky na přístupnost a volný pohyb (1) Požadavky na přístupnost výrobků podle § 2 odst. 1 stanoví příloha č. 1 oddíly I a II. (2) Požadavky na přístupnost služeb podle § 2 odst. 2 stanoví příloha č. 1 oddíly III a IV.",
                  "citation": "§4 zákona č. 424/2023 Sb.",
                  "jurisdiction": "cz"
                }
              ]
            },
            "whyMatters": "Inputs without a programmatic label are inaccessible to assistive technology (WCAG 1.3.1 / EN 301 549 § 9.1.3.1)."
          },
          {
            "i18n": {
              "key": "a11y.headings.structure",
              "params": {
                "h1": 1,
                "skips": "h1→h3"
              }
            },
            "name": "Heading Structure",
            "value": "Heading levels skip: h1→h3",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Use a single <h1> and don't jump heading levels (e.g. <h2> straight to <h4>).",
            "legalRefs": {
              "gdpr": [],
              "czLaw": [
                "§ 4 zák. 424/2023"
              ],
              "skLaw": [
                "§ 4 zák. 351/2022"
              ],
              "verified": [
                {
                  "act": "351/2022",
                  "excerpt": "§ 4 — (1) Ak odseky 2 až 4 neustanovujú inak, poskytovaná služba musí spĺňať ustanovené požiadavky na prístupnosť služby pre osoby so zdravotným postihnutím; ak ide o výrobky použité na poskytnutie služby, požiadavky na prístupnosť výrobkov",
                  "citation": "§4 zákona č. 351/2022 Z.z.",
                  "jurisdiction": "sk"
                },
                {
                  "act": "424/2023",
                  "title": "Požadavky na přístupnost a volný pohyb",
                  "excerpt": "§ 4 Požadavky na přístupnost a volný pohyb (1) Požadavky na přístupnost výrobků podle § 2 odst. 1 stanoví příloha č. 1 oddíly I a II. (2) Požadavky na přístupnost služeb podle § 2 odst. 2 stanoví příloha č. 1 oddíly III a IV.",
                  "citation": "§4 zákona č. 424/2023 Sb.",
                  "jurisdiction": "cz"
                }
              ]
            },
            "whyMatters": "A clean heading hierarchy is the primary way assistive-tech users skim a page (WCAG 1.3.1 / 2.4.6)."
          },
          {
            "i18n": {
              "key": "a11y.links.pass"
            },
            "name": "Link Text",
            "value": "Links use descriptive text",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "confidence": "low"
          },
          {
            "i18n": {
              "key": "a11y.landmarks.pass"
            },
            "name": "Landmark Regions",
            "value": "Semantic landmarks present (<main>, <nav>/<header>)",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "a11y.zoom.pass"
            },
            "name": "Zoom & Scaling",
            "value": "Pinch-zoom is not disabled",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "a11y.skiplink.pass"
            },
            "name": "Skip Link",
            "value": "A skip-to-content link is present",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "confidence": "low"
          },
          {
            "i18n": {
              "key": "a11y.legal-basis"
            },
            "name": "EAA Legal Basis",
            "value": "In scope for the European Accessibility Act (in force 28.6.2025): SK zákon 351/2022 Z. z., CZ zákon 424/2023 Sb., Dir. (EU) 2019/882 — assessed against EN 301 549. Inger provides EAA remediation audits.",
            "status": "info",
            "fixLink": {
              "url": "https://www.inger.sk/#contact",
              "label": "Accessibility audit — Inger →"
            },
            "howToFix": "",
            "isUpsell": true,
            "legalRefs": {
              "gdpr": [],
              "czLaw": [
                "§ 4 zák. 424/2023"
              ],
              "skLaw": [
                "§ 4 zák. 351/2022",
                "§ 5 zák. 351/2022"
              ],
              "verified": [
                {
                  "act": "351/2022",
                  "excerpt": "§ 4 — (1) Ak odseky 2 až 4 neustanovujú inak, poskytovaná služba musí spĺňať ustanovené požiadavky na prístupnosť služby pre osoby so zdravotným postihnutím; ak ide o výrobky použité na poskytnutie služby, požiadavky na prístupnosť výrobkov",
                  "citation": "§4 zákona č. 351/2022 Z.z.",
                  "jurisdiction": "sk"
                },
                {
                  "act": "351/2022",
                  "excerpt": "§ 5 — (1) Ak ustanovené požiadavky na prístupnosť služby pre osoby so zdravotným postihnutím nezahŕňajú jednu alebo viac funkcií vyplývajúcich z poskytovania služby, tieto funkcie musia byť prístupné na základe dodržiavania ustanovených kri",
                  "citation": "§5 zákona č. 351/2022 Z.z.",
                  "jurisdiction": "sk"
                },
                {
                  "act": "424/2023",
                  "title": "Požadavky na přístupnost a volný pohyb",
                  "excerpt": "§ 4 Požadavky na přístupnost a volný pohyb (1) Požadavky na přístupnost výrobků podle § 2 odst. 1 stanoví příloha č. 1 oddíly I a II. (2) Požadavky na přístupnost služeb podle § 2 odst. 2 stanoví příloha č. 1 oddíly III a IV.",
                  "citation": "§4 zákona č. 424/2023 Sb.",
                  "jurisdiction": "cz"
                }
              ]
            },
            "whyMatters": ""
          }
        ]
      },
      "vulnerability": {
        "score": 57,
        "checks": [
          {
            "i18n": {
              "key": "vuln.cve.fail",
              "params": {
                "count": 5,
                "items": 1,
                "plural": "s",
                "perItem": "Update jQuery 1.11.3 → 3.7.1 (CVE-2011-4969, CVE-2012-6708, CVE-2015-9251, CVE-2020-11022, CVE-2020-11023)",
                "cveLinks": "CVE-2011-4969: https://nvd.nist.gov/vuln/detail/CVE-2011-4969 · CVE-2012-6708: https://nvd.nist.gov/vuln/detail/CVE-2012-6708 · CVE-2015-9251: https://nvd.nist.gov/vuln/detail/CVE-2015-9251 · CVE-2020-11022: https://nvd.nist.gov/vuln/detail/CVE-2020-11022 · CVE-2020-11023: https://nvd.nist.gov/vuln/detail/CVE-2020-11023",
                "itemsPlural": ""
              }
            },
            "name": "Known Vulnerabilities (CVE)",
            "value": "5 CVEs associated with 1 detected component version",
            "status": "fail",
            "fixLink": {
              "url": "https://www.inger.sk/#contact",
              "label": "Emergency Security Fix →"
            },
            "evidence": {
              "source": "file-probe"
            },
            "howToFix": "Update jQuery 1.11.3 → 3.7.1 (CVE-2011-4969, CVE-2012-6708, CVE-2015-9251, CVE-2020-11022, CVE-2020-11023). Verify each before acting — a host or distro can backport a security patch while the version string still reads as vulnerable, so a detected CVE is not proof your install is affected. CVE details: CVE-2011-4969: https://nvd.nist.gov/vuln/detail/CVE-2011-4969 · CVE-2012-6708: https://nvd.nist.gov/vuln/detail/CVE-2012-6708 · CVE-2015-9251: https://nvd.nist.gov/vuln/detail/CVE-2015-9251 · CVE-2020-11022: https://nvd.nist.gov/vuln/detail/CVE-2020-11022 · CVE-2020-11023: https://nvd.nist.gov/vuln/detail/CVE-2020-11023",
            "confidence": "low",
            "whyMatters": "Versions with published CVEs are a prime automated-scanner target — bots (Shodan, Greynoise, Mirai-family) probe for them within minutes. This finding is inferred from the detected version, so confirm the component is actually unpatched before treating it as exploitable."
          },
          {
            "i18n": {
              "key": "vuln.cms-version.pass"
            },
            "name": "CMS Version Disclosure",
            "value": "No generator tag — CMS identity hidden",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "vuln.sensitive-files.pass"
            },
            "name": "Sensitive Files Exposed",
            "value": ".env, .git, composer.json — all properly blocked",
            "status": "pass",
            "evidence": {
              "source": "file-probe"
            }
          },
          {
            "i18n": {
              "key": "vuln.install-script.pass"
            },
            "name": "Install Script Exposed",
            "value": "No /install/ or /setup/ paths accessible",
            "status": "pass",
            "evidence": {
              "source": "file-probe"
            }
          },
          {
            "i18n": {
              "key": "vuln.directory-listing.pass"
            },
            "name": "Directory Listing",
            "value": "Disabled — file structure hidden",
            "status": "pass",
            "evidence": {
              "source": "file-probe"
            }
          },
          {
            "i18n": {
              "key": "vuln.admin-url.fail",
              "params": {
                "paths": "/admin"
              }
            },
            "name": "Admin Panel at Default URL",
            "value": "Accessible at: /admin",
            "status": "fail",
            "evidence": {
              "source": "file-probe"
            },
            "howToFix": "Rename your admin directory to a random, non-guessable path (e.g., /admin-x7k9m2). Add IP whitelisting via .htaccess, implement 2FA, and set up brute-force protection (fail2ban or similar).",
            "whyMatters": "Default admin URLs receive thousands of automated brute-force attempts daily. Botnets target /admin, /wp-admin, /administrator relentlessly. A renamed path blocks 99% of automated attacks."
          },
          {
            "i18n": {
              "key": "vuln.debug-mode.pass"
            },
            "name": "Debug Mode / Error Exposure",
            "value": "No debug indicators found in page output",
            "status": "pass",
            "evidence": {
              "source": "HTML-heuristic"
            }
          },
          {
            "i18n": {
              "key": "vuln.jquery.fail",
              "params": {
                "major": 1,
                "version": "1.11.3"
              }
            },
            "name": "jQuery Version",
            "value": "jQuery 1.11.3 — critically outdated!",
            "status": "fail",
            "fixLink": {
              "url": "https://www.inger.sk/#contact",
              "label": "Get Store Update →"
            },
            "evidence": {
              "source": "file-probe"
            },
            "howToFix": "jQuery 1.11.3 is associated with multiple known security vulnerabilities. Upgrade to 3.7.x. If your plugins require jQuery 1.x/2.x, use jquery-migrate as a temporary bridge.",
            "confidence": "low",
            "whyMatters": "jQuery 1.x is associated with 6+ known CVEs including XSS and prototype pollution. Automated scanners specifically target sites with jQuery <3.0."
          },
          {
            "i18n": {
              "key": "vuln.csrf.warning",
              "params": {
                "count": 5,
                "withCsrf": 2
              }
            },
            "name": "Form CSRF Protection",
            "value": "2/5 forms have CSRF tokens",
            "status": "warning",
            "evidence": {
              "source": "HTML-heuristic"
            },
            "howToFix": "Ensure ALL forms include a CSRF token. In PrestaShop, use {$csrf_token} in templates. In WordPress, use wp_nonce_field().",
            "confidence": "low",
            "whyMatters": "Forms without CSRF tokens allow cross-site request forgery — an attacker's site can submit orders, change settings, or modify data on behalf of your logged-in users."
          },
          {
            "i18n": {
              "key": "vuln.spf.pass",
              "params": {
                "record": "v=spf1 a mx include:_spf.websupport.sk ?all"
              }
            },
            "name": "SPF Record (Email Security)",
            "value": "SPF configured: v=spf1 a mx include:_spf.websupport.sk ?all",
            "status": "pass",
            "evidence": {
              "source": "DNS"
            }
          },
          {
            "i18n": {
              "key": "vuln.dmarc.fail-missing"
            },
            "name": "DMARC Policy (Email Auth)",
            "status": "fail",
            "fixLink": {
              "url": "https://www.inger.sk/#contact",
              "label": "Get Email Security Setup →"
            },
            "evidence": {
              "source": "DNS"
            },
            "howToFix": "Add a DMARC TXT record at _dmarc.yourdomain.com: v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com — start with quarantine, then move to reject.",
            "whyMatters": "Without DMARC, attackers can send perfectly spoofed emails as your brand. Since May 2025, Google, Yahoo, and Microsoft require DMARC for bulk senders. Missing DMARC = email deliverability problems."
          },
          {
            "i18n": {
              "key": "vuln.dkim.warning"
            },
            "name": "DKIM Signing (Email Auth)",
            "status": "warning",
            "evidence": {
              "source": "file-probe"
            },
            "howToFix": "Configure DKIM signing through your email provider (Google Workspace, Microsoft 365, Mailchimp, SendGrid). Publish the DKIM public key as a TXT record at <selector>._domainkey.yourdomain.com.",
            "whyMatters": "DKIM cryptographically signs outgoing email to prove it comes from your domain. Without DKIM, email providers downgrade trust score — transactional emails land in spam. Gmail and Yahoo require DKIM since 2024 for bulk senders."
          },
          {
            "i18n": {
              "key": "vuln.cross-origin.warning"
            },
            "name": "Cross-Origin Isolation",
            "status": "warning",
            "evidence": {
              "source": "HTTP-header"
            },
            "howToFix": "Add Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Resource-Policy: same-origin headers. These protect against Spectre-type side-channel attacks.",
            "whyMatters": "Without cross-origin isolation headers, your site is vulnerable to Spectre attacks that can leak sensitive data across browser tabs. These headers are required for SharedArrayBuffer and high-resolution timers."
          },
          {
            "i18n": {
              "key": "vuln.mixed-content.warning",
              "params": {
                "urls": "http://www.eponeshop.sk/podmienky-ochrany-osobnych-udajov/",
                "count": 1
              }
            },
            "name": "Mixed Content Resources",
            "value": "1 HTTP resource(s) on HTTPS page",
            "status": "warning",
            "evidence": {
              "source": "file-probe"
            },
            "howToFix": "Replace HTTP URLs with HTTPS: http://www.eponeshop.sk/podmienky-ochrany-osobnych-udajov/",
            "whyMatters": "Mixed content allows man-in-the-middle attacks on specific resources. Browsers increasingly block mixed content, breaking images and scripts on your site."
          },
          {
            "i18n": {
              "key": "vuln.login-form.warning-autocomplete"
            },
            "name": "Login Form Security",
            "value": "Login form blocks password manager autofill",
            "status": "warning",
            "evidence": {
              "source": "file-probe"
            },
            "howToFix": "Remove autocomplete='off' from login forms. Password managers improve security by enabling unique, complex passwords per site.",
            "whyMatters": "NIST guidelines recommend allowing password autofill. Blocking it forces users to choose weak, memorable passwords — a leading cause of credential compromise."
          },
          {
            "i18n": {
              "key": "vuln.payment-page.fail",
              "params": {
                "issues": "No HSTS, No CSP"
              }
            },
            "name": "Payment Page Security",
            "value": "Payment page missing: No HSTS, No CSP",
            "status": "fail",
            "fixLink": {
              "url": "https://www.inger.sk/#contact",
              "label": "Get PCI Compliance Audit →"
            },
            "evidence": {
              "source": "file-probe"
            },
            "howToFix": "CRITICAL: Your payment page is missing security headers: No HSTS, No CSP. PCI DSS Requirement 6.5 mandates protection against common vulnerabilities on pages handling card data.",
            "whyMatters": "Payment pages without proper security headers violate PCI DSS and make card data theft significantly easier. Payment processors can impose monthly fines for non-compliance."
          }
        ]
      },
      "executive_summary": {
        "en": "Your site works reasonably well but has security gaps to close. Immediately enable HTTPS protection (HSTS) in your server settings. Bright spot: your SEO and accessibility are performing well.",
        "sk": "Váš web funguje slušne, ale má bezpečnostné medzery. Prioritne aktivujte HTTPS zabezpečenie (HSTS) v nastaveniach servera. Pozitívum: Vaša SEO a prístupnosť sú na dobrej úrovni."
      },
      "opendata_security": {
        "ico": "54025192",
        "name": "EPONESHOP s.r.o.",
        "counts": {
          "low": 0,
          "high": 1,
          "info": 0,
          "total": 4,
          "medium": 3
        },
        "summary": {
          "spf": true,
          "ssl": {
            "valid": true,
            "issuer": "ZeroSSL GmbH",
            "daysUntilExpiry": 60
          },
          "dmarc": null,
          "dnssec": true,
          "cveHigh": 0,
          "cveCount": 0,
          "mxProvider": null,
          "cveCritical": 0,
          "ctDomainsCount": 2,
          "httpSecurityScore": 20
        },
        "website": "https://www.eponeshop.sk",
        "findings": [
          {
            "code": "LOW_SECURITY_SCORE",
            "title": "HTTP security score je nízke: 20/100",
            "detail": "Implementuj HSTS, CSP, X-Frame-Options a ďalšie security headers.",
            "category": "http",
            "severity": "high"
          },
          {
            "code": "NO_DMARC",
            "title": "Chýba DMARC záznam",
            "detail": null,
            "category": "dns",
            "severity": "medium"
          },
          {
            "code": "NO_HSTS",
            "title": "Chýba HSTS hlavička",
            "detail": "Strict-Transport-Security vynúti HTTPS pre klientov.",
            "category": "http",
            "severity": "medium"
          },
          {
            "code": "NO_CSP",
            "title": "Chýba Content-Security-Policy",
            "detail": "CSP znižuje XSS riziko.",
            "category": "http",
            "severity": "medium"
          }
        ],
        "cyberScore": {
          "band": "B",
          "score": 72,
          "buckets": {
            "ct": 100,
            "cve": 100,
            "ssl": 100,
            "http": 5
          },
          "computedAt": "2026-09-14T14:42:07.671Z"
        },
        "overallScore": 45
      },
      "platform_evidence": [],
      "maintenance_bypass": false,
      "scanner_token_sent": false
    },
    "created_at": "2026-10-08T15:23:04.50048+00:00",
    "status": "complete",
    "platform_detected": null,
    "company_ico": "54025192",
    "company_name": "EPONESHOP s.r.o.",
    "company_country": "SK",
    "company_nace": "4778",
    "company_size": "small",
    "nis2_scope": "none",
    "nis2_sector": null,
    "company_risk_score": 10,
    "company_risk_level": "low"
  }
}