Audit

20260610T100406Z-69db

← Back to larsenee
Audited URL
https://larsen.ee/
Timestamp
2026-06-10T10:09:49.906Z
Kind
site
Pages
5
Audit summary
https://larsen.ee/
5 of 5 pages audited
Pagespeed scores
Other checks
LLM Report

Weighted audit summary

50
Overall site quality
Poorhigh confidence

Site overall 50 is the mean of 5 pages. Scores range 45 (https://larsen.ee/) → 52 (https://larsen.ee/et). Weakest page: Mobile performance is catastrophic (PSI 48, LCP 47.1s) due to 69 MB page weight and 1.37 MB unused JavaScript, dragging the score into the 'Poor' band. Accessibility is compromised by 2 critical axe violations (button-name, image-alt) and 11 W3C errors including heading skips. Security headers are weak (40/100) with missing HSTS and X-Frame-Options, though no auth/payments signals reduce immediate exploitation risk. Desktop performance (43) is similarly poor, indicating systemic architectural issues rather than just mobile throttling.

Per-page scores
45
Home
high
52
/about
high
52
/faq
high
48
/terms-of-service
high
52
/et
high

Audit Report: Larsen - The Coolest Accommodation in Tallinn

Website: https://larsen.ee/
Date: 2026-06-10

Overall Score: 50 / 100
Status: 🟠 Poor
Confidence: high
Audit Coverage: 100% — all sources returned data

Pages Audited (5 of 5):

Summary

Site overall 50 is the mean of 5 pages. Scores range 45 (https://larsen.ee/) → 52 (https://larsen.ee/et). Weakest page: Mobile performance is catastrophic (PSI 48, LCP 47.1s) due to 69 MB page weight and 1.37 MB unused JavaScript, dragging the score into the 'Poor' band. Accessibility is compromised by 2 critical axe violations (button-name, image-alt) and 11 W3C errors including heading skips. Security headers are weak (40/100) with missing HSTS and X-Frame-Options, though no auth/payments signals reduce immediate exploitation risk. Desktop performance (43) is similarly poor, indicating systemic architectural issues rather than just mobile throttling.

Per-Page Scores

Page Score Status Confidence
https://larsen.ee/ 45 🟠 Poor high
https://larsen.ee/about 52 🟠 Poor high
https://larsen.ee/faq 52 🟠 Poor high
https://larsen.ee/terms-of-service 48 🟠 Poor high
https://larsen.ee/et 52 🟠 Poor high

PageSpeed Insights — Mobile vs Desktop

Lower is worse for Performance; higher is worse for LCP and CLS. Worse value is bolded.

URL Performance (M / D) LCP (M / D) CLS (M / D)
https://larsen.ee/ 48 / 43 47.08 s / 5.32 s 0.139 / 0.000
https://larsen.ee/about 47 / 51 36.15 s / 5.27 s 0.000 / 0.000
https://larsen.ee/faq 49 / 52 4.06 s / 3.07 s 0.651 / 0.000
https://larsen.ee/terms-of-service 27 / 55 15.99 s / 2.82 s 0.000 / 0.055
https://larsen.ee/et 53 / 44 10.50 s / 4.88 s 0.001 / 0.001

Optimization Checklist

1 of 7 passing — 1 pass · 1 warn · 5 fail

Item Status Detail
Page caching plugin / CDN active Fail No WordPress cache plugin marker or CDN edge cache detected on the document response.
Images lazy-loaded Fail 5 of 7 non-hero raster images are not lazy-loaded (threshold: 2).
Hero image eagerly loaded Fail Hero image has loading="lazy", which delays LCP (inferred from DOM order/size — Lighthouse LCP element unavailable). Use loading="eager" (or omit loading) and add fetchpriority="high".
Hero is a real <img> (not a CSS background-image) Warn Hero element uses a CSS background-image (no image-set() variants), so the browser always loads the original asset regardless of viewport — there is no srcset equivalent. Move the hero to a real <img> with srcset/sizes (or <picture>) so smaller viewports can fetch a smaller file.
Responsive images (srcset / <picture>) Fail 16/16 raster images lack srcset and are not inside <picture>.
Reasonable number of image sizes Fail No raster images use srcset; browsers cannot pick an optimally sized variant.
JS scripts not blocking in <head> Pass No render-blocking scripts in <head>.

Fixes

Priority 1: Critical

Immediate action — impacts user experience, search rankings, or site safety.

1A. Reduce JavaScript bundle and media weight to fix LCP

  • Impact: LCP (47.1s), FCP (3.6s), Total Page Weight (69 MB)
  • Problem: Mobile LCP is 47.1s with 1.37 MB unused JS (app-889782a39d4314ef1bf6.js) and 55 MB media weight causing massive load delays.
  • Solution:
    • Split the 1.37 MB app-*.js bundle using code splitting (React.lazy or dynamic imports).
    • Compress media: Convert 55 MB of images/video to WebP/AVIF and implement lazy loading.
    • Defer non-critical third-party scripts (Hotjar, PostHog) until user interaction.

1B. Fix critical accessibility violations

  • Impact: WCAG 2.1 Compliance, Screen Reader Usability
  • Problem: axe-core reports 2 critical violations: buttons lack discernible text (slider dots) and images lack alt attributes.
  • Solution:
    • Add aria-label to all slider dot buttons (e.g., aria-label="Slide 1").
    • Add descriptive alt text to all content images; use alt="" for purely decorative icons.
    • Ensure all interactive elements have accessible names.

1C. Reduce JavaScript bundle size and eliminate unused code

  • Impact: LCP, FCP, TBT, Performance Score
  • Problem: 1.4 MB of unused JavaScript detected (app-889782a39d4314ef1bf6.js alone is 1397 KB wasted), contributing to LCP of 36.2 s.
  • Solution:
    • Implement code splitting to load only necessary JS for the About page.
    • Tree-shake dependencies and remove unused third-party scripts.
    • Defer non-critical scripts (e.g., analytics, hotjar) until after main content renders.

1D. Optimize and lazy-load images

  • Impact: Page Weight, LCP, CLS
  • Problem: Images total 3.75 MB with no srcset, 6 missing lazy loading, and 1 missing alt attribute. Hero image is a CSS background.
  • Solution:
    • Convert all images to WebP/AVIF with fallbacks.
    • Add srcset and sizes attributes for responsive loading.
    • Add loading="lazy" to non-hero images.
    • Move hero CSS background to a real <img> tag with fetchpriority="high".

1E. Strengthen Content Security Policy (CSP)

  • Impact: XSS Defense, Security Score
  • Problem: CSP is weak (only frame-ancestors set). Site signals indicate user-generated content (reviews), elevating XSS risk to Priority 1 per rubric.
  • Solution:
    • Implement a strict CSP with default-src and object-src 'none'.
    • Use nonces or hashes for inline scripts rather than a permissive allowlist.
    • Example: Content-Security-Policy: default-src 'self'; script-src 'nonce-{random}' 'strict-dynamic'; object-src 'none';

1F. Fix Core Web Vitals (LCP, CLS) and Reduce JavaScript

  • Impact: Performance, LCP, CLS, TBT
  • Problem: Mobile Performance 49, LCP 4.1s (>4s penalty), CLS 0.651 (>0.25 penalty), and 1.4MB wasted JS (app-889782a39d4314ef1bf6.js).
  • Solution:
    • LCP: Remove loading="lazy" from the hero image and add fetchpriority="high".
    • CLS: Reserve space for dynamic content (cookies, ads) using CSS min-height or aspect-ratio.
    • JS: Code-split the 1.4MB app-889782a39d4314ef1bf6.js and defer non-critical third-party scripts (Hotjar, PostHog).

1G. Harden Security Headers (CSP & HSTS)

  • Impact: XSS protection, Transport security
  • Problem: Security Headers grade 40/100. HSTS max-age too short (15552000s) and missing includeSubDomains. CSP is weak (missing default-src). UGC signal present increases XSS risk.
  • Solution:
    • HSTS: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
    • CSP: Implement nonce-based CSP with strict-dynamic:
      Content-Security-Policy: default-src 'self'; script-src 'nonce-{random}' 'strict-dynamic'; object-src 'none'; base-uri 'none';
      
    • X-Frame-Options: Add X-Frame-Options: SAMEORIGIN as fallback.

1H. Reduce JavaScript bundle and defer non-critical scripts

  • Impact: TBT, LCP, FCP, Performance Score
  • Problem: 1.4 MB of unused JavaScript (GTM, PostHog, Facebook) causes 6.09 s TBT and 16.0 s LCP on mobile.
  • Solution:
    • Audit third-party scripts; remove unused tracking codes.
    • Load critical scripts inline or defer non-critical ones.
    • Use module/nomodule pattern for modern/legacy JS.
    • Implement code splitting to reduce initial bundle size.

1I. Fix Hero Image Loading Strategy

  • Impact: LCP, Performance Score
  • Problem: Hero image is lazy-loaded (loading="lazy"), delaying LCP to 16.0 s on mobile.
  • Solution:
    • Remove loading="lazy" from the hero image.
    • Add fetchpriority="high" to the hero image.
    • Ensure hero image is preloaded if it's not the first resource.

1J. Implement Strict Content Security Policy (CSP)

  • Impact: XSS Protection, Security Score
  • Problem: CSP is missing default-src and object-src, leaving the site vulnerable to XSS (site has user-generated content).
  • Solution:
    • Deploy a nonce-based CSP rather than a flat allowlist.
    • Example: Content-Security-Policy: default-src 'self'; script-src 'nonce-{random}' 'strict-dynamic'; object-src 'none';
    • Ensure all inline scripts use the nonce.

1K. Reduce page weight and optimize media delivery

  • Impact: LCP, Speed Index, Total Blocking Time
  • Problem: Total page weight is 69.19 MB (56 MB media); LCP is 10.5 s on mobile. Unused JavaScript alone is 1.37 MB.
  • Solution:
    • Compress and resize images; serve WebP/AVIF.
    • Implement lazy loading for below-fold media.
    • Remove or defer unused JavaScript (e.g., app-889782a39d4314ef1bf6.js).
    • Use a CDN with edge caching to reduce TTFB and transfer time.

1L. Harden security headers for UGC site

  • Impact: XSS, Clickjacking, Transport Security
  • Problem: Security grade is 40/100. HSTS max-age is short (15M s) and missing includeSubDomains. CSP lacks default-src. Site has user-generated content (reviews), increasing XSS risk.
  • Solution:
    • Update HSTS: max-age=31536000; includeSubDomains; preload.
    • Add X-Frame-Options: SAMEORIGIN.
    • Implement strict CSP with nonce/hash: Content-Security-Policy: default-src 'self'; script-src 'nonce-{random}' 'strict-dynamic'; object-src 'none';

Priority 2: Important

Essential for compliance, user reach, and search visibility.

2A. Strengthen Security Headers (HSTS, X-Frame-Options)

  • Impact: Transport Security, Clickjacking Protection
  • Problem: HSTS max-age is too short (15552000s) and missing directives; X-Frame-Options is missing entirely.
  • Solution:
    • Update HSTS: max-age=31536000; includeSubDomains; preload.
    • Add X-Frame-Options: SAMEORIGIN (or use CSP frame-ancestors exclusively).
    • Ensure X-Content-Type-Options: nosniff is present (currently OK).

2B. Implement Responsive Images (srcset)

  • Impact: Mobile Data Usage, LCP, CLS
  • Problem: 16/16 raster images lack srcset, forcing mobile devices to download desktop-sized assets (55 MB total media).
  • Solution:
    • Generate multiple image sizes (e.g., 400w, 800w, 1200w) for all raster images.
    • Update HTML to use <img srcset="..." sizes="..."> or <picture> elements.
    • Add explicit width and height attributes to prevent CLS.

2C. Fix HSTS and Accessibility violations

  • Impact: Transport Security, WCAG Compliance
  • Problem: HSTS max-age is too short (15552000s) and missing includeSubDomains. 5 axe violations including missing lang and alt.
  • Solution:
    • Update HSTS: Strict-Transport-Security: max-age=31536000; includeSubDomains; preload.
    • Add lang="en" to <html>.
    • Add descriptive alt text to all content images (e.g., Co-Liv.png).
    • Ensure color contrast ratios meet 4.5:1 for text.

2D. Resolve W3C HTML Errors and Structure

  • Impact: SEO, Document Outline, Validation
  • Problem: 18 W3C errors including obsolete <font> tags, missing <h1>, duplicate IDs, and charset placement issues.
  • Solution:
    • Headings: Add one <h1> at the top of the page content.
    • Tags: Replace <font> elements with CSS classes.
    • IDs: Ensure unique IDs (e.g., what-are-the-prices-of-the-rooms-and-what-does-the-price-depend-on?).
    • Charset: Move <meta charset="UTF-8"> within the first 1024 bytes.

2E. Optimize Image Delivery

  • Impact: Page Weight, CLS, Mobile Data
  • Problem: 3 images lack width/height (causing CLS), 1 missing alt, and no srcset for responsive loading.
  • Solution:
    • Dimensions: Add explicit width and height attributes to all <img> tags.
    • Responsive: Add srcset with WebP/AVIF variants for all raster images.
    • Alt: Ensure all content images have descriptive alt text; decorative images use alt="".

2F. Add Responsive Images (srcset)

  • Impact: Page Weight, LCP, CLS
  • Problem: 3/3 raster images lack srcset, preventing browsers from loading optimally sized variants.
  • Solution:
    • Generate multiple image sizes (e.g., 400w, 800w, 1200w).
    • Add srcset and sizes attributes to <img> tags.
    • Use <picture> for art direction if needed.

2G. Implement responsive images and dimensions

  • Impact: CLS, Mobile Data Usage, LCP
  • Problem: 16/16 raster images lack srcset and explicit width/height, preventing browser optimization and risking layout shifts.
  • Solution:
    • Add width and height attributes to all <img> tags.
    • Generate srcset variants (e.g., 400w, 800w, 1200w) for all raster images.
    • Wrap hero images in <picture> elements for format switching.

2H. Fix SEO metadata and HTML structure

  • Impact: Search Visibility, Crawlability
  • Problem: Missing canonical tag, robots.txt, and heading hierarchy skips (h2 → h4). W3C reports 12 errors including nested buttons inside anchors.
  • Solution:
    • Add <link rel="canonical" href="...">.
    • Ensure robots.txt exists at root.
    • Fix heading order (h2 → h3 → h4).
    • Remove <button> elements nested inside <a> tags; use <a> styled as buttons or JS event handlers.

Priority 3: Best Practice

Recommended for long-term maintainability.

3A. Resolve W3C HTML Validation Errors

  • Impact: SEO, Code Maintainability
  • Problem: 11 errors found including button inside a (x5) and heading skips (h2→h4).
  • Solution:
    • Remove button elements nested inside a tags; use a with role="button" or separate the link and button.
    • Fix heading hierarchy: Ensure h3 follows h2 without skipping levels.
    • Add lang="en" to the <html> tag.

3B. Enable proper caching and SEO metadata

  • Impact: Repeat Visit Performance, Search Indexing
  • Problem: No Cache-Control header (unpredictable caching), missing canonical tag, and missing robots meta.
  • Solution:
    • Set Cache-Control: public, max-age=31536000 for static assets.
    • Add <link rel="canonical" href="https://larsen.ee/about">.
    • Add <meta name="robots" content="index, follow">.

3C. Add Missing SEO Meta Tags

  • Impact: Search Visibility, CTR
  • Problem: Missing meta description, canonical URL, and robots meta tag.
  • Solution:
    • Add <meta name="description" content="...">.
    • Add <link rel="canonical" href="...">.
    • Add <meta name="robots" content="index, follow">.
▸Raw Markdown sent to the LLM
# Site Audit — https://larsen.ee/
Run: 2026-06-10T10:04:06.804Z

Audited **5** of 5 discovered pages.
Average per-page audit coverage: **100%**

Pages audited:
- https://larsen.ee/
- https://larsen.ee/about
- https://larsen.ee/faq
- https://larsen.ee/terms-of-service
- https://larsen.ee/et

---

# Page 1 of 5 — https://larsen.ee/

Run: 2026-06-10T10:04:07.740Z

## Audit Coverage
**100%** of audit sources returned data.

_All sources OK._

## Methodology

Each tool below contributes data to a single overall 0–100 site quality score. Performance dominates the weighting (~40%), followed by accessibility (~30%), image assets (~15%), and SEO/security (~15%). These weights are informative — the score is judged holistically, not from a fixed formula.

Severity scale in `priorities[]`:
- **high** — blocking issue / vulnerability / fail.
- **medium** — significant degradation.
- **low** — minor improvement.

Each tool section below lists: scores → priority fixes → findings → manual checks the tool cannot verify.

## Site Signals (inferred)

Heuristic site-shape signals derived from the audit data. Use these to calibrate the priority of security-header recommendations (see system rubric). Override when the evidence is clearly wrong.

- Auth surface: no
- Payments: no
- User-generated content: **yes** — anchor href contains "review"
- E-commerce: no

## PageSpeed Insights
_Captured in 29697 ms (mobile + desktop in parallel)._

**Lighthouse scores (mobile vs desktop; worse value bolded):**
| Category | Mobile | Desktop |
| --- | --- | --- |
| Performance | 48 | **43** |
| Accessibility | 74 | 74 |
| Best Practices | 96 | 96 |
| SEO | 82 | 82 |

**Core Web Vitals — lab (Lighthouse) / field (CrUX p75); worse lab value bolded:**
| Metric | Mobile | Desktop |
| --- | --- | --- |
| LCP | **47.1 s** / 2357 ms p75 (fast) | 5.3 s / 1834 ms p75 (fast) |
| CLS | **0.139** / 43 p75 (slow) | 0.000 / 39 p75 (slow) |
| TBT | 258 ms | **792 ms** |
| FCP | **3.64 s** / 2046 ms p75 (average) | 1.10 s / 1558 ms p75 (fast) |
| Speed Index | **14.70 s** | 2.22 s |
| TTFB | **78 ms** / 1160 ms p75 (average) | 39 ms / 918 ms p75 (average) |
| INP (field only) | 407 ms p75 (average) | 240 ms p75 (average) |

### Priority fixes
1. **largest-contentful-paint** (high) — 47.1 s
2. **speed-index** (high) — 14.7 s
3. **first-contentful-paint** (high) — 3.6 s
4. **cumulative-layout-shift** (low) — 0.139
5. **total-blocking-time** (low) — 260 ms

### Findings (mobile)

#### Unused JavaScript
- https://larsen.ee/client/app-889782a39d4314ef1bf6.js — 1370 KB wasted
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 69 KB wasted
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM — 68 KB wasted
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641 — 66 KB wasted
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641 — 64 KB wasted
- https://script.hotjar.com/modules.c3d712579ef0b1b5af2a.js — 38 KB wasted
- https://connect.facebook.net/en_US/fbevents.js — 34 KB wasted
- https://eu-assets.i.posthog.com/static/array.js — 32 KB wasted
- https://eu-assets.i.posthog.com/static/surveys.js?v=1.384.1 — 25 KB wasted
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 — 21 KB wasted
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 — 21 KB wasted

#### Layout-shift sources
- body > div#react-app > div.cookies — shift 0.136
- body > div#react-app > div.cookies — shift 0.003

#### Long tasks
- https://larsen.ee/client/app-889782a39d4314ef1bf6.js — 243 ms
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641 — 112 ms
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 — 98 ms
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641 — 94 ms
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 68 ms
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 — 57 ms
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 54 ms
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM — 54 ms
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM — 52 ms
- https://script.hotjar.com/modules.c3d712579ef0b1b5af2a.js — 50 ms

#### DOM size
- Total nodes: 0

#### Failing modeled audits
- SEO: `canonical`
- SEO: `robotsTxt`
- SEO: `tapTargets`
- SEO: `structuredData`
- Best Practices: `errorsInConsole`

#### All failing PSI audits (sorted by weight × failure margin)
- `largest-contentful-paint` (performance, score 0.00, weight 25) — Largest Contentful Paint — 47.1 s
- `button-name` (accessibility, score 0.00, weight 10) — Buttons do not have an accessible name
- `image-alt` (accessibility, score 0.00, weight 10) — Image elements do not have `[alt]` attributes
- `speed-index` (performance, score 0.01, weight 10) — Speed Index — 14.7 s
- `color-contrast` (accessibility, score 0.00, weight 7) — Background and foreground colors do not have a sufficient contrast ratio.
- `html-has-lang` (accessibility, score 0.00, weight 7) — `<html>` element does not have a `[lang]` attribute
- `link-name` (accessibility, score 0.00, weight 7) — Links do not have a discernible name
- `first-contentful-paint` (performance, score 0.31, weight 10) — First Contentful Paint — 3.6 s
- `cumulative-layout-shift` (performance, score 0.79, weight 25) — Cumulative Layout Shift — 0.139
- `total-blocking-time` (performance, score 0.83, weight 30) — Total Blocking Time — 260 ms
- `heading-order` (accessibility, score 0.00, weight 3) — Heading elements are not in a sequentially-descending order
- `cls-culprits-insight` (performance, score 0.00, weight 0) — Layout shift culprits
- `lcp-discovery-insight` (performance, score 0.00, weight 0) — LCP request discovery
- `network-dependency-tree-insight` (performance, score 0.00, weight 0) — Network dependency tree
- `interactive` (performance, score 0.00, weight 0) — Time to Interactive — 48.7 s
- `errors-in-console` (best-practices, score 0.00, weight 1) — Browser errors were logged to the console
- `valid-source-maps` (best-practices, score 0.00, weight 0) — Missing source maps for large first-party JavaScript
- `link-text` (seo, score 0.00, weight 1) — Links do not have descriptive text — 1 link found
- `image-alt` (seo, score 0.00, weight 1) — Image elements do not have `[alt]` attributes
- `max-potential-fid` (performance, score 0.52, weight 0) — Max Potential First Input Delay — 240 ms

### Manual checks
- Real-device behavior on slow 3G / low-tier mobile hardware (Lighthouse is throttled simulation).
- Sustained INP under typical user interaction, not just initial load.
- CrUX data interpretation if site is low-traffic and field data falls back to origin or is missing.

## Security Headers & HTTP
_Captured in 620 ms._

**Transport:**
- Final URL: https://larsen.ee/
- Status: 200
- Redirected: false
- HTTPS redirect: HTTP → HTTPS ✓

**Caching:**
- cache-control: not set
- etag: W/"cb905-X3xYS0lD8Zz8ZbhvNRbi9bN7N2Q"
- last-modified: n/a
- expires: n/a
- pragma: n/a
- vary: Accept-Encoding
- Issues:
  - no cache-control header — caching behavior is unpredictable

**Compression:**
- content-encoding: gzip
- content-length: n/a
- Decoded body: 814.3 KB

### Priority fixes
1. **strict-transport-security weak** (high) — max-age too short (15552000s, recommended >= 31536000); missing includeSubDomains directive; missing preload directive
2. **content-security-policy weak** (high) — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
3. **x-frame-options missing** (medium) — Prefer CSP frame-ancestors; X-Frame-Options as fallback
4. **weak caching policy** (medium) — no cache-control header — caching behavior is unpredictable
5. **permissions-policy missing** (low) — Declare Permissions-Policy to disable unused features
6. **cross-origin-opener-policy missing** (low) — Set COOP to same-origin to isolate browsing context
7. **cross-origin-resource-policy missing** (low) — Set CORP to same-origin or same-site to prevent cross-origin reads
8. **server header discloses technology** (low) — Server: Google Frontend

### Findings

#### Tracked headers
- **strict-transport-security** (weak, high) `max-age=15552000` — max-age too short (15552000s, recommended >= 31536000); missing includeSubDomains directive; missing preload directive
- **content-security-policy** (weak, high) `frame-ancestors https://hub.larsen.ee` — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
- **x-frame-options** (missing, medium)
- **x-content-type-options** (present, medium) `nosniff`
- **referrer-policy** (present, low) `no-referrer`
- **permissions-policy** (missing, low)
- **cross-origin-opener-policy** (missing, low)
- **cross-origin-resource-policy** (missing, low)
- **x-permitted-cross-domain-policies** (present, low) `none`

#### Info disclosure
- Server: `Google Frontend`


#### All response headers
```
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
content-encoding: gzip
content-security-policy: frame-ancestors https://hub.larsen.ee
content-type: text/html; charset=utf-8
date: Wed, 10 Jun 2026 10:04:08 GMT
etag: W/"cb905-X3xYS0lD8Zz8ZbhvNRbi9bN7N2Q"
expect-ct: max-age=0
referrer-policy: no-referrer
server: Google Frontend
strict-transport-security: max-age=15552000
transfer-encoding: chunked
vary: Accept-Encoding
via: 1.1 google
x-content-type-options: nosniff
x-dns-prefetch-control: off
x-download-options: noopen
x-permitted-cross-domain-policies: none
x-xss-protection: 0
```

### Manual checks
- Cookie attributes set via JavaScript (not visible in HTTP response).
- CORS preflight behavior under non-GET methods (only GET response headers checked).
- HSTS preload list inclusion (check hstspreload.org).
- WAF / DDoS posture beyond what static headers reveal.

## W3C HTML Validator
_Captured in 1138 ms._

**Scoring:** 11 errors · 1 warnings · 18 cosmetic (suppressed)

### Priority fixes
1. **The element “button” must not appear as a descendant of the “a” element.** (high) — x5, first at line 66
2. **An “img” element must have an “alt” attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images.** (medium) — x2, first at line 63
3. **The value of the “for” attribute of the “label” element must be the ID of a non-hidden form control.** (medium) — x2, first at line 66
4. **The heading “h4” (with computed level 4) follows the heading “h2” (with computed level 2), skipping 1 heading level.** (medium) — x2, first at line 66

### Issue groups
- (×2) [error] An “img” element must have an “alt” attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images. — first at line 63 `pt>
      <img height="1" width="1" style="display:none"
        src="https://ww`
- (×5) [error] The element “button” must not appear as a descendant of the “a” element. — first at line 66 `"/search"><button class="button button--main desktop-header__yellow-button deskt`
- (×2) [error] The value of the “for” attribute of the “label” element must be the ID of a non-hidden form control. — first at line 66 `xt-area "><label for="room-type-1">Severa`
- (×1) [warning] This document appears to be written in English. Consider adding “lang="en"” (or variant) to the “html” start tag. — first at line 2 `type html>
<html >
  <he`
- (×2) [error] The heading “h4” (with computed level 4) follows the heading “h2” (with computed level 2), skipping 1 heading level. — first at line 66 `From</div><h4 class="apartment-type-slider__price-price">559<!-`

### Manual checks
- Whether each `<section>` / `<article>` wraps semantically meaningful content.
- Language tag accuracy for multi-language pages or quoted content.
- Whether structural choices align with the document outline algorithm in screen readers.

## axe-core (Accessibility)
_Captured in 8435 ms._

**Scoring:** 7 violations · 36 passes · critical 2 · serious 3 · moderate 2 · minor 0

### Priority fixes
1. **button-name** (high) — Buttons must have discernible text
2. **image-alt** (high) — Images must have alternative text
3. **color-contrast** (high) — Elements must meet minimum color contrast ratio thresholds
4. **html-has-lang** (high) — <html> element must have a lang attribute
5. **link-name** (high) — Links must have discernible text

### Findings

#### `button-name` (critical) — WCAG: wcag2a, wcag412
[Buttons must have discernible text](https://dequeuniversity.com/rules/axe/4.11/button-name?application=playwright)
- `.apartment-type-box:nth-child(1) > .apartment-type-slider.apartment-type-box__slider-box > .slider > .slider__dots > .active.slider__dot`
- `.apartment-type-box:nth-child(1) > .apartment-type-slider.apartment-type-box__slider-box > .slider > .slider__dots > .slider__dot:nth-child(2)`
- `.apartment-type-box:nth-child(1) > .apartment-type-slider.apartment-type-box__slider-box > .slider > .slider__dots > .slider__dot:nth-child(3)`
- `.apartment-type-box:nth-child(1) > .apartment-type-slider.apartment-type-box__slider-box > .slider > .slider__dots > .slider__dot:nth-child(4)`
- `.apartment-type-box:nth-child(1) > .apartment-type-slider.apartment-type-box__slider-box > .slider > .slider__dots > .slider__dot:nth-child(5)`
- … and 15 more nodes

#### `color-contrast` (serious) — WCAG: wcag2aa, wcag143
[Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright)
- `.search-container__stay-type-input-wrapper > .search-container__value`
- `.react-datepicker-wrapper:nth-child(4) > .react-datepicker__input-container > .search-container__date-picker-input-container > .search-container__date-picker-input-wrapper > .search-container__value`
- `.react-datepicker-wrapper:nth-child(5) > .react-datepicker__input-container > .search-container__date-picker-input-container > .search-container__date-picker-input-wrapper > .search-container__value`
- `.apartment-type-box:nth-child(1) > .apartment-type-slider.apartment-type-box__slider-box > .apartment-type-slider__prices > .apartment-type-slider__price > .apartment-type-slider__price-from`
- `.apartment-type-box:nth-child(2) > .apartment-type-slider.apartment-type-box__slider-box > .apartment-type-slider__prices > .apartment-type-slider__price > .apartment-type-slider__price-from`
- … and 4 more nodes

#### `heading-order` (moderate)
[Heading levels should only increase by one](https://dequeuniversity.com/rules/axe/4.11/heading-order?application=playwright)
- `.apartment-type-box:nth-child(1) > .apartment-type-slider.apartment-type-box__slider-box > .apartment-type-slider__prices > .apartment-type-slider__price > .apartment-type-slider__price-price`
- `.other-features-container__feature:nth-child(1) > .other-features-container__title > h4`

#### `html-has-lang` (serious) — WCAG: wcag2a, wcag311
[<html> element must have a lang attribute](https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=playwright)
- `html`

#### `image-alt` (critical) — WCAG: wcag2a, wcag111
[Images must have alternative text](https://dequeuniversity.com/rules/axe/4.11/image-alt?application=playwright)
- `img[src$="Co-Liv.e0807b70.png"]`

#### `link-name` (serious) — WCAG: wcag2a, wcag244, wcag412
[Links must have discernible text](https://dequeuniversity.com/rules/axe/4.11/link-name?application=playwright)
- `.larsen-logo-wrapper > .active[aria-current="page"][href="/"]`
- `.footer__icon--facebook`
- `.footer__icon--instagram`

#### `region` (moderate)
[All page content should be contained by landmarks](https://dequeuniversity.com/rules/axe/4.11/region?application=playwright)
- `.language-switcher.fill-white[href="/et"]:nth-child(1)`
- `.language-switcher.fill-white[href="/et"]:nth-child(2)`
- `.cookies__content`

### Incomplete (axe could not determine)
- [ARIA attributes must conform to valid values](https://dequeuniversity.com/rules/axe/4.11/aria-valid-attr-value?application=playwright) — 1 node
- [Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright) — 16 nodes
- [<video> elements must have captions](https://dequeuniversity.com/rules/axe/4.11/video-caption?application=playwright) — 2 nodes

### Manual checks
- Keyboard-only navigation flow + visible focus indicators on every interactive element.
- Screen reader output (NVDA, VoiceOver) for actual auditory experience.
- Modal focus trapping and restoration on close.
- Touch target sizes (44×44 px minimum per WCAG 2.5.8).
- Color contrast for elements with alpha-transparency or gradients (axe skips these).

## Browser Runtime
_Captured in 8454 ms._

**Capture summary:** 1 console events · 0 mixed-content requests · 57 network requests · 69.10 MB total

**Network bytes by resource type:**
| Type | Count | Bytes |
| --- | --- | --- |
| media | 4 | 55.78 MB |
| image | 21 | 12.39 MB |
| script | 17 | 843.4 KB |
| font | 2 | 67.8 KB |
| stylesheet | 2 | 40.8 KB |
| xhr | 2 | 15 B |
| document | 1 | 0 B |
| fetch | 6 | 0 B |
| ping | 2 | 0 B |

**Third-party origins (by bytes):**
- https://thumbor.larsen.ee — 5 requests, 4.66 MB
- https://www.googletagmanager.com — 4 requests, 648.0 KB
- https://connect.facebook.net — 3 requests, 175.1 KB
- https://fonts.gstatic.com — 1 request, 43.8 KB
- https://www.google-analytics.com — 2 requests, 20.3 KB
- https://www.google.ee — 2 requests, 84 B
- https://region1.analytics.google.com — 3 requests, 0 B
- https://stats.g.doubleclick.net — 2 requests, 0 B
- https://pagead2.googlesyndication.com — 2 requests, 0 B
- https://static.hotjar.com — 1 request, 0 B
- https://fonts.googleapis.com — 2 requests, 0 B
- https://eu-assets.i.posthog.com — 6 requests, 0 B

**Slowest requests (top 5):**
- https://larsen.ee/ (document) — 2.86 s, 0 B
- https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&family=Inter+Tight:wght@400;500&display=swap (stylesheet) — 1.92 s, 0 B
- https://larsen.ee/client/image-placeholder.4d1b7c5c.jpg (image) — 715 ms, 97.2 KB
- https://thumbor.larsen.ee/XRxbalFyCkbJoO5TloRPcMJ_6qE=/fit-in/0x0/filters:quality(90)/https://larsen.ee/production/media/2024/04/-tun4221.jpg (image) — 535 ms, 2.13 MB
- https://thumbor.larsen.ee/_x8XSrH1ef3TBiVhXrIMQ5B6xBI=/fit-in/0x0/filters:quality(90)/https://larsen.ee/production/media/2025/09/ttun8394-hdr.jpg (image) — 535 ms, 860.4 KB

### Priority fixes
1. **failed request** (medium) — fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-9DLXLVKRKQ&gtm=45je6641v9128456099za200zd9128456099&_p=1781085850642&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=EAAAAGAC&are=1&cid=1668116980.1781085851&frm=0&ir=1&pscdl=noapi&rcb=11&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115616985~115938465~115938468&sid=1781085850&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2F&dt=Larsen%20-%20The%20Coolest%20Accommodation%20in%20Tallinn&en=page_view&_fv=1&_nsi=1&_ss=1&_ee=1&tfd=3169 — net::ERR_ABORTED
2. **failed request** (medium) — fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=4&frm=0&ae=g&en=page_view&dl=https%3A%2F%2Flarsen.ee%2F&scrsrc=www.googletagmanager.com&rnd=1367820441.1781085851&navt=n&npa=1&ep.ads_data_redaction=0&gtm=45He6641v847628427za200zd847628427xea&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115938465~115938469~119061278&apve=1&apvf=f&apvc=1&tft=1781085850992&tfd=3219 — net::ERR_ABORTED
3. **failed request** (medium) — fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-L1DE8WRGT9&gtm=45je6641v9119440986z8847628427za20gzb847628427zd847628427&_p=1781085850642&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=AAAAAGAC&are=1&cid=1668116980.1781085851&frm=0&pscdl=noapi&rcb=1&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115938465~115938468&sid=1781085851&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2F&dt=Larsen%20-%20The%20Coolest%20Accommodation%20in%20Tallinn&en=page_view&_fv=1&_ss=1&tfd=3568 — net::ERR_ABORTED

### Findings

#### Failed requests
- fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-9DLXLVKRKQ&gtm=45je6641v9128456099za200zd9128456099&_p=1781085850642&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=EAAAAGAC&are=1&cid=1668116980.1781085851&frm=0&ir=1&pscdl=noapi&rcb=11&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115616985~115938465~115938468&sid=1781085850&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2F&dt=Larsen%20-%20The%20Coolest%20Accommodation%20in%20Tallinn&en=page_view&_fv=1&_nsi=1&_ss=1&_ee=1&tfd=3169 — net::ERR_ABORTED
- fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=4&frm=0&ae=g&en=page_view&dl=https%3A%2F%2Flarsen.ee%2F&scrsrc=www.googletagmanager.com&rnd=1367820441.1781085851&navt=n&npa=1&ep.ads_data_redaction=0&gtm=45He6641v847628427za200zd847628427xea&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115938465~115938469~119061278&apve=1&apvf=f&apvc=1&tft=1781085850992&tfd=3219 — net::ERR_ABORTED
- fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-L1DE8WRGT9&gtm=45je6641v9119440986z8847628427za20gzb847628427zd847628427&_p=1781085850642&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=AAAAAGAC&are=1&cid=1668116980.1781085851&frm=0&pscdl=noapi&rcb=1&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115938465~115938468&sid=1781085851&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2F&dt=Larsen%20-%20The%20Coolest%20Accommodation%20in%20Tallinn&en=page_view&_fv=1&_ss=1&tfd=3568 — net::ERR_ABORTED
- fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=15&frm=0&en=page_view&dl=https%3A%2F%2Flarsen.ee%2F&scrsrc=www.googletagmanager.com&rnd=1367820441.1781085851&navt=n&npa=1&gtm=45be6641v9218844185z8847628427za20gzb847628427zd847628427xec&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115616985~115938465~115938468~117776794~119061278&apve=1&apvf=f&apvc=0&tids=AW-17042172798&tid=AW-17042172798&tft=1781085851401&tfd=3628 — net::ERR_ABORTED
- media: https://larsen.ee/production/media/2023/video-files/Larsen%20-%20Kokkuvo%CC%83te%20eng%20bars.mp4 — net::ERR_ABORTED
- media: https://larsen.ee/videos/uus-logota-larsen-video-2.mp4 — net::ERR_ABORTED
- fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-9DLXLVKRKQ&gtm=45je6641v9128456099za200zd9128456099&_p=1781085850642&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=EEAAAGQC&ae=a&are=1&cid=1668116980.1781085851&frm=0&ir=1&pscdl=noapi&rcb=11&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=2&tag_exp=0~115616985~115938465~115938468&sid=1781085850&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2F&dt=Larsen%20-%20The%20Coolest%20Accommodation%20in%20Tallinn&en=scroll&epn.percent_scrolled=90&_et=4&tfd=8174 — net::ERR_ABORTED

#### Console events
- [warning] Hotjar not launching due to suspicious userAgent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/148.0.7778.96 Safari/537.36 (https://static.hotjar.com/c/hotjar-3296638.js?sv=7)

### Manual checks
- Console output during user interaction (load-only capture).
- Behavior on slow networks and constrained devices.
- WebGL / canvas FPS profiling via DevTools Layers panel.
- Service worker / cache behavior on repeat visits.

## HTML Inventory
_Captured in 8454 ms._

**Document:**
- Lang: not set
- Title: Larsen - The Coolest Accommodation in Tallinn
- Canonical: not set
- Viewport: width=device-width
- Charset: UTF-8
- HTML bytes: 850029

**Meta tags:**
- Description: Looking for a stress-free rental experience in Tallinn? Look no further than Larsen, your trusted accommodation service provider. From short-term to long-term rentals, our fully furnished apartments offer the perfect solution for your accommodation needs. Discover the Larsen difference today and enjoy the ultimate in comfort and convenience.
- Robots: not set
- Theme color: #ffffff
- Open Graph tags: 3 (og:title, og:description, og:image)
- Twitter tags: 0
- hreflang: none
- JSON-LD: none

**Heading outline:**
- Counts: h1 ×1, h2 ×21, h3 ×6, h4 ×14, h5 ×0, h6 ×0
- Sequence (first 20):
  - h1: Tallinn accommodation made easy
  - h2: Everyone's welcome here -  no bureaucracy, no hassle.
  - h4: 559 €
  - h3: Sume Loft with Balcony
  - h4: 489 €
  - h3: Sume Twin Studio with Balcony
  - h4: 459 €
  - h3: Sume Studio with Balcony
  - h4: 54 €
  - h4: 419 €
  - h3: Eduard House Studio L
  - h2: Looking for something else?
  - h2: Eduard House
  - h2: Instant booking, no hassle
  - h2: Join our vibrant community
  - h2: Why stay with Larsen?
  - h4: Flexible length of stay
  - h4: Instant booking
  - h4: Fully furnished
  - h4: Co-living areas
- Skips:
  - h2 → h4 after "Everyone's welcome here -  no bureaucracy, no hassle."
  - h2 → h4 after "Why stay with Larsen?"

**Landmarks:**
- nav: present
- main: present
- header: **missing**
- footer: present
- Skip-to-content link: **missing**

**Scripts:** 26 total — 0 defer, 16 async, 1 render-blocking. Speculation rules: no.

External scripts (first 15):
- https://eu-assets.i.posthog.com/static/array.js (async)
- https://static.hotjar.com/c/hotjar-3296638.js?sv=7 (async)
- https://www.google-analytics.com/analytics.js (async)
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641 (async)
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641 (async)
- https://connect.facebook.net/signals/config/1726152210919905?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171%2C231%2C230%2C225%2C227%2C228%2C229%2C226%2C214%2C224%2C196%2C193%2C194%2C188%2C192%2C195%2C191%2C186%2C322%2C199%2C189%2C190%2C218%2C187%2C185%2C238%2C209%2C179%2C180%2C175%2C181%2C178%2C176%2C177%2C174%2C172%2C183%2C184%2C182%2C269%2C321%2C291%2C289%2C290%2C288%2C197%2C241%2C247%2C242%2C244%2C246%2C245%2C243%2C240%2C256%2C251%2C253%2C250%2C257%2C254%2C249%2C255%2C252%2C248%2C284%2C295 (async)
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 (async)
- https://connect.facebook.net/en_US/fbevents.js (async)
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM (async)
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ (async)
- https://eu-assets.i.posthog.com/static/web-vitals.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/dead-clicks-autocapture.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/surveys.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/array/phc_9AAcqE521KLngxSgpVorPQDkU4ENZA9RJXVJnkr12nN/config.js (async)

**Stylesheets:** 1 external, 2 inline (1.2 KB)

**Images:** 16 total — **1 without alt**, **16 without width/height**, 4 without loading="lazy"

Image inventory (first 15):
| src | alt | w×h | loading | srcset |
| --- | --- | --- | --- | --- |
| s://larsen.ee/images/uus-logota-larsen-video-2-thumbnail.jpg | thumbnail of the video | _n/a_ | _n/a_ | ✗ |
| ttps://larsen.ee/production/media/2023/11/maja-fasssad-2.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| s://larsen.ee/production/media/2025/03/rocca-house-drone.png | _(empty)_ | _n/a_ | lazy | ✗ |
| 0)/https://larsen.ee/production/media/2021/12/img-1042-1.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| /larsen.ee/production/media/2024/09/dji-0044-enhanced-nr.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| (90)/https://larsen.ee/production/media/2025/11/ttun8888.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| /https://larsen.ee/production/media/2025/11/ttun8720-hdr.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| /https://larsen.ee/production/media/2025/09/ttun8103-hdr.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| /https://larsen.ee/production/media/2025/09/ttun8394-hdr.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| (90)/https://larsen.ee/production/media/2024/04/-tun4221.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| ttps://larsen.ee/production/media/2023/11/maja-fasssad-2.jpg | Building image | _n/a_ | lazy | ✗ |
| https://larsen.ee/images/rectangle/Rectangle-158.png | imageOne | _n/a_ | _n/a_ | ✗ |
| https://larsen.ee/images/rectangle/Rectangle-159.png | imageOne | _n/a_ | _n/a_ | ✗ |
| lity(90)/https://larsen.ee/production/media/2024/07/karl.png | _(empty)_ | _n/a_ | lazy | ✗ |
| https://larsen.ee/production/media/2022/03/ehrl-blue-eng.png | _(empty)_ | _n/a_ | lazy | ✗ |

**Links:** 36 anchors — 3 external, 1 preconnect, 0 preload.

Vague repeated link text:
- "all available rooms" ×2

### Priority fixes
1. **Heading level skips** (medium) — h2→h4 after "Everyone's welcome here -  no bureaucrac"; h2→h4 after "Why stay with Larsen?"
2. **Missing skip-to-content link** (medium) — No anchor link with "skip" / "otse sisu" text found
3. **1 images without alt attribute** (high) — Content images need descriptive alt text; decorative images need empty alt=""
4. **16 images without explicit width/height** (medium) — Missing dimensions can cause layout shifts (CLS)

### Manual checks
- Visual rendering of detected mojibake (browser may auto-correct for display).
- Whether decorative images correctly use empty `alt=""` (vs. content images missing it).
- Whether headings reflect actual document hierarchy semantically.
- Whether vague link text is disambiguated by `aria-label` or surrounding context.

## Optimized-Web Checklist
_Captured in 0 ms._

**Summary:** 1 pass · 3 warn · 3 fail

**Checklist:**
| Item | Status | Detail |
| --- | --- | --- |
| Page caching plugin / CDN active | ✗ fail | No WordPress cache plugin marker or CDN edge cache detected on the document response. |
| Images lazy-loaded | ! warn | 3 of 15 non-hero raster images are not lazy-loaded. |
| Hero image eagerly loaded | ! warn | Hero image has no explicit loading or fetchpriority (inferred from DOM order/size — Lighthouse LCP element unavailable). Browser default is eager but adding fetchpriority="high" helps LCP. |
| Hero is a real <img> (not a CSS background-image) | ! warn | Hero element uses a CSS background-image (no image-set() variants), so the browser always loads the original asset regardless of viewport — there is no srcset equivalent. Move the hero to a real <img> with srcset/sizes (or <picture>) so smaller viewports can fetch a smaller file. |
| Responsive images (srcset / <picture>) | ✗ fail | 16/16 raster images lack srcset and are not inside <picture>. |
| Reasonable number of image sizes | ✗ fail | No raster images use srcset; browsers cannot pick an optimally sized variant. |
| JS scripts not blocking in <head> | ✓ pass | No render-blocking scripts in <head>. |

**Evidence:**
- Images lazy-loaded:
  - `https://larsen.ee/images/rectangle/Rectangle-158.png`
  - `https://larsen.ee/images/rectangle/Rectangle-159.png`
  - `https://larsen.ee/client/Co-Liv.e0807b70.png`
- Hero image eagerly loaded:
  - `hero: https://larsen.ee/images/uus-logota-larsen-video-2-thumbnail.jpg`
  - `loading: (not set)`
  - `fetchpriority: (not set)`
- Hero is a real <img> (not a CSS background-image):
  - `selector: div.buildings-map__map-overlay`
  - `url: https://larsen.ee/client/Tallinn.d777459c.png`
  - `box: 520×1021px`
- Responsive images (srcset / <picture>):
  - `https://larsen.ee/images/uus-logota-larsen-video-2-thumbnail.jpg`
  - `…ers:quality(90)/https://larsen.ee/production/media/2023/11/maja-fasssad-2.jpg`
  - `…:quality(90)/https://larsen.ee/production/media/2025/03/rocca-house-drone.png`
  - `…filters:quality(90)/https://larsen.ee/production/media/2021/12/img-1042-1.jpg`
  - `…ality(90)/https://larsen.ee/production/media/2024/09/dji-0044-enhanced-nr.jpg`

### Priority fixes
1. **Page caching plugin / CDN active** (high) — No WordPress cache plugin marker or CDN edge cache detected on the document response.
2. **Responsive images (srcset / <picture>)** (high) — 16/16 raster images lack srcset and are not inside <picture>.
3. **Reasonable number of image sizes** (high) — No raster images use srcset; browsers cannot pick an optimally sized variant.
4. **Images lazy-loaded** (medium) — 3 of 15 non-hero raster images are not lazy-loaded.
5. **Hero image eagerly loaded** (medium) — Hero image has no explicit loading or fetchpriority (inferred from DOM order/size — Lighthouse LCP element unavailable). Browser default is eager but adding fetchpriority="high" helps LCP.
6. **Hero is a real <img> (not a CSS background-image)** (medium) — Hero element uses a CSS background-image (no image-set() variants), so the browser always loads the original asset regardless of viewport — there is no srcset equivalent. Move the hero to a real <img> with srcset/sizes (or <picture>) so smaller viewports can fetch a smaller file.

### Manual checks
- Cart / checkout / logged-in pages must bypass the page cache or load dynamic regions via AJAX.
- Verify the cache is warmed for the canonical URL on initial deploy (first visitor should not pay the cold-start cost).
- Inspect "hero" image visually — heuristic above picks the first/largest <img>, which may not match the actual LCP element on JS-heavy pages.
- Confirm scripts marked as defer/async actually tolerate deferred execution (some legacy snippets break when reordered).

---

# Page 2 of 5 — https://larsen.ee/about

Run: 2026-06-10T10:04:07.743Z

## Audit Coverage
**100%** of audit sources returned data.

_All sources OK._

## Methodology

Each tool below contributes data to a single overall 0–100 site quality score. Performance dominates the weighting (~40%), followed by accessibility (~30%), image assets (~15%), and SEO/security (~15%). These weights are informative — the score is judged holistically, not from a fixed formula.

Severity scale in `priorities[]`:
- **high** — blocking issue / vulnerability / fail.
- **medium** — significant degradation.
- **low** — minor improvement.

Each tool section below lists: scores → priority fixes → findings → manual checks the tool cannot verify.

## Site Signals (inferred)

Heuristic site-shape signals derived from the audit data. Use these to calibrate the priority of security-header recommendations (see system rubric). Override when the evidence is clearly wrong.

- Auth surface: no
- Payments: no
- User-generated content: **yes** — anchor href contains "review"
- E-commerce: no

## PageSpeed Insights
_Captured in 21563 ms (mobile + desktop in parallel)._

**Lighthouse scores (mobile vs desktop; worse value bolded):**
| Category | Mobile | Desktop |
| --- | --- | --- |
| Performance | **47** | 51 |
| Accessibility | 82 | 82 |
| Best Practices | 100 | 100 |
| SEO | 91 | 91 |

**Core Web Vitals — lab (Lighthouse) / field (CrUX p75); worse lab value bolded:**
| Metric | Mobile | Desktop |
| --- | --- | --- |
| LCP | **36.2 s** / 3555 ms p75 (average) | 5.3 s / 2726 ms p75 (average) |
| CLS | 0.000 / 6 p75 (fast) | **0.000** / 43 p75 (slow) |
| TBT | 357 ms | **597 ms** |
| FCP | **11.26 s** / 3280 ms p75 (slow) | 1.06 s / 2197 ms p75 (average) |
| Speed Index | **13.12 s** | 1.16 s |
| TTFB | 24 ms / 2621 ms p75 (slow) | **25 ms** / 1414 ms p75 (average) |
| INP (field only) | 390 ms p75 (average) | 245 ms p75 (average) |

### Priority fixes
1. **largest-contentful-paint** (high) — 36.2 s
2. **first-contentful-paint** (high) — 11.3 s
3. **speed-index** (high) — 13.1 s
4. **total-blocking-time** (medium) — 360 ms
5. **cache-insight** (high) — Est savings of 839 KiB

### Findings (mobile)

#### Unused JavaScript
- https://larsen.ee/client/app-889782a39d4314ef1bf6.js — 1397 KB wasted
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 67 KB wasted
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM — 67 KB wasted
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641 — 65 KB wasted
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641 — 62 KB wasted
- https://script.hotjar.com/modules.c3d712579ef0b1b5af2a.js — 38 KB wasted
- https://connect.facebook.net/en_US/fbevents.js — 34 KB wasted
- https://eu-assets.i.posthog.com/static/array.js — 32 KB wasted
- https://eu-assets.i.posthog.com/static/surveys.js?v=1.384.1 — 25 KB wasted
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 — 22 KB wasted
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 — 21 KB wasted

#### Long tasks
- https://larsen.ee/client/app-889782a39d4314ef1bf6.js — 270 ms
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641 — 128 ms
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641 — 115 ms
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 — 101 ms
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 72 ms
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM — 71 ms
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 — 70 ms
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 66 ms
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM — 62 ms
- https://connect.facebook.net/en_US/fbevents.js — 54 ms

#### DOM size
- Total nodes: 0

#### Failing modeled audits
- SEO: `canonical`
- SEO: `robotsTxt`
- SEO: `tapTargets`
- SEO: `structuredData`

#### All failing PSI audits (sorted by weight × failure margin)
- `largest-contentful-paint` (performance, score 0.00, weight 25) — Largest Contentful Paint — 36.2 s
- `first-contentful-paint` (performance, score 0.00, weight 10) — First Contentful Paint — 11.3 s
- `image-alt` (accessibility, score 0.00, weight 10) — Image elements do not have `[alt]` attributes
- `speed-index` (performance, score 0.02, weight 10) — Speed Index — 13.1 s
- `total-blocking-time` (performance, score 0.72, weight 30) — Total Blocking Time — 360 ms
- `color-contrast` (accessibility, score 0.00, weight 7) — Background and foreground colors do not have a sufficient contrast ratio.
- `html-has-lang` (accessibility, score 0.00, weight 7) — `<html>` element does not have a `[lang]` attribute
- `link-name` (accessibility, score 0.00, weight 7) — Links do not have a discernible name
- `network-dependency-tree-insight` (performance, score 0.00, weight 0) — Network dependency tree
- `interactive` (performance, score 0.00, weight 0) — Time to Interactive — 36.2 s
- `valid-source-maps` (best-practices, score 0.00, weight 0) — Missing source maps for large first-party JavaScript
- `image-alt` (seo, score 0.00, weight 1) — Image elements do not have `[alt]` attributes
- `max-potential-fid` (performance, score 0.44, weight 0) — Max Potential First Input Delay — 270 ms

### Manual checks
- Real-device behavior on slow 3G / low-tier mobile hardware (Lighthouse is throttled simulation).
- Sustained INP under typical user interaction, not just initial load.
- CrUX data interpretation if site is low-traffic and field data falls back to origin or is missing.

## Security Headers & HTTP
_Captured in 173 ms._

**Transport:**
- Final URL: https://larsen.ee/about
- Status: 200
- Redirected: false
- HTTPS redirect: HTTP → HTTPS ✓

**Caching:**
- cache-control: not set
- etag: W/"2262f-KA+BNc0tq7B3P3JRCzf9mSg2crM"
- last-modified: n/a
- expires: n/a
- pragma: n/a
- vary: Accept-Encoding
- Issues:
  - no cache-control header — caching behavior is unpredictable

**Compression:**
- content-encoding: gzip
- content-length: n/a
- Decoded body: 137.5 KB

### Priority fixes
1. **strict-transport-security weak** (high) — max-age too short (15552000s, recommended >= 31536000); missing includeSubDomains directive; missing preload directive
2. **content-security-policy weak** (high) — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
3. **x-frame-options missing** (medium) — Prefer CSP frame-ancestors; X-Frame-Options as fallback
4. **weak caching policy** (medium) — no cache-control header — caching behavior is unpredictable
5. **permissions-policy missing** (low) — Declare Permissions-Policy to disable unused features
6. **cross-origin-opener-policy missing** (low) — Set COOP to same-origin to isolate browsing context
7. **cross-origin-resource-policy missing** (low) — Set CORP to same-origin or same-site to prevent cross-origin reads
8. **server header discloses technology** (low) — Server: Google Frontend

### Findings

#### Tracked headers
- **strict-transport-security** (weak, high) `max-age=15552000` — max-age too short (15552000s, recommended >= 31536000); missing includeSubDomains directive; missing preload directive
- **content-security-policy** (weak, high) `frame-ancestors https://hub.larsen.ee` — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
- **x-frame-options** (missing, medium)
- **x-content-type-options** (present, medium) `nosniff`
- **referrer-policy** (present, low) `no-referrer`
- **permissions-policy** (missing, low)
- **cross-origin-opener-policy** (missing, low)
- **cross-origin-resource-policy** (missing, low)
- **x-permitted-cross-domain-policies** (present, low) `none`

#### Info disclosure
- Server: `Google Frontend`


#### All response headers
```
alt-svc: h3=":443"; ma=2592000
content-encoding: gzip
content-security-policy: frame-ancestors https://hub.larsen.ee
content-type: text/html; charset=utf-8
date: Wed, 10 Jun 2026 10:04:07 GMT
etag: W/"2262f-KA+BNc0tq7B3P3JRCzf9mSg2crM"
expect-ct: max-age=0
referrer-policy: no-referrer
server: Google Frontend
strict-transport-security: max-age=15552000
transfer-encoding: chunked
vary: Accept-Encoding
via: 1.1 google
x-content-type-options: nosniff
x-dns-prefetch-control: off
x-download-options: noopen
x-permitted-cross-domain-policies: none
x-xss-protection: 0
```

### Manual checks
- Cookie attributes set via JavaScript (not visible in HTTP response).
- CORS preflight behavior under non-GET methods (only GET response headers checked).
- HSTS preload list inclusion (check hstspreload.org).
- WAF / DDoS posture beyond what static headers reveal.

## W3C HTML Validator
_Captured in 732 ms._

**Scoring:** 3 errors · 1 warnings · 20 cosmetic (suppressed)

### Priority fixes
1. **An “img” element must have an “alt” attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images.** (medium) — x2, first at line 63
2. **The element “button” must not appear as a descendant of the “a” element.** (medium) — x1, first at line 66

### Issue groups
- (×2) [error] An “img” element must have an “alt” attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images. — first at line 63 `pt>
      <img height="1" width="1" style="display:none"
        src="https://ww`
- (×1) [error] The element “button” must not appear as a descendant of the “a” element. — first at line 66 `"/search"><button class="button button--main desktop-header__yellow-button deskt`
- (×1) [warning] This document appears to be written in English. Consider adding “lang="en"” (or variant) to the “html” start tag. — first at line 2 `type html>
<html >
  <he`

### Manual checks
- Whether each `<section>` / `<article>` wraps semantically meaningful content.
- Language tag accuracy for multi-language pages or quoted content.
- Whether structural choices align with the document outline algorithm in screen readers.

## axe-core (Accessibility)
_Captured in 3731 ms._

**Scoring:** 5 violations · 33 passes · critical 1 · serious 3 · moderate 1 · minor 0

### Priority fixes
1. **image-alt** (high) — Images must have alternative text
2. **color-contrast** (high) — Elements must meet minimum color contrast ratio thresholds
3. **html-has-lang** (high) — <html> element must have a lang attribute
4. **link-name** (high) — Links must have discernible text
5. **region** (medium) — All page content should be contained by landmarks

### Findings

#### `color-contrast` (serious) — WCAG: wcag2aa, wcag143
[Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright)
- `a[href$="about"] > .text`

#### `html-has-lang` (serious) — WCAG: wcag2a, wcag311
[<html> element must have a lang attribute](https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=playwright)
- `html`

#### `image-alt` (critical) — WCAG: wcag2a, wcag111
[Images must have alternative text](https://dequeuniversity.com/rules/axe/4.11/image-alt?application=playwright)
- `img[src$="Co-Liv.e0807b70.png"]`

#### `link-name` (serious) — WCAG: wcag2a, wcag244, wcag412
[Links must have discernible text](https://dequeuniversity.com/rules/axe/4.11/link-name?application=playwright)
- `.active[aria-current="page"][href="/"]`
- `.footer__icon--facebook`
- `.footer__icon--instagram`

#### `region` (moderate)
[All page content should be contained by landmarks](https://dequeuniversity.com/rules/axe/4.11/region?application=playwright)
- `.language-switcher.active[href$="meist"]`
- `.language-switcher.fill-white[href$="meist"]:nth-child(2)`
- `.cookies__content`

### Incomplete (axe could not determine)
- [ARIA attributes must conform to valid values](https://dequeuniversity.com/rules/axe/4.11/aria-valid-attr-value?application=playwright) — 1 node
- [Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright) — 5 nodes

### Manual checks
- Keyboard-only navigation flow + visible focus indicators on every interactive element.
- Screen reader output (NVDA, VoiceOver) for actual auditory experience.
- Modal focus trapping and restoration on close.
- Touch target sizes (44×44 px minimum per WCAG 2.5.8).
- Color contrast for elements with alpha-transparency or gradients (axe skips these).

## Browser Runtime
_Captured in 3739 ms._

**Capture summary:** 1 console events · 0 mixed-content requests · 40 network requests · 4.60 MB total

**Network bytes by resource type:**
| Type | Count | Bytes |
| --- | --- | --- |
| image | 9 | 3.75 MB |
| script | 17 | 765.8 KB |
| font | 2 | 67.8 KB |
| stylesheet | 2 | 40.8 KB |
| xhr | 2 | 15 B |
| document | 1 | 0 B |
| fetch | 5 | 0 B |
| ping | 2 | 0 B |

**Third-party origins (by bytes):**
- https://www.googletagmanager.com — 4 requests, 648.0 KB
- https://connect.facebook.net — 3 requests, 97.5 KB
- https://fonts.gstatic.com — 1 request, 43.8 KB
- https://www.google-analytics.com — 2 requests, 20.3 KB
- https://www.google.ee — 2 requests, 84 B
- https://fonts.googleapis.com — 2 requests, 0 B
- https://eu-assets.i.posthog.com — 6 requests, 0 B
- https://region1.analytics.google.com — 2 requests, 0 B
- https://stats.g.doubleclick.net — 2 requests, 0 B
- https://static.hotjar.com — 1 request, 0 B
- https://pagead2.googlesyndication.com — 2 requests, 0 B
- https://www.chatbase.co — 2 requests, 0 B

**Slowest requests (top 5):**
- https://connect.facebook.net/en_US/fbevents.js (script) — 769 ms, 97.5 KB
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM (script) — 768 ms, 159.2 KB
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ (script) — 525 ms, 177.7 KB
- https://fonts.gstatic.com/s/intertight/v9/NGSwv5HMAFg6IuGlBNMjxLsH8ag.woff2 (font) — 518 ms, 43.8 KB
- https://region1.analytics.google.com/g/collect?v=2&tid=G-9DLXLVKRKQ&gtm=45je6641v9128456099za200zd9128456099&_p=1781085847929&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=EAAAAGAC&are=1&cid=1183638079.1781085849&frm=0&ir=1&pscdl=noapi&rcb=17&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115938466~115938468&sid=1781085848&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2Fabout&dt=About%20Larsen&en=page_view&_fv=1&_nsi=1&_ss=1&_ee=1&tfd=922 (fetch) — 436 ms, 0 B

### Priority fixes
1. **failed request** (medium) — fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-9DLXLVKRKQ&gtm=45je6641v9128456099za200zd9128456099&_p=1781085847929&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=EAAAAGAC&are=1&cid=1183638079.1781085849&frm=0&ir=1&pscdl=noapi&rcb=17&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115938466~115938468&sid=1781085848&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2Fabout&dt=About%20Larsen&en=page_view&_fv=1&_nsi=1&_ss=1&_ee=1&tfd=922 — net::ERR_ABORTED
2. **failed request** (medium) — fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=2&frm=0&ae=g&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Fabout&scrsrc=www.googletagmanager.com&rnd=349637489.1781085849&navt=n&npa=1&ep.ads_data_redaction=0&gtm=45He6641v847628427za200zd847628427xea&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115616986~115938466~115938468&apve=1&apvf=f&apvc=1&tft=1781085849176&tfd=1401 — net::ERR_ABORTED
3. **failed request** (medium) — fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=14&frm=0&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Fabout&scrsrc=www.googletagmanager.com&rnd=349637489.1781085849&navt=n&npa=1&gtm=45be6641v9218844185z8847628427za20gzb847628427zd847628427xec&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115616986~115938466~115938469&apve=1&apvf=f&apvc=0&tids=AW-17042172798&tid=AW-17042172798&tft=1781085849306&tfd=1531 — net::ERR_ABORTED

### Findings

#### Failed requests
- fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-9DLXLVKRKQ&gtm=45je6641v9128456099za200zd9128456099&_p=1781085847929&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=EAAAAGAC&are=1&cid=1183638079.1781085849&frm=0&ir=1&pscdl=noapi&rcb=17&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115938466~115938468&sid=1781085848&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2Fabout&dt=About%20Larsen&en=page_view&_fv=1&_nsi=1&_ss=1&_ee=1&tfd=922 — net::ERR_ABORTED
- fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=2&frm=0&ae=g&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Fabout&scrsrc=www.googletagmanager.com&rnd=349637489.1781085849&navt=n&npa=1&ep.ads_data_redaction=0&gtm=45He6641v847628427za200zd847628427xea&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115616986~115938466~115938468&apve=1&apvf=f&apvc=1&tft=1781085849176&tfd=1401 — net::ERR_ABORTED
- fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=14&frm=0&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Fabout&scrsrc=www.googletagmanager.com&rnd=349637489.1781085849&navt=n&npa=1&gtm=45be6641v9218844185z8847628427za20gzb847628427zd847628427xec&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115616986~115938466~115938469&apve=1&apvf=f&apvc=0&tids=AW-17042172798&tid=AW-17042172798&tft=1781085849306&tfd=1531 — net::ERR_ABORTED
- fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-L1DE8WRGT9&gtm=45je6641v9119440986z8847628427za20gzb847628427zd847628427&_p=1781085847929&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=AAAAAGAC&are=1&cid=1183638079.1781085849&frm=0&pscdl=noapi&rcb=8&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115616986~115938466~115938468~119061279&sid=1781085849&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2Fabout&dt=About%20Larsen&en=page_view&_fv=1&_ss=1&tfd=1589 — net::ERR_ABORTED

#### Console events
- [warning] Hotjar not launching due to suspicious userAgent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/148.0.7778.96 Safari/537.36 (https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1)

### Manual checks
- Console output during user interaction (load-only capture).
- Behavior on slow networks and constrained devices.
- WebGL / canvas FPS profiling via DevTools Layers panel.
- Service worker / cache behavior on repeat visits.

## HTML Inventory
_Captured in 3739 ms._

**Document:**
- Lang: not set
- Title: About Larsen
- Canonical: not set
- Viewport: width=device-width
- Charset: UTF-8
- HTML bytes: 152901

**Meta tags:**
- Description: Learn more about Larsen
- Robots: not set
- Theme color: #ffffff
- Open Graph tags: 3 (og:title, og:description, og:image)
- Twitter tags: 0
- hreflang: none
- JSON-LD: none

**Heading outline:**
- Counts: h1 ×1, h2 ×18, h3 ×2, h4 ×1, h5 ×0, h6 ×0
- Sequence (first 20):
  - h1: About & Contact
  - h2: Finding a place to stay can be a stressful undertaking.
  - h2: But it doesn't have to be like that.
  - h2: Larsen houses offer a selection of fully furnished rooms
  - h2: Sounds good? Then book via this website or get in touch if you have further ques
  - h2: Navigate
  - h2: Home
  - h2: Rooms
  - h2: Locations
  - h2: Features
  - h2: Testimonials
  - h2: About & Contact
  - h2: FAQ
  - h2: Kuubik Storages
  - h2: For customers
  - h2: Report an issue
  - h2: House rules
  - h2: Contract preview
  - h2: Customer support
  - h3: Karl Limbak

**Landmarks:**
- nav: present
- main: present
- header: **missing**
- footer: present
- Skip-to-content link: **missing**

**Scripts:** 26 total — 0 defer, 16 async, 1 render-blocking. Speculation rules: no.

External scripts (first 15):
- https://static.hotjar.com/c/hotjar-3296638.js?sv=7 (async)
- https://www.google-analytics.com/analytics.js (async)
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641 (async)
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641 (async)
- https://eu-assets.i.posthog.com/static/array.js (async)
- https://connect.facebook.net/signals/config/1726152210919905?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171%2C231%2C230%2C225%2C227%2C228%2C229%2C226%2C214%2C224%2C196%2C193%2C194%2C188%2C192%2C195%2C191%2C186%2C322%2C199%2C189%2C190%2C218%2C187%2C185%2C238%2C209%2C179%2C180%2C175%2C181%2C178%2C176%2C177%2C174%2C172%2C183%2C184%2C182%2C269%2C321%2C291%2C289%2C290%2C288%2C197%2C241%2C247%2C242%2C244%2C246%2C245%2C243%2C240%2C256%2C251%2C253%2C250%2C257%2C254%2C249%2C255%2C252%2C248%2C284%2C295 (async)
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 (async)
- https://connect.facebook.net/en_US/fbevents.js (async)
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM (async)
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ (async)
- https://eu-assets.i.posthog.com/static/web-vitals.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/dead-clicks-autocapture.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/surveys.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/array/phc_9AAcqE521KLngxSgpVorPQDkU4ENZA9RJXVJnkr12nN/config.js (async)

**Stylesheets:** 1 external, 2 inline (1.2 KB)

**Images:** 8 total — **1 without alt**, **8 without width/height**, 6 without loading="lazy"

Image inventory (first 15):
| src | alt | w×h | loading | srcset |
| --- | --- | --- | --- | --- |
| https://larsen.ee/images/features/about_and_contact/1.jpg | imageOne | _n/a_ | _n/a_ | ✗ |
| https://larsen.ee/images/features/about_and_contact/2.jpg | imageTwo | _n/a_ | _n/a_ | ✗ |
| https://larsen.ee/images/features/about_and_contact/3.jpg | imageOne | _n/a_ | _n/a_ | ✗ |
| https://larsen.ee/images/features/about_and_contact/4.jpg | imageTwo | _n/a_ | _n/a_ | ✗ |
| https://larsen.ee/images/features/about_and_contact/5.jpg | imageOne | _n/a_ | _n/a_ | ✗ |
| lity(90)/https://larsen.ee/production/media/2024/07/karl.png | _(empty)_ | _n/a_ | lazy | ✗ |
| https://larsen.ee/production/media/2022/03/ehrl-blue-eng.png | _(empty)_ | _n/a_ | lazy | ✗ |
| https://larsen.ee/client/Co-Liv.e0807b70.png | _(no attr)_ | _n/a_ | _n/a_ | ✗ |

**Links:** 20 anchors — 3 external, 1 preconnect, 0 preload.

### Priority fixes
1. **Missing skip-to-content link** (medium) — No anchor link with "skip" / "otse sisu" text found
2. **1 images without alt attribute** (high) — Content images need descriptive alt text; decorative images need empty alt=""
3. **8 images without explicit width/height** (medium) — Missing dimensions can cause layout shifts (CLS)

### Manual checks
- Visual rendering of detected mojibake (browser may auto-correct for display).
- Whether decorative images correctly use empty `alt=""` (vs. content images missing it).
- Whether headings reflect actual document hierarchy semantically.
- Whether vague link text is disambiguated by `aria-label` or surrounding context.

## Optimized-Web Checklist
_Captured in 0 ms._

**Summary:** 1 pass · 2 warn · 4 fail

**Checklist:**
| Item | Status | Detail |
| --- | --- | --- |
| Page caching plugin / CDN active | ✗ fail | No WordPress cache plugin marker or CDN edge cache detected on the document response. |
| Images lazy-loaded | ✗ fail | 5 of 7 non-hero raster images are not lazy-loaded (threshold: 2). |
| Hero image eagerly loaded | ! warn | Hero image has no explicit loading or fetchpriority (inferred from DOM order/size — Lighthouse LCP element unavailable). Browser default is eager but adding fetchpriority="high" helps LCP. |
| Hero is a real <img> (not a CSS background-image) | ! warn | Hero element uses a CSS background-image (no image-set() variants), so the browser always loads the original asset regardless of viewport — there is no srcset equivalent. Move the hero to a real <img> with srcset/sizes (or <picture>) so smaller viewports can fetch a smaller file. |
| Responsive images (srcset / <picture>) | ✗ fail | 8/8 raster images lack srcset and are not inside <picture>. |
| Reasonable number of image sizes | ✗ fail | No raster images use srcset; browsers cannot pick an optimally sized variant. |
| JS scripts not blocking in <head> | ✓ pass | No render-blocking scripts in <head>. |

**Evidence:**
- Images lazy-loaded:
  - `https://larsen.ee/images/features/about_and_contact/2.jpg`
  - `https://larsen.ee/images/features/about_and_contact/3.jpg`
  - `https://larsen.ee/images/features/about_and_contact/4.jpg`
  - `https://larsen.ee/images/features/about_and_contact/5.jpg`
  - `https://larsen.ee/client/Co-Liv.e0807b70.png`
- Hero image eagerly loaded:
  - `hero: https://larsen.ee/images/features/about_and_contact/1.jpg`
  - `loading: (not set)`
  - `fetchpriority: (not set)`
- Hero is a real <img> (not a CSS background-image):
  - `selector: div.single-feature-page__title-container`
  - `url: https://larsen.ee/images/features/about_and_contact/hero_about_and_contact.jpg`
  - `box: 1280×576px`
- Responsive images (srcset / <picture>):
  - `https://larsen.ee/images/features/about_and_contact/1.jpg`
  - `https://larsen.ee/images/features/about_and_contact/2.jpg`
  - `https://larsen.ee/images/features/about_and_contact/3.jpg`
  - `https://larsen.ee/images/features/about_and_contact/4.jpg`
  - `https://larsen.ee/images/features/about_and_contact/5.jpg`

### Priority fixes
1. **Page caching plugin / CDN active** (high) — No WordPress cache plugin marker or CDN edge cache detected on the document response.
2. **Images lazy-loaded** (high) — 5 of 7 non-hero raster images are not lazy-loaded (threshold: 2).
3. **Responsive images (srcset / <picture>)** (high) — 8/8 raster images lack srcset and are not inside <picture>.
4. **Reasonable number of image sizes** (high) — No raster images use srcset; browsers cannot pick an optimally sized variant.
5. **Hero image eagerly loaded** (medium) — Hero image has no explicit loading or fetchpriority (inferred from DOM order/size — Lighthouse LCP element unavailable). Browser default is eager but adding fetchpriority="high" helps LCP.
6. **Hero is a real <img> (not a CSS background-image)** (medium) — Hero element uses a CSS background-image (no image-set() variants), so the browser always loads the original asset regardless of viewport — there is no srcset equivalent. Move the hero to a real <img> with srcset/sizes (or <picture>) so smaller viewports can fetch a smaller file.

### Manual checks
- Cart / checkout / logged-in pages must bypass the page cache or load dynamic regions via AJAX.
- Verify the cache is warmed for the canonical URL on initial deploy (first visitor should not pay the cold-start cost).
- Inspect "hero" image visually — heuristic above picks the first/largest <img>, which may not match the actual LCP element on JS-heavy pages.
- Confirm scripts marked as defer/async actually tolerate deferred execution (some legacy snippets break when reordered).

---

# Page 3 of 5 — https://larsen.ee/faq

Run: 2026-06-10T10:04:29.307Z

## Audit Coverage
**100%** of audit sources returned data.

_All sources OK._

## Methodology

Each tool below contributes data to a single overall 0–100 site quality score. Performance dominates the weighting (~40%), followed by accessibility (~30%), image assets (~15%), and SEO/security (~15%). These weights are informative — the score is judged holistically, not from a fixed formula.

Severity scale in `priorities[]`:
- **high** — blocking issue / vulnerability / fail.
- **medium** — significant degradation.
- **low** — minor improvement.

Each tool section below lists: scores → priority fixes → findings → manual checks the tool cannot verify.

## Site Signals (inferred)

Heuristic site-shape signals derived from the audit data. Use these to calibrate the priority of security-header recommendations (see system rubric). Override when the evidence is clearly wrong.

- Auth surface: no
- Payments: no
- User-generated content: **yes** — anchor href contains "review"
- E-commerce: no

## PageSpeed Insights
_Captured in 22836 ms (mobile + desktop in parallel)._

**Lighthouse scores (mobile vs desktop; worse value bolded):**
| Category | Mobile | Desktop |
| --- | --- | --- |
| Performance | **49** | 52 |
| Accessibility | 80 | 80 |
| Best Practices | 100 | 100 |
| SEO | 91 | 91 |

**Core Web Vitals — lab (Lighthouse) / field (CrUX p75); worse lab value bolded:**
| Metric | Mobile | Desktop |
| --- | --- | --- |
| LCP | **4.1 s** / 3555 ms p75 (average) | 3.1 s / 2726 ms p75 (average) |
| CLS | **0.651** / 6 p75 (fast) | 0.000 / 43 p75 (slow) |
| TBT | 292 ms | **870 ms** |
| FCP | **3.16 s** / 3280 ms p75 (slow) | 998 ms / 2197 ms p75 (average) |
| Speed Index | **4.99 s** | 1.56 s |
| TTFB | **14 ms** / 2621 ms p75 (slow) | 13 ms / 1414 ms p75 (average) |
| INP (field only) | 390 ms p75 (average) | 245 ms p75 (average) |

### Priority fixes
1. **cumulative-layout-shift** (high) — 0.651
2. **largest-contentful-paint** (high) — 4.1 s
3. **total-blocking-time** (low) — 290 ms
4. **first-contentful-paint** (high) — 3.2 s
5. **speed-index** (medium) — 5.0 s

### Findings (mobile)

#### Unused JavaScript
- https://larsen.ee/client/app-889782a39d4314ef1bf6.js — 1398 KB wasted
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 69 KB wasted
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM — 68 KB wasted
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641 — 66 KB wasted
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641 — 64 KB wasted
- https://script.hotjar.com/modules.c3d712579ef0b1b5af2a.js — 38 KB wasted
- https://connect.facebook.net/en_US/fbevents.js — 34 KB wasted
- https://eu-assets.i.posthog.com/static/array.js — 32 KB wasted
- https://eu-assets.i.posthog.com/static/surveys.js?v=1.384.1 — 25 KB wasted
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 — 21 KB wasted
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 — 21 KB wasted

#### Layout-shift sources
- body > div#react-app > div.page — shift 0.648
- body > div#react-app > div.cookies — shift 0.003

#### Long tasks
- https://larsen.ee/client/app-889782a39d4314ef1bf6.js — 213 ms
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641 — 121 ms
- Unattributable — 99 ms
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 — 96 ms
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641 — 93 ms
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 80 ms
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM — 68 ms
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM — 64 ms
- https://connect.facebook.net/en_US/fbevents.js — 59 ms
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 — 54 ms

#### DOM size
- Total nodes: 0

#### Failing modeled audits
- SEO: `canonical`
- SEO: `robotsTxt`
- SEO: `tapTargets`
- SEO: `structuredData`

#### All failing PSI audits (sorted by weight × failure margin)
- `cumulative-layout-shift` (performance, score 0.09, weight 25) — Cumulative Layout Shift — 0.651
- `largest-contentful-paint` (performance, score 0.48, weight 25) — Largest Contentful Paint — 4.1 s
- `image-alt` (accessibility, score 0.00, weight 10) — Image elements do not have `[alt]` attributes
- `color-contrast` (accessibility, score 0.00, weight 7) — Background and foreground colors do not have a sufficient contrast ratio.
- `html-has-lang` (accessibility, score 0.00, weight 7) — `<html>` element does not have a `[lang]` attribute
- `link-name` (accessibility, score 0.00, weight 7) — Links do not have a discernible name
- `total-blocking-time` (performance, score 0.79, weight 30) — Total Blocking Time — 290 ms
- `first-contentful-paint` (performance, score 0.44, weight 10) — First Contentful Paint — 3.2 s
- `speed-index` (performance, score 0.63, weight 10) — Speed Index — 5.0 s
- `landmark-one-main` (accessibility, score 0.00, weight 3) — Document does not have a main landmark.
- `cls-culprits-insight` (performance, score 0.00, weight 0) — Layout shift culprits
- `network-dependency-tree-insight` (performance, score 0.00, weight 0) — Network dependency tree
- `valid-source-maps` (best-practices, score 0.00, weight 0) — Missing source maps for large first-party JavaScript
- `image-alt` (seo, score 0.00, weight 1) — Image elements do not have `[alt]` attributes
- `interactive` (performance, score 0.03, weight 0) — Time to Interactive — 19.0 s
- `max-potential-fid` (performance, score 0.62, weight 0) — Max Potential First Input Delay — 210 ms

### Manual checks
- Real-device behavior on slow 3G / low-tier mobile hardware (Lighthouse is throttled simulation).
- Sustained INP under typical user interaction, not just initial load.
- CrUX data interpretation if site is low-traffic and field data falls back to origin or is missing.

## Security Headers & HTTP
_Captured in 211 ms._

**Transport:**
- Final URL: https://larsen.ee/faq
- Status: 200
- Redirected: false
- HTTPS redirect: HTTP → HTTPS ✓

**Caching:**
- cache-control: not set
- etag: W/"3bc31-sRrOZaVz6Aji8/DxSUTKNVf3Yc8"
- last-modified: n/a
- expires: n/a
- pragma: n/a
- vary: Accept-Encoding
- Issues:
  - no cache-control header — caching behavior is unpredictable

**Compression:**
- content-encoding: gzip
- content-length: n/a
- Decoded body: 239.0 KB

### Priority fixes
1. **strict-transport-security weak** (high) — max-age too short (15552000s, recommended >= 31536000); missing includeSubDomains directive; missing preload directive
2. **content-security-policy weak** (high) — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
3. **x-frame-options missing** (medium) — Prefer CSP frame-ancestors; X-Frame-Options as fallback
4. **weak caching policy** (medium) — no cache-control header — caching behavior is unpredictable
5. **permissions-policy missing** (low) — Declare Permissions-Policy to disable unused features
6. **cross-origin-opener-policy missing** (low) — Set COOP to same-origin to isolate browsing context
7. **cross-origin-resource-policy missing** (low) — Set CORP to same-origin or same-site to prevent cross-origin reads
8. **server header discloses technology** (low) — Server: Google Frontend

### Findings

#### Tracked headers
- **strict-transport-security** (weak, high) `max-age=15552000` — max-age too short (15552000s, recommended >= 31536000); missing includeSubDomains directive; missing preload directive
- **content-security-policy** (weak, high) `frame-ancestors https://hub.larsen.ee` — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
- **x-frame-options** (missing, medium)
- **x-content-type-options** (present, medium) `nosniff`
- **referrer-policy** (present, low) `no-referrer`
- **permissions-policy** (missing, low)
- **cross-origin-opener-policy** (missing, low)
- **cross-origin-resource-policy** (missing, low)
- **x-permitted-cross-domain-policies** (present, low) `none`

#### Info disclosure
- Server: `Google Frontend`


#### All response headers
```
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
content-encoding: gzip
content-security-policy: frame-ancestors https://hub.larsen.ee
content-type: text/html; charset=utf-8
date: Wed, 10 Jun 2026 10:04:29 GMT
etag: W/"3bc31-sRrOZaVz6Aji8/DxSUTKNVf3Yc8"
expect-ct: max-age=0
referrer-policy: no-referrer
server: Google Frontend
strict-transport-security: max-age=15552000
transfer-encoding: chunked
vary: Accept-Encoding
via: 1.1 google
x-content-type-options: nosniff
x-dns-prefetch-control: off
x-download-options: noopen
x-permitted-cross-domain-policies: none
x-xss-protection: 0
```

### Manual checks
- Cookie attributes set via JavaScript (not visible in HTTP response).
- CORS preflight behavior under non-GET methods (only GET response headers checked).
- HSTS preload list inclusion (check hstspreload.org).
- WAF / DDoS posture beyond what static headers reveal.

## W3C HTML Validator
_Captured in 552 ms._

**Scoring:** 18 errors · 3 warnings · 15 cosmetic (suppressed)

### Priority fixes
1. **The “font” element is obsolete. Use CSS instead.** (high) — x7, first at line 66
2. **No “p” element in scope but a “p” end tag seen.** (medium) — x4, first at line 67
3. **An “img” element must have an “alt” attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images.** (medium) — x2, first at line 63
4. **CSS: “color”: Parse Error.** (medium) — x2, first at line 67
5. **A “charset” attribute on a “meta” element found after the first 1024 bytes.** (medium) — x1, first at line 35

### Issue groups
- (×1) [error] A “charset” attribute on a “meta” element found after the first 1024 bytes. — first at line 35 `charset="UTF-8">
    <title d`
- (×2) [error] An “img” element must have an “alt” attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images. — first at line 63 `pt>
      <img height="1" width="1" style="display:none"
        src="https://ww`
- (×1) [error] The element “button” must not appear as a descendant of the “a” element. — first at line 66 `"/search"><button class="button button--main desktop-header__yellow-button deskt`
- (×7) [error] The “font” element is obsolete. Use CSS instead. — first at line 66 `style=""><font color="#000000"><span`
- (×1) [error] Duplicate ID “what-are-the-prices-of-the-rooms-and-what-does-the-price-depend-on?”. — first at line 66 `div></div><div class="accordion-wrapper  " id="what-are-the-prices-of-the-rooms-`
- (×1) [warning] The first occurrence of ID “what-are-the-prices-of-the-rooms-and-what-does-the-price-depend-on?” was here. — first at line 66 `div></div><div class="accordion-wrapper  " id="what-are-the-prices-of-the-rooms-`
- (×4) [error] No “p” element in scope but a “p” end tag seen. — first at line 67 `an></font></p><p cla`
- (×2) [error] CSS: “color”: Parse Error. — first at line 67 `></div><p><span style="background-color: rgba(255,255,255,var(--tw-bg-opacity));`
- (×1) [warning] This document appears to be written in English. Consider adding “lang="en"” (or variant) to the “html” start tag. — first at line 2 `type html>
<html >
  <he`
- (×1) [warning] This document has heading elements but none of them has a computed heading level of 1. — first at line 66 `s="topic"><h3 id="long-term-booking" class="topic-title h3">Long-T`

### Manual checks
- Whether each `<section>` / `<article>` wraps semantically meaningful content.
- Language tag accuracy for multi-language pages or quoted content.
- Whether structural choices align with the document outline algorithm in screen readers.

## axe-core (Accessibility)
_Captured in 3320 ms._

**Scoring:** 7 violations · 29 passes · critical 1 · serious 3 · moderate 3 · minor 0

### Priority fixes
1. **image-alt** (high) — Images must have alternative text
2. **color-contrast** (high) — Elements must meet minimum color contrast ratio thresholds
3. **html-has-lang** (high) — <html> element must have a lang attribute
4. **link-name** (high) — Links must have discernible text
5. **landmark-one-main** (medium) — Document should have one main landmark

### Findings

#### `color-contrast` (serious) — WCAG: wcag2aa, wcag143
[Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright)
- `a[href$="faq"] > h2`

#### `html-has-lang` (serious) — WCAG: wcag2a, wcag311
[<html> element must have a lang attribute](https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=playwright)
- `html`

#### `image-alt` (critical) — WCAG: wcag2a, wcag111
[Images must have alternative text](https://dequeuniversity.com/rules/axe/4.11/image-alt?application=playwright)
- `img[src$="Co-Liv.e0807b70.png"]`

#### `landmark-one-main` (moderate)
[Document should have one main landmark](https://dequeuniversity.com/rules/axe/4.11/landmark-one-main?application=playwright)
- `html`

#### `link-name` (serious) — WCAG: wcag2a, wcag244, wcag412
[Links must have discernible text](https://dequeuniversity.com/rules/axe/4.11/link-name?application=playwright)
- `.active[aria-current="page"][href="/"]`
- `.footer__icon--facebook`
- `.footer__icon--instagram`

#### `page-has-heading-one` (moderate)
[Page should contain a level-one heading](https://dequeuniversity.com/rules/axe/4.11/page-has-heading-one?application=playwright)
- `html`

#### `region` (moderate)
[All page content should be contained by landmarks](https://dequeuniversity.com/rules/axe/4.11/region?application=playwright)
- `.language-switcher.active[href$="kkk"]`
- `.language-switcher.fill-black[href$="kkk"]:nth-child(2)`
- `.page`
- `.cookies__content`

### Incomplete (axe could not determine)
- [ARIA attributes must conform to valid values](https://dequeuniversity.com/rules/axe/4.11/aria-valid-attr-value?application=playwright) — 1 node
- [Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright) — 18 nodes

### Manual checks
- Keyboard-only navigation flow + visible focus indicators on every interactive element.
- Screen reader output (NVDA, VoiceOver) for actual auditory experience.
- Modal focus trapping and restoration on close.
- Touch target sizes (44×44 px minimum per WCAG 2.5.8).
- Color contrast for elements with alpha-transparency or gradients (axe skips these).

## Browser Runtime
_Captured in 3338 ms._

**Capture summary:** 1 console events · 0 mixed-content requests · 35 network requests · 1.21 MB total

**Network bytes by resource type:**
| Type | Count | Bytes |
| --- | --- | --- |
| script | 17 | 844.5 KB |
| image | 3 | 267.0 KB |
| font | 3 | 91.3 KB |
| stylesheet | 2 | 40.8 KB |
| xhr | 2 | 15 B |
| document | 1 | 0 B |
| fetch | 5 | 0 B |
| ping | 2 | 0 B |

**Third-party origins (by bytes):**
- https://www.googletagmanager.com — 4 requests, 649.1 KB
- https://connect.facebook.net — 3 requests, 175.1 KB
- https://fonts.gstatic.com — 1 request, 43.8 KB
- https://www.google-analytics.com — 2 requests, 20.3 KB
- https://www.google.ee — 2 requests, 84 B
- https://fonts.googleapis.com — 2 requests, 0 B
- https://eu-assets.i.posthog.com — 6 requests, 0 B
- https://region1.analytics.google.com — 2 requests, 0 B
- https://stats.g.doubleclick.net — 2 requests, 0 B
- https://static.hotjar.com — 1 request, 0 B
- https://pagead2.googlesyndication.com — 2 requests, 0 B
- https://www.chatbase.co — 2 requests, 0 B

**Slowest requests (top 5):**
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ (script) — 368 ms, 178.7 KB
- https://connect.facebook.net/en_US/fbevents.js (script) — 366 ms, 97.5 KB
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM (script) — 366 ms, 159.2 KB
- https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500;600;700&family=Inter+Tight:wght@400;500&display=swap (xhr) — 361 ms, 0 B
- https://www.chatbase.co/api/get-chatbot-styles/y7CotFfAzSHKzmcew7JaK (fetch) — 336 ms, 0 B

### Priority fixes
1. **failed request** (medium) — fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-9DLXLVKRKQ&gtm=45je6690h2v9128456099za200zd9128456099&_p=1781085869496&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=EAAAAGAC&are=1&cid=1246322957.1781085870&frm=0&ir=1&pscdl=noapi&rcb=19&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115616985~115938466~115938468&sid=1781085869&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2Ffaq&dt=Larsen%20Accommodation%20FAQ%20%E2%80%93%20Contracts%2C%20Payments%2C%20Check-In%20%26%20More&en=page_view&_fv=1&_nsi=1&_ss=1&_ee=1&tfd=651 — net::ERR_ABORTED
2. **failed request** (medium) — fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=10&frm=0&ae=g&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Ffaq&scrsrc=www.googletagmanager.com&rnd=19571068.1781085870&navt=n&npa=1&ep.ads_data_redaction=0&gtm=45He6641v847628427za200zd847628427xea&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115616986~115938466~115938469~119061279&apve=1&apvf=f&apvc=1&tft=1781085870067&tfd=734 — net::ERR_ABORTED
3. **failed request** (medium) — fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=7&frm=0&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Ffaq&scrsrc=www.googletagmanager.com&rnd=19571068.1781085870&navt=n&npa=1&gtm=45be6641v9218844185z8847628427za20gzb847628427zd847628427xec&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115938466~115938469&apve=1&apvf=f&apvc=0&tids=AW-17042172798&tid=AW-17042172798&tft=1781085870246&tfd=912 — net::ERR_ABORTED

### Findings

#### Failed requests
- fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-9DLXLVKRKQ&gtm=45je6690h2v9128456099za200zd9128456099&_p=1781085869496&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=EAAAAGAC&are=1&cid=1246322957.1781085870&frm=0&ir=1&pscdl=noapi&rcb=19&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115616985~115938466~115938468&sid=1781085869&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2Ffaq&dt=Larsen%20Accommodation%20FAQ%20%E2%80%93%20Contracts%2C%20Payments%2C%20Check-In%20%26%20More&en=page_view&_fv=1&_nsi=1&_ss=1&_ee=1&tfd=651 — net::ERR_ABORTED
- fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=10&frm=0&ae=g&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Ffaq&scrsrc=www.googletagmanager.com&rnd=19571068.1781085870&navt=n&npa=1&ep.ads_data_redaction=0&gtm=45He6641v847628427za200zd847628427xea&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115616986~115938466~115938469~119061279&apve=1&apvf=f&apvc=1&tft=1781085870067&tfd=734 — net::ERR_ABORTED
- fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=7&frm=0&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Ffaq&scrsrc=www.googletagmanager.com&rnd=19571068.1781085870&navt=n&npa=1&gtm=45be6641v9218844185z8847628427za20gzb847628427zd847628427xec&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115938466~115938469&apve=1&apvf=f&apvc=0&tids=AW-17042172798&tid=AW-17042172798&tft=1781085870246&tfd=912 — net::ERR_ABORTED
- fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-L1DE8WRGT9&gtm=45je6641v9119440986z8847628427za20gzb847628427zd847628427&_p=1781085869496&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=AAAAAGAC&are=1&cid=1246322957.1781085870&frm=0&pscdl=noapi&rcb=7&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115616985~115938466~115938469&sid=1781085870&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2Ffaq&dt=Larsen%20Accommodation%20FAQ%20%E2%80%93%20Contracts%2C%20Payments%2C%20Check-In%20%26%20More&en=page_view&_fv=1&_ss=1&tfd=956 — net::ERR_ABORTED

#### Console events
- [warning] Hotjar not launching due to suspicious userAgent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/148.0.7778.96 Safari/537.36 (https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1)

### Manual checks
- Console output during user interaction (load-only capture).
- Behavior on slow networks and constrained devices.
- WebGL / canvas FPS profiling via DevTools Layers panel.
- Service worker / cache behavior on repeat visits.

## HTML Inventory
_Captured in 3338 ms._

**Document:**
- Lang: not set
- Title: Larsen Accommodation FAQ – Contracts, Payments, Check-In & More
- Canonical: not set
- Viewport: width=device-width
- Charset: UTF-8
- HTML bytes: 256700

**Meta tags:**
- Description: Find answers to common questions about staying at Larsen — including contract terms, payments, deposits, utilities, check-in info, and long-term housing support.
- Robots: not set
- Theme color: #ffffff
- Open Graph tags: 3 (og:title, og:description, og:image)
- Twitter tags: 0
- hreflang: none
- JSON-LD: none

**Heading outline:**
- Counts: h1 ×0, h2 ×14, h3 ×18, h4 ×1, h5 ×0, h6 ×0
- Sequence (first 20):
  - h3: Long-Term booking
  - h3: Short-Term booking
  - h3: Payments
  - h3: Houses and room types
  - h3: Arrival
  - h3: Parking
  - h3: Pets
  - h3: Room and house change
  - h3: In your new room
  - h3: Larsen community
  - h3: Departure
  - h3: Extension
  - h3: Cancellation
  - h3: Contacts
  - h3: Legal Residence & Documents
  - h3: Storages -  Kuubik
  - h2: Navigate
  - h2: Home
  - h2: Rooms
  - h2: Locations

**Landmarks:**
- nav: present
- main: **missing**
- header: **missing**
- footer: present
- Skip-to-content link: **missing**

**Scripts:** 26 total — 0 defer, 16 async, 1 render-blocking. Speculation rules: no.

External scripts (first 15):
- https://static.hotjar.com/c/hotjar-3296638.js?sv=7 (async)
- https://www.google-analytics.com/analytics.js (async)
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641 (async)
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641 (async)
- https://eu-assets.i.posthog.com/static/array.js (async)
- https://connect.facebook.net/signals/config/1726152210919905?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171%2C231%2C230%2C225%2C227%2C228%2C229%2C226%2C214%2C224%2C196%2C193%2C194%2C188%2C192%2C195%2C191%2C186%2C322%2C199%2C189%2C190%2C218%2C187%2C185%2C238%2C209%2C179%2C180%2C175%2C181%2C178%2C176%2C177%2C174%2C172%2C183%2C184%2C182%2C269%2C321%2C291%2C289%2C290%2C288%2C197%2C241%2C247%2C242%2C244%2C246%2C245%2C243%2C240%2C256%2C251%2C253%2C250%2C257%2C254%2C249%2C255%2C252%2C248%2C284%2C295 (async)
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 (async)
- https://connect.facebook.net/en_US/fbevents.js (async)
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM (async)
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ (async)
- https://eu-assets.i.posthog.com/static/web-vitals.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/dead-clicks-autocapture.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/surveys.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/array/phc_9AAcqE521KLngxSgpVorPQDkU4ENZA9RJXVJnkr12nN/config.js (async)

**Stylesheets:** 1 external, 2 inline (1.2 KB)

**Images:** 3 total — **1 without alt**, **3 without width/height**, 1 without loading="lazy"

Image inventory (first 15):
| src | alt | w×h | loading | srcset |
| --- | --- | --- | --- | --- |
| lity(90)/https://larsen.ee/production/media/2024/07/karl.png | _(empty)_ | _n/a_ | lazy | ✗ |
| https://larsen.ee/production/media/2022/03/ehrl-blue-eng.png | _(empty)_ | _n/a_ | lazy | ✗ |
| https://larsen.ee/client/Co-Liv.e0807b70.png | _(no attr)_ | _n/a_ | _n/a_ | ✗ |

**Links:** 46 anchors — 22 external, 1 preconnect, 0 preload.

Vague repeated link text:
- "support@larsen.ee" ×6
- "hello@larsen.ee" ×4
- "report an issue" ×2

### Priority fixes
1. **Document has 0 <h1> elements** (high) — A page should have exactly one h1; multiple h1s break document outline
2. **Missing skip-to-content link** (medium) — No anchor link with "skip" / "otse sisu" text found
3. **1 images without alt attribute** (high) — Content images need descriptive alt text; decorative images need empty alt=""
4. **3 images without explicit width/height** (medium) — Missing dimensions can cause layout shifts (CLS)

### Manual checks
- Visual rendering of detected mojibake (browser may auto-correct for display).
- Whether decorative images correctly use empty `alt=""` (vs. content images missing it).
- Whether headings reflect actual document hierarchy semantically.
- Whether vague link text is disambiguated by `aria-label` or surrounding context.

## Optimized-Web Checklist
_Captured in 0 ms._

**Summary:** 2 pass · 0 warn · 4 fail · 1 n/a

**Checklist:**
| Item | Status | Detail |
| --- | --- | --- |
| Page caching plugin / CDN active | ✗ fail | No WordPress cache plugin marker or CDN edge cache detected on the document response. |
| Images lazy-loaded | ✓ pass | All non-hero raster images use loading="lazy" except one. |
| Hero image eagerly loaded | ✗ fail | Hero image has loading="lazy", which delays LCP (inferred from DOM order/size — Lighthouse LCP element unavailable). Use loading="eager" (or omit loading) and add fetchpriority="high". |
| Hero is a real <img> (not a CSS background-image) | – n/a | No CSS background-images detected on raster-image-eligible elements. |
| Responsive images (srcset / <picture>) | ✗ fail | 3/3 raster images lack srcset and are not inside <picture>. |
| Reasonable number of image sizes | ✗ fail | No raster images use srcset; browsers cannot pick an optimally sized variant. |
| JS scripts not blocking in <head> | ✓ pass | No render-blocking scripts in <head>. |

**Evidence:**
- Images lazy-loaded:
  - `https://larsen.ee/client/Co-Liv.e0807b70.png`
- Hero image eagerly loaded:
  - `hero: …256x0/filters:quality(90)/https://larsen.ee/production/media/2024/07/karl.png`
  - `loading: lazy`
  - `fetchpriority: (not set)`
- Responsive images (srcset / <picture>):
  - `…256x0/filters:quality(90)/https://larsen.ee/production/media/2024/07/karl.png`
  - `…ters:quality(90)/https://larsen.ee/production/media/2022/03/ehrl-blue-eng.png`
  - `https://larsen.ee/client/Co-Liv.e0807b70.png`

### Priority fixes
1. **Page caching plugin / CDN active** (high) — No WordPress cache plugin marker or CDN edge cache detected on the document response.
2. **Hero image eagerly loaded** (high) — Hero image has loading="lazy", which delays LCP (inferred from DOM order/size — Lighthouse LCP element unavailable). Use loading="eager" (or omit loading) and add fetchpriority="high".
3. **Responsive images (srcset / <picture>)** (high) — 3/3 raster images lack srcset and are not inside <picture>.
4. **Reasonable number of image sizes** (high) — No raster images use srcset; browsers cannot pick an optimally sized variant.

### Manual checks
- Cart / checkout / logged-in pages must bypass the page cache or load dynamic regions via AJAX.
- Verify the cache is warmed for the canonical URL on initial deploy (first visitor should not pay the cold-start cost).
- Inspect "hero" image visually — heuristic above picks the first/largest <img>, which may not match the actual LCP element on JS-heavy pages.
- Confirm scripts marked as defer/async actually tolerate deferred execution (some legacy snippets break when reordered).

---

# Page 4 of 5 — https://larsen.ee/terms-of-service

Run: 2026-06-10T10:04:37.438Z

## Audit Coverage
**100%** of audit sources returned data.

_All sources OK._

## Methodology

Each tool below contributes data to a single overall 0–100 site quality score. Performance dominates the weighting (~40%), followed by accessibility (~30%), image assets (~15%), and SEO/security (~15%). These weights are informative — the score is judged holistically, not from a fixed formula.

Severity scale in `priorities[]`:
- **high** — blocking issue / vulnerability / fail.
- **medium** — significant degradation.
- **low** — minor improvement.

Each tool section below lists: scores → priority fixes → findings → manual checks the tool cannot verify.

## Site Signals (inferred)

Heuristic site-shape signals derived from the audit data. Use these to calibrate the priority of security-header recommendations (see system rubric). Override when the evidence is clearly wrong.

- Auth surface: no
- Payments: no
- User-generated content: **yes** — anchor href contains "review"
- E-commerce: no

## PageSpeed Insights
_Captured in 61351 ms (mobile + desktop in parallel)._

**Lighthouse scores (mobile vs desktop; worse value bolded):**
| Category | Mobile | Desktop |
| --- | --- | --- |
| Performance | **27** | 55 |
| Accessibility | 84 | 84 |
| Best Practices | 100 | 100 |
| SEO | 82 | 82 |

**Core Web Vitals — lab (Lighthouse) / field (CrUX p75); worse lab value bolded:**
| Metric | Mobile | Desktop |
| --- | --- | --- |
| LCP | **16.0 s** / 3555 ms p75 (average) | 2.8 s / 2726 ms p75 (average) |
| CLS | 0.000 / 6 p75 (fast) | **0.055** / 43 p75 (slow) |
| TBT | **6.09 s** | 961 ms |
| FCP | **4.72 s** / 3280 ms p75 (slow) | 772 ms / 2197 ms p75 (average) |
| Speed Index | **11.26 s** | 772 ms |
| TTFB | 7 ms / 2621 ms p75 (slow) | **30 ms** / 1414 ms p75 (average) |
| INP (field only) | 390 ms p75 (average) | 245 ms p75 (average) |

### Priority fixes
1. **total-blocking-time** (high) — 6,090 ms
2. **largest-contentful-paint** (high) — 16.0 s
3. **speed-index** (high) — 11.3 s
4. **first-contentful-paint** (high) — 4.7 s
5. **cache-insight** (high) — Est savings of 491 KiB

### Findings (mobile)

#### Unused JavaScript
- https://larsen.ee/client/app-889782a39d4314ef1bf6.js — 1398 KB wasted
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 67 KB wasted
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM — 67 KB wasted
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641 — 65 KB wasted
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641 — 61 KB wasted
- https://script.hotjar.com/modules.c3d712579ef0b1b5af2a.js — 38 KB wasted
- https://connect.facebook.net/en_US/fbevents.js — 34 KB wasted
- https://eu-assets.i.posthog.com/static/array.js — 32 KB wasted
- https://eu-assets.i.posthog.com/static/surveys.js?v=1.384.1 — 25 KB wasted
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 — 21 KB wasted
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 — 21 KB wasted

#### Long tasks
- https://larsen.ee/client/app-889782a39d4314ef1bf6.js — 1.38 s
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM — 967 ms
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641 — 856 ms
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 — 710 ms
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 598 ms
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641 — 581 ms
- https://connect.facebook.net/en_US/fbevents.js — 478 ms
- https://eu-assets.i.posthog.com/static/array.js — 374 ms
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 — 358 ms
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 352 ms

#### DOM size
- Total nodes: 0

#### Failing modeled audits
- SEO: `metaDescription`
- SEO: `canonical`
- SEO: `robotsTxt`
- SEO: `tapTargets`
- SEO: `structuredData`

#### All failing PSI audits (sorted by weight × failure margin)
- `total-blocking-time` (performance, score 0.00, weight 30) — Total Blocking Time — 6,090 ms
- `largest-contentful-paint` (performance, score 0.00, weight 25) — Largest Contentful Paint — 16.0 s
- `image-alt` (accessibility, score 0.00, weight 10) — Image elements do not have `[alt]` attributes
- `speed-index` (performance, score 0.05, weight 10) — Speed Index — 11.3 s
- `first-contentful-paint` (performance, score 0.12, weight 10) — First Contentful Paint — 4.7 s
- `html-has-lang` (accessibility, score 0.00, weight 7) — `<html>` element does not have a `[lang]` attribute
- `link-name` (accessibility, score 0.00, weight 7) — Links do not have a discernible name
- `landmark-one-main` (accessibility, score 0.00, weight 3) — Document does not have a main landmark.
- `forced-reflow-insight` (performance, score 0.00, weight 0) — Forced reflow
- `lcp-breakdown-insight` (performance, score 0.00, weight 0) — LCP breakdown
- `network-dependency-tree-insight` (performance, score 0.00, weight 0) — Network dependency tree
- `max-potential-fid` (performance, score 0.00, weight 0) — Max Potential First Input Delay — 1,380 ms
- `valid-source-maps` (best-practices, score 0.00, weight 0) — Missing source maps for large first-party JavaScript
- `meta-description` (seo, score 0.00, weight 1) — Document does not have a meta description
- `image-alt` (seo, score 0.00, weight 1) — Image elements do not have `[alt]` attributes
- `interactive` (performance, score 0.01, weight 0) — Time to Interactive — 21.9 s

### Manual checks
- Real-device behavior on slow 3G / low-tier mobile hardware (Lighthouse is throttled simulation).
- Sustained INP under typical user interaction, not just initial load.
- CrUX data interpretation if site is low-traffic and field data falls back to origin or is missing.

## Security Headers & HTTP
_Captured in 179 ms._

**Transport:**
- Final URL: https://larsen.ee/terms-of-service
- Status: 200
- Redirected: false
- HTTPS redirect: HTTP → HTTPS ✓

**Caching:**
- cache-control: not set
- etag: W/"23d47-cQu6cm+NqnEe+nMSDUtq1sHdiVc"
- last-modified: n/a
- expires: n/a
- pragma: n/a
- vary: Accept-Encoding
- Issues:
  - no cache-control header — caching behavior is unpredictable

**Compression:**
- content-encoding: gzip
- content-length: n/a
- Decoded body: 143.3 KB

### Priority fixes
1. **strict-transport-security weak** (high) — max-age too short (15552000s, recommended >= 31536000); missing includeSubDomains directive; missing preload directive
2. **content-security-policy weak** (high) — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
3. **x-frame-options missing** (medium) — Prefer CSP frame-ancestors; X-Frame-Options as fallback
4. **weak caching policy** (medium) — no cache-control header — caching behavior is unpredictable
5. **permissions-policy missing** (low) — Declare Permissions-Policy to disable unused features
6. **cross-origin-opener-policy missing** (low) — Set COOP to same-origin to isolate browsing context
7. **cross-origin-resource-policy missing** (low) — Set CORP to same-origin or same-site to prevent cross-origin reads
8. **server header discloses technology** (low) — Server: Google Frontend

### Findings

#### Tracked headers
- **strict-transport-security** (weak, high) `max-age=15552000` — max-age too short (15552000s, recommended >= 31536000); missing includeSubDomains directive; missing preload directive
- **content-security-policy** (weak, high) `frame-ancestors https://hub.larsen.ee` — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
- **x-frame-options** (missing, medium)
- **x-content-type-options** (present, medium) `nosniff`
- **referrer-policy** (present, low) `no-referrer`
- **permissions-policy** (missing, low)
- **cross-origin-opener-policy** (missing, low)
- **cross-origin-resource-policy** (missing, low)
- **x-permitted-cross-domain-policies** (present, low) `none`

#### Info disclosure
- Server: `Google Frontend`


#### All response headers
```
alt-svc: h3=":443"; ma=2592000
content-encoding: gzip
content-security-policy: frame-ancestors https://hub.larsen.ee
content-type: text/html; charset=utf-8
date: Wed, 10 Jun 2026 10:04:37 GMT
etag: W/"23d47-cQu6cm+NqnEe+nMSDUtq1sHdiVc"
expect-ct: max-age=0
referrer-policy: no-referrer
server: Google Frontend
strict-transport-security: max-age=15552000
transfer-encoding: chunked
vary: Accept-Encoding
via: 1.1 google
x-content-type-options: nosniff
x-dns-prefetch-control: off
x-download-options: noopen
x-permitted-cross-domain-policies: none
x-xss-protection: 0
```

### Manual checks
- Cookie attributes set via JavaScript (not visible in HTTP response).
- CORS preflight behavior under non-GET methods (only GET response headers checked).
- HSTS preload list inclusion (check hstspreload.org).
- WAF / DDoS posture beyond what static headers reveal.

## W3C HTML Validator
_Captured in 434 ms._

**Scoring:** 6 errors · 3 warnings · 12 cosmetic (suppressed)

### Priority fixes
1. **An “img” element must have an “alt” attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images.** (medium) — x2, first at line 63
2. **CSS: “color”: Parse Error.** (medium) — x2, first at line 66
3. **A “charset” attribute on a “meta” element found after the first 1024 bytes.** (medium) — x1, first at line 35
4. **The element “button” must not appear as a descendant of the “a” element.** (medium) — x1, first at line 66

### Issue groups
- (×1) [error] A “charset” attribute on a “meta” element found after the first 1024 bytes. — first at line 35 `charset="UTF-8">
    <title d`
- (×2) [error] An “img” element must have an “alt” attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images. — first at line 63 `pt>
      <img height="1" width="1" style="display:none"
        src="https://ww`
- (×1) [error] The element “button” must not appear as a descendant of the “a” element. — first at line 66 `"/search"><button class="button button--main desktop-header__yellow-button deskt`
- (×2) [error] CSS: “color”: Parse Error. — first at line 66 `p><ul><li><span style="background-color: rgba(255,255,255,var(--tw-bg-opacity));`
- (×1) [warning] Empty heading. — first at line 66 `s="topic"><h3 id="-" class="topic-title h3"> </h3>`
- (×1) [warning] This document appears to be written in English. Consider adding “lang="en"” (or variant) to the “html” start tag. — first at line 2 `type html>
<html >
  <he`
- (×1) [warning] This document has heading elements but none of them has a computed heading level of 1. — first at line 66 `s="topic"><h3 id="-1.-acceptance-of-terms" class="topic-title h3"> 1. Ac`

### Manual checks
- Whether each `<section>` / `<article>` wraps semantically meaningful content.
- Language tag accuracy for multi-language pages or quoted content.
- Whether structural choices align with the document outline algorithm in screen readers.

## axe-core (Accessibility)
_Captured in 2929 ms._

**Scoring:** 7 violations · 29 passes · critical 1 · serious 2 · moderate 3 · minor 1

### Priority fixes
1. **image-alt** (high) — Images must have alternative text
2. **html-has-lang** (high) — <html> element must have a lang attribute
3. **link-name** (high) — Links must have discernible text
4. **landmark-one-main** (medium) — Document should have one main landmark
5. **page-has-heading-one** (medium) — Page should contain a level-one heading

### Findings

#### `empty-heading` (minor)
[Headings should not be empty](https://dequeuniversity.com/rules/axe/4.11/empty-heading?application=playwright)
- `#\-`

#### `html-has-lang` (serious) — WCAG: wcag2a, wcag311
[<html> element must have a lang attribute](https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=playwright)
- `html`

#### `image-alt` (critical) — WCAG: wcag2a, wcag111
[Images must have alternative text](https://dequeuniversity.com/rules/axe/4.11/image-alt?application=playwright)
- `img[src$="Co-Liv.e0807b70.png"]`

#### `landmark-one-main` (moderate)
[Document should have one main landmark](https://dequeuniversity.com/rules/axe/4.11/landmark-one-main?application=playwright)
- `html`

#### `link-name` (serious) — WCAG: wcag2a, wcag244, wcag412
[Links must have discernible text](https://dequeuniversity.com/rules/axe/4.11/link-name?application=playwright)
- `a[aria-current="page"]`
- `.footer__icon--facebook`
- `.footer__icon--instagram`

#### `page-has-heading-one` (moderate)
[Page should contain a level-one heading](https://dequeuniversity.com/rules/axe/4.11/page-has-heading-one?application=playwright)
- `html`

#### `region` (moderate)
[All page content should be contained by landmarks](https://dequeuniversity.com/rules/axe/4.11/region?application=playwright)
- `.language-switcher.active[href$="kasutustingimused"]`
- `.language-switcher.fill-black[href$="kasutustingimused"]:nth-child(2)`
- `.page`
- `.cookies__content`

### Incomplete (axe could not determine)
- [ARIA attributes must conform to valid values](https://dequeuniversity.com/rules/axe/4.11/aria-valid-attr-value?application=playwright) — 1 node
- [Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright) — 14 nodes

### Manual checks
- Keyboard-only navigation flow + visible focus indicators on every interactive element.
- Screen reader output (NVDA, VoiceOver) for actual auditory experience.
- Modal focus trapping and restoration on close.
- Touch target sizes (44×44 px minimum per WCAG 2.5.8).
- Color contrast for elements with alpha-transparency or gradients (axe skips these).

## Browser Runtime
_Captured in 2936 ms._

**Capture summary:** 1 console events · 0 mixed-content requests · 37 network requests · 1.27 MB total

**Network bytes by resource type:**
| Type | Count | Bytes |
| --- | --- | --- |
| script | 17 | 843.4 KB |
| image | 5 | 323.5 KB |
| font | 3 | 91.3 KB |
| stylesheet | 2 | 40.8 KB |
| xhr | 2 | 15 B |
| document | 1 | 0 B |
| fetch | 5 | 0 B |
| ping | 2 | 0 B |

**Third-party origins (by bytes):**
- https://www.googletagmanager.com — 4 requests, 648.0 KB
- https://connect.facebook.net — 3 requests, 175.1 KB
- https://thumbor.larsen.ee — 2 requests, 56.5 KB
- https://fonts.gstatic.com — 1 request, 43.8 KB
- https://www.google-analytics.com — 2 requests, 20.3 KB
- https://www.google.ee — 2 requests, 84 B
- https://fonts.googleapis.com — 2 requests, 0 B
- https://eu-assets.i.posthog.com — 6 requests, 0 B
- https://region1.analytics.google.com — 2 requests, 0 B
- https://static.hotjar.com — 1 request, 0 B
- https://stats.g.doubleclick.net — 2 requests, 0 B
- https://pagead2.googlesyndication.com — 2 requests, 0 B

**Slowest requests (top 5):**
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ (script) — 362 ms, 177.7 KB
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM (script) — 361 ms, 159.2 KB
- https://connect.facebook.net/en_US/fbevents.js (script) — 361 ms, 97.5 KB
- https://www.chatbase.co/api/get-chatbot-styles/y7CotFfAzSHKzmcew7JaK (fetch) — 335 ms, 0 B
- https://www.google.ee/ads/ga-audiences?v=1&t=sr&slf_rd=1&_r=4&tid=G-9DLXLVKRKQ&cid=173112324.1781085878&gtm=45je6641h1v9128456099za200zd9128456099&rcb=16&aip=1&dma=1&dma_cps=-&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&frm=0&tag_exp=0~115938466~115938468~117776794&z=869414304 (image) — 226 ms, 42 B

### Priority fixes
1. **failed request** (medium) — fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-9DLXLVKRKQ&gtm=45je6641h1v9128456099za200zd9128456099&_p=1781085877643&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=EAAAAGAC&are=1&cid=173112324.1781085878&frm=0&ir=1&pscdl=noapi&rcb=16&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115938466~115938468~117776794&sid=1781085878&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2Fterms-of-service&dt=Larsen&en=page_view&_fv=1&_nsi=1&_ss=1&_ee=1&tfd=650 — net::ERR_ABORTED
2. **failed request** (medium) — fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=2&frm=0&ae=g&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Fterms-of-service&scrsrc=www.googletagmanager.com&rnd=407637100.1781085878&navt=n&npa=1&ep.ads_data_redaction=0&gtm=45He6641h1v847628427za200zd847628427xea&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115938466~115938469~117776794&apve=1&apvf=f&apvc=1&tft=1781085878205&tfd=739 — net::ERR_ABORTED
3. **failed request** (medium) — fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=6&frm=0&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Fterms-of-service&scrsrc=www.googletagmanager.com&rnd=407637100.1781085878&navt=n&npa=1&gtm=45be6641h1v9218844185z8847628427za20gzb847628427zd847628427xec&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115938466~115938469&apve=1&apvf=f&apvc=0&tids=AW-17042172798&tid=AW-17042172798&tft=1781085878397&tfd=931 — net::ERR_ABORTED

### Findings

#### Failed requests
- fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-9DLXLVKRKQ&gtm=45je6641h1v9128456099za200zd9128456099&_p=1781085877643&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=EAAAAGAC&are=1&cid=173112324.1781085878&frm=0&ir=1&pscdl=noapi&rcb=16&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115938466~115938468~117776794&sid=1781085878&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2Fterms-of-service&dt=Larsen&en=page_view&_fv=1&_nsi=1&_ss=1&_ee=1&tfd=650 — net::ERR_ABORTED
- fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=2&frm=0&ae=g&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Fterms-of-service&scrsrc=www.googletagmanager.com&rnd=407637100.1781085878&navt=n&npa=1&ep.ads_data_redaction=0&gtm=45He6641h1v847628427za200zd847628427xea&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115938466~115938469~117776794&apve=1&apvf=f&apvc=1&tft=1781085878205&tfd=739 — net::ERR_ABORTED
- fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=6&frm=0&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Fterms-of-service&scrsrc=www.googletagmanager.com&rnd=407637100.1781085878&navt=n&npa=1&gtm=45be6641h1v9218844185z8847628427za20gzb847628427zd847628427xec&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115938466~115938469&apve=1&apvf=f&apvc=0&tids=AW-17042172798&tid=AW-17042172798&tft=1781085878397&tfd=931 — net::ERR_ABORTED
- fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-L1DE8WRGT9&gtm=45je6641h1v9119440986z8847628427za20gzb847628427zd847628427&_p=1781085877643&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=AAAAAGAC&are=1&cid=173112324.1781085878&frm=0&pscdl=noapi&rcb=17&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115616986~115938466~115938469&sid=1781085878&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2Fterms-of-service&dt=Larsen&en=page_view&_fv=1&_ss=1&tfd=994 — net::ERR_ABORTED

#### Console events
- [warning] Hotjar not launching due to suspicious userAgent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/148.0.7778.96 Safari/537.36 (https://static.hotjar.com/c/hotjar-3296638.js?sv=7)

### Manual checks
- Console output during user interaction (load-only capture).
- Behavior on slow networks and constrained devices.
- WebGL / canvas FPS profiling via DevTools Layers panel.
- Service worker / cache behavior on repeat visits.

## HTML Inventory
_Captured in 2936 ms._

**Document:**
- Lang: not set
- Title: Larsen
- Canonical: not set
- Viewport: width=device-width
- Charset: UTF-8
- HTML bytes: 158881

**Meta tags:**
- Description: not set
- Robots: not set
- Theme color: #ffffff
- Open Graph tags: 1 (og:title)
- Twitter tags: 0
- hreflang: none
- JSON-LD: none

**Heading outline:**
- Counts: h1 ×0, h2 ×14, h3 ×15, h4 ×1, h5 ×0, h6 ×0
- Sequence (first 20):
  - h3: 1. Acceptance of Terms
  - h3: 2. Changes to Terms
  - h3: 3. Use of the Website
  - h3: 4. Intellectual Property
  - h3: 5. User-Generated Content
  - h3: 6. Booking and Payments
  - h3: 7. Privacy
  - h3: 8. Limitation of Liability
  - h3: 9. Indemnification
  - h3: 10. Termination
  - h3: 11. Governing Law
  - h3: 12. Contact Information
  - h3: 
  - h2: Navigate
  - h2: Home
  - h2: Rooms
  - h2: Locations
  - h2: Features
  - h2: Testimonials
  - h2: About & Contact

**Landmarks:**
- nav: present
- main: **missing**
- header: **missing**
- footer: present
- Skip-to-content link: **missing**

**Scripts:** 26 total — 0 defer, 16 async, 1 render-blocking. Speculation rules: no.

External scripts (first 15):
- https://static.hotjar.com/c/hotjar-3296638.js?sv=7 (async)
- https://www.google-analytics.com/analytics.js (async)
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641h1 (async)
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641h1 (async)
- https://eu-assets.i.posthog.com/static/array.js (async)
- https://connect.facebook.net/signals/config/1726152210919905?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171%2C231%2C230%2C225%2C227%2C228%2C229%2C226%2C214%2C224%2C196%2C193%2C194%2C188%2C192%2C195%2C191%2C186%2C322%2C199%2C189%2C190%2C218%2C187%2C185%2C238%2C209%2C179%2C180%2C175%2C181%2C178%2C176%2C177%2C174%2C172%2C183%2C184%2C182%2C269%2C321%2C291%2C289%2C290%2C288%2C197%2C241%2C247%2C242%2C244%2C246%2C245%2C243%2C240%2C256%2C251%2C253%2C250%2C257%2C254%2C249%2C255%2C252%2C248%2C284%2C295 (async)
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 (async)
- https://connect.facebook.net/en_US/fbevents.js (async)
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM (async)
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ (async)
- https://eu-assets.i.posthog.com/static/web-vitals.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/dead-clicks-autocapture.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/surveys.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/array/phc_9AAcqE521KLngxSgpVorPQDkU4ENZA9RJXVJnkr12nN/config.js (async)

**Stylesheets:** 1 external, 2 inline (1.2 KB)

**Images:** 3 total — **1 without alt**, **3 without width/height**, 1 without loading="lazy"

Image inventory (first 15):
| src | alt | w×h | loading | srcset |
| --- | --- | --- | --- | --- |
| lity(90)/https://larsen.ee/production/media/2024/07/karl.png | _(empty)_ | _n/a_ | lazy | ✗ |
| https://larsen.ee/production/media/2022/03/ehrl-blue-eng.png | _(empty)_ | _n/a_ | lazy | ✗ |
| https://larsen.ee/client/Co-Liv.e0807b70.png | _(no attr)_ | _n/a_ | _n/a_ | ✗ |

**Links:** 20 anchors — 3 external, 1 preconnect, 0 preload.

### Priority fixes
1. **Document has 0 <h1> elements** (high) — A page should have exactly one h1; multiple h1s break document outline
2. **Missing skip-to-content link** (medium) — No anchor link with "skip" / "otse sisu" text found
3. **1 images without alt attribute** (high) — Content images need descriptive alt text; decorative images need empty alt=""
4. **3 images without explicit width/height** (medium) — Missing dimensions can cause layout shifts (CLS)

### Manual checks
- Visual rendering of detected mojibake (browser may auto-correct for display).
- Whether decorative images correctly use empty `alt=""` (vs. content images missing it).
- Whether headings reflect actual document hierarchy semantically.
- Whether vague link text is disambiguated by `aria-label` or surrounding context.

## Optimized-Web Checklist
_Captured in 0 ms._

**Summary:** 2 pass · 0 warn · 4 fail · 1 n/a

**Checklist:**
| Item | Status | Detail |
| --- | --- | --- |
| Page caching plugin / CDN active | ✗ fail | No WordPress cache plugin marker or CDN edge cache detected on the document response. |
| Images lazy-loaded | ✓ pass | All non-hero raster images use loading="lazy" except one. |
| Hero image eagerly loaded | ✗ fail | Hero image has loading="lazy", which delays LCP (inferred from DOM order/size — Lighthouse LCP element unavailable). Use loading="eager" (or omit loading) and add fetchpriority="high". |
| Hero is a real <img> (not a CSS background-image) | – n/a | No CSS background-images detected on raster-image-eligible elements. |
| Responsive images (srcset / <picture>) | ✗ fail | 3/3 raster images lack srcset and are not inside <picture>. |
| Reasonable number of image sizes | ✗ fail | No raster images use srcset; browsers cannot pick an optimally sized variant. |
| JS scripts not blocking in <head> | ✓ pass | No render-blocking scripts in <head>. |

**Evidence:**
- Images lazy-loaded:
  - `https://larsen.ee/client/Co-Liv.e0807b70.png`
- Hero image eagerly loaded:
  - `hero: …256x0/filters:quality(90)/https://larsen.ee/production/media/2024/07/karl.png`
  - `loading: lazy`
  - `fetchpriority: (not set)`
- Responsive images (srcset / <picture>):
  - `…256x0/filters:quality(90)/https://larsen.ee/production/media/2024/07/karl.png`
  - `…ters:quality(90)/https://larsen.ee/production/media/2022/03/ehrl-blue-eng.png`
  - `https://larsen.ee/client/Co-Liv.e0807b70.png`

### Priority fixes
1. **Page caching plugin / CDN active** (high) — No WordPress cache plugin marker or CDN edge cache detected on the document response.
2. **Hero image eagerly loaded** (high) — Hero image has loading="lazy", which delays LCP (inferred from DOM order/size — Lighthouse LCP element unavailable). Use loading="eager" (or omit loading) and add fetchpriority="high".
3. **Responsive images (srcset / <picture>)** (high) — 3/3 raster images lack srcset and are not inside <picture>.
4. **Reasonable number of image sizes** (high) — No raster images use srcset; browsers cannot pick an optimally sized variant.

### Manual checks
- Cart / checkout / logged-in pages must bypass the page cache or load dynamic regions via AJAX.
- Verify the cache is warmed for the canonical URL on initial deploy (first visitor should not pay the cold-start cost).
- Inspect "hero" image visually — heuristic above picks the first/largest <img>, which may not match the actual LCP element on JS-heavy pages.
- Confirm scripts marked as defer/async actually tolerate deferred execution (some legacy snippets break when reordered).

---

# Page 5 of 5 — https://larsen.ee/et

Run: 2026-06-10T10:04:52.144Z

## Audit Coverage
**100%** of audit sources returned data.

_All sources OK._

## Methodology

Each tool below contributes data to a single overall 0–100 site quality score. Performance dominates the weighting (~40%), followed by accessibility (~30%), image assets (~15%), and SEO/security (~15%). These weights are informative — the score is judged holistically, not from a fixed formula.

Severity scale in `priorities[]`:
- **high** — blocking issue / vulnerability / fail.
- **medium** — significant degradation.
- **low** — minor improvement.

Each tool section below lists: scores → priority fixes → findings → manual checks the tool cannot verify.

## Site Signals (inferred)

Heuristic site-shape signals derived from the audit data. Use these to calibrate the priority of security-header recommendations (see system rubric). Override when the evidence is clearly wrong.

- Auth surface: no
- Payments: no
- User-generated content: **yes** — anchor href contains "review"
- E-commerce: no

## PageSpeed Insights
_Captured in 23898 ms (mobile + desktop in parallel)._

**Lighthouse scores (mobile vs desktop; worse value bolded):**
| Category | Mobile | Desktop |
| --- | --- | --- |
| Performance | 53 | **44** |
| Accessibility | 74 | 74 |
| Best Practices | 96 | 96 |
| SEO | 91 | 91 |

**Core Web Vitals — lab (Lighthouse) / field (CrUX p75); worse lab value bolded:**
| Metric | Mobile | Desktop |
| --- | --- | --- |
| LCP | **10.5 s** / 3555 ms p75 (average) | 4.9 s / 2726 ms p75 (average) |
| CLS | **0.001** / 6 p75 (fast) | 0.001 / 43 p75 (slow) |
| TBT | 264 ms | **646 ms** |
| FCP | **3.64 s** / 3280 ms p75 (slow) | 848 ms / 2197 ms p75 (average) |
| Speed Index | **15.44 s** | 3.26 s |
| TTFB | 61 ms / 2621 ms p75 (slow) | **77 ms** / 1414 ms p75 (average) |
| INP (field only) | 390 ms p75 (average) | 245 ms p75 (average) |

### Priority fixes
1. **largest-contentful-paint** (high) — 10.5 s
2. **speed-index** (high) — 15.4 s
3. **first-contentful-paint** (high) — 3.6 s
4. **total-blocking-time** (low) — 260 ms
5. **cache-insight** (high) — Est savings of 2,451 KiB

### Findings (mobile)

#### Unused JavaScript
- https://larsen.ee/client/app-889782a39d4314ef1bf6.js — 1370 KB wasted
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 68 KB wasted
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM — 68 KB wasted
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641 — 66 KB wasted
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641 — 63 KB wasted
- https://script.hotjar.com/modules.c3d712579ef0b1b5af2a.js — 38 KB wasted
- https://connect.facebook.net/en_US/fbevents.js — 34 KB wasted
- https://eu-assets.i.posthog.com/static/array.js — 32 KB wasted
- https://eu-assets.i.posthog.com/static/surveys.js?v=1.384.1 — 25 KB wasted
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 — 21 KB wasted
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 — 21 KB wasted

#### Layout-shift sources
- div.calendar-container — shift 0.001

#### Long tasks
- https://larsen.ee/client/app-889782a39d4314ef1bf6.js — 252 ms
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641 — 111 ms
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 — 92 ms
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641 — 89 ms
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 76 ms
- https://larsen.ee/et — 59 ms
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM — 59 ms
- https://connect.facebook.net/en_US/fbevents.js — 54 ms
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ — 52 ms
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 — 51 ms

#### DOM size
- Total nodes: 0

#### Failing modeled audits
- SEO: `canonical`
- SEO: `robotsTxt`
- SEO: `tapTargets`
- SEO: `structuredData`
- Best Practices: `errorsInConsole`

#### All failing PSI audits (sorted by weight × failure margin)
- `largest-contentful-paint` (performance, score 0.00, weight 25) — Largest Contentful Paint — 10.5 s
- `speed-index` (performance, score 0.00, weight 10) — Speed Index — 15.4 s
- `button-name` (accessibility, score 0.00, weight 10) — Buttons do not have an accessible name
- `image-alt` (accessibility, score 0.00, weight 10) — Image elements do not have `[alt]` attributes
- `color-contrast` (accessibility, score 0.00, weight 7) — Background and foreground colors do not have a sufficient contrast ratio.
- `html-has-lang` (accessibility, score 0.00, weight 7) — `<html>` element does not have a `[lang]` attribute
- `link-name` (accessibility, score 0.00, weight 7) — Links do not have a discernible name
- `first-contentful-paint` (performance, score 0.31, weight 10) — First Contentful Paint — 3.6 s
- `total-blocking-time` (performance, score 0.83, weight 30) — Total Blocking Time — 260 ms
- `heading-order` (accessibility, score 0.00, weight 3) — Heading elements are not in a sequentially-descending order
- `lcp-discovery-insight` (performance, score 0.00, weight 0) — LCP request discovery
- `network-dependency-tree-insight` (performance, score 0.00, weight 0) — Network dependency tree
- `interactive` (performance, score 0.00, weight 0) — Time to Interactive — 40.2 s
- `errors-in-console` (best-practices, score 0.00, weight 1) — Browser errors were logged to the console
- `valid-source-maps` (best-practices, score 0.00, weight 0) — Missing source maps for large first-party JavaScript
- `image-alt` (seo, score 0.00, weight 1) — Image elements do not have `[alt]` attributes
- `max-potential-fid` (performance, score 0.49, weight 0) — Max Potential First Input Delay — 250 ms

### Manual checks
- Real-device behavior on slow 3G / low-tier mobile hardware (Lighthouse is throttled simulation).
- Sustained INP under typical user interaction, not just initial load.
- CrUX data interpretation if site is low-traffic and field data falls back to origin or is missing.

## Security Headers & HTTP
_Captured in 1227 ms._

**Transport:**
- Final URL: https://larsen.ee/et
- Status: 200
- Redirected: false
- HTTPS redirect: HTTP → HTTPS ✓

**Caching:**
- cache-control: not set
- etag: W/"cb584-5S746A0oAL8Ouv3+WBk3nKXjvIE"
- last-modified: n/a
- expires: n/a
- pragma: n/a
- vary: Accept-Encoding
- Issues:
  - no cache-control header — caching behavior is unpredictable

**Compression:**
- content-encoding: gzip
- content-length: n/a
- Decoded body: 813.4 KB

### Priority fixes
1. **strict-transport-security weak** (high) — max-age too short (15552000s, recommended >= 31536000); missing includeSubDomains directive; missing preload directive
2. **content-security-policy weak** (high) — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
3. **x-frame-options missing** (medium) — Prefer CSP frame-ancestors; X-Frame-Options as fallback
4. **weak caching policy** (medium) — no cache-control header — caching behavior is unpredictable
5. **permissions-policy missing** (low) — Declare Permissions-Policy to disable unused features
6. **cross-origin-opener-policy missing** (low) — Set COOP to same-origin to isolate browsing context
7. **cross-origin-resource-policy missing** (low) — Set CORP to same-origin or same-site to prevent cross-origin reads
8. **server header discloses technology** (low) — Server: Google Frontend

### Findings

#### Tracked headers
- **strict-transport-security** (weak, high) `max-age=15552000` — max-age too short (15552000s, recommended >= 31536000); missing includeSubDomains directive; missing preload directive
- **content-security-policy** (weak, high) `frame-ancestors https://hub.larsen.ee` — missing default-src; missing object-src 'none'; only frame-ancestors set — no script/resource restrictions
- **x-frame-options** (missing, medium)
- **x-content-type-options** (present, medium) `nosniff`
- **referrer-policy** (present, low) `no-referrer`
- **permissions-policy** (missing, low)
- **cross-origin-opener-policy** (missing, low)
- **cross-origin-resource-policy** (missing, low)
- **x-permitted-cross-domain-policies** (present, low) `none`

#### Info disclosure
- Server: `Google Frontend`


#### All response headers
```
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
content-encoding: gzip
content-security-policy: frame-ancestors https://hub.larsen.ee
content-type: text/html; charset=utf-8
date: Wed, 10 Jun 2026 10:04:52 GMT
etag: W/"cb584-5S746A0oAL8Ouv3+WBk3nKXjvIE"
expect-ct: max-age=0
referrer-policy: no-referrer
server: Google Frontend
strict-transport-security: max-age=15552000
transfer-encoding: chunked
vary: Accept-Encoding
via: 1.1 google
x-content-type-options: nosniff
x-dns-prefetch-control: off
x-download-options: noopen
x-permitted-cross-domain-policies: none
x-xss-protection: 0
```

### Manual checks
- Cookie attributes set via JavaScript (not visible in HTTP response).
- CORS preflight behavior under non-GET methods (only GET response headers checked).
- HSTS preload list inclusion (check hstspreload.org).
- WAF / DDoS posture beyond what static headers reveal.

## W3C HTML Validator
_Captured in 1492 ms._

**Scoring:** 12 errors · 1 warnings · 18 cosmetic (suppressed)

### Priority fixes
1. **The element “button” must not appear as a descendant of the “a” element.** (high) — x5, first at line 66
2. **An “img” element must have an “alt” attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images.** (medium) — x2, first at line 63
3. **The value of the “for” attribute of the “label” element must be the ID of a non-hidden form control.** (medium) — x2, first at line 66
4. **The heading “h4” (with computed level 4) follows the heading “h2” (with computed level 2), skipping 1 heading level.** (medium) — x2, first at line 66
5. **A “charset” attribute on a “meta” element found after the first 1024 bytes.** (medium) — x1, first at line 35

### Issue groups
- (×1) [error] A “charset” attribute on a “meta” element found after the first 1024 bytes. — first at line 35 `charset="UTF-8">
    <title d`
- (×2) [error] An “img” element must have an “alt” attribute, except under certain conditions. For details, consult guidance on providing text alternatives for images. — first at line 63 `pt>
      <img height="1" width="1" style="display:none"
        src="https://ww`
- (×5) [error] The element “button” must not appear as a descendant of the “a” element. — first at line 66 `"/otsing"><button class="button button--main desktop-header__yellow-button deskt`
- (×2) [error] The value of the “for” attribute of the “label” element must be the ID of a non-hidden form control. — first at line 66 `xt-area "><label for="room-type-1">Mõni p`
- (×1) [warning] This document appears to be written in Estonian. Consider adding “lang="et"” (or variant) to the “html” start tag. — first at line 2 `type html>
<html >
  <he`
- (×2) [error] The heading “h4” (with computed level 4) follows the heading “h2” (with computed level 2), skipping 1 heading level. — first at line 66 `ates</div><h4 class="apartment-type-slider__price-price">559<!-`

### Manual checks
- Whether each `<section>` / `<article>` wraps semantically meaningful content.
- Language tag accuracy for multi-language pages or quoted content.
- Whether structural choices align with the document outline algorithm in screen readers.

## axe-core (Accessibility)
_Captured in 4501 ms._

**Scoring:** 7 violations · 36 passes · critical 2 · serious 3 · moderate 2 · minor 0

### Priority fixes
1. **button-name** (high) — Buttons must have discernible text
2. **image-alt** (high) — Images must have alternative text
3. **color-contrast** (high) — Elements must meet minimum color contrast ratio thresholds
4. **html-has-lang** (high) — <html> element must have a lang attribute
5. **link-name** (high) — Links must have discernible text

### Findings

#### `button-name` (critical) — WCAG: wcag2a, wcag412
[Buttons must have discernible text](https://dequeuniversity.com/rules/axe/4.11/button-name?application=playwright)
- `a[href$="sume-loft-roduga-452"] > .apartment-type-slider.apartment-type-box__slider-box > .slider > .slider__dots > .active.slider__dot`
- `a[href$="sume-loft-roduga-452"] > .apartment-type-slider.apartment-type-box__slider-box > .slider > .slider__dots > .slider__dot:nth-child(2)`
- `a[href$="sume-loft-roduga-452"] > .apartment-type-slider.apartment-type-box__slider-box > .slider > .slider__dots > .slider__dot:nth-child(3)`
- `a[href$="sume-loft-roduga-452"] > .apartment-type-slider.apartment-type-box__slider-box > .slider > .slider__dots > .slider__dot:nth-child(4)`
- `a[href$="sume-loft-roduga-452"] > .apartment-type-slider.apartment-type-box__slider-box > .slider > .slider__dots > .slider__dot:nth-child(5)`
- … and 15 more nodes

#### `color-contrast` (serious) — WCAG: wcag2aa, wcag143
[Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright)
- `.search-container__stay-type-input-wrapper > .search-container__value`
- `.react-datepicker-wrapper:nth-child(4) > .react-datepicker__input-container > .search-container__date-picker-input-container > .search-container__date-picker-input-wrapper > .search-container__value`
- `.react-datepicker-wrapper:nth-child(5) > .react-datepicker__input-container > .search-container__date-picker-input-container > .search-container__date-picker-input-wrapper > .search-container__value`
- `a[href$="sume-loft-roduga-452"] > .apartment-type-slider.apartment-type-box__slider-box > .apartment-type-slider__prices > .apartment-type-slider__price > .apartment-type-slider__price-from`
- `.apartment-type-box:nth-child(2) > .apartment-type-slider.apartment-type-box__slider-box > .apartment-type-slider__prices > .apartment-type-slider__price > .apartment-type-slider__price-from`
- … and 4 more nodes

#### `heading-order` (moderate)
[Heading levels should only increase by one](https://dequeuniversity.com/rules/axe/4.11/heading-order?application=playwright)
- `a[href$="sume-loft-roduga-452"] > .apartment-type-slider.apartment-type-box__slider-box > .apartment-type-slider__prices > .apartment-type-slider__price > .apartment-type-slider__price-price`
- `.other-features-container__feature:nth-child(1) > .other-features-container__title > h4`

#### `html-has-lang` (serious) — WCAG: wcag2a, wcag311
[<html> element must have a lang attribute](https://dequeuniversity.com/rules/axe/4.11/html-has-lang?application=playwright)
- `html`

#### `image-alt` (critical) — WCAG: wcag2a, wcag111
[Images must have alternative text](https://dequeuniversity.com/rules/axe/4.11/image-alt?application=playwright)
- `img[src$="Co-Liv.e0807b70.png"]`

#### `link-name` (serious) — WCAG: wcag2a, wcag244, wcag412
[Links must have discernible text](https://dequeuniversity.com/rules/axe/4.11/link-name?application=playwright)
- `.larsen-logo-wrapper > .active[aria-current="page"][href="/et"]`
- `.footer__icon--facebook`
- `.footer__icon--instagram`

#### `region` (moderate)
[All page content should be contained by landmarks](https://dequeuniversity.com/rules/axe/4.11/region?application=playwright)
- `.language-switcher.fill-white[href="/"]:nth-child(1)`
- `.language-switcher.fill-white[href="/"]:nth-child(2)`
- `.cookies__content`

### Incomplete (axe could not determine)
- [ARIA attributes must conform to valid values](https://dequeuniversity.com/rules/axe/4.11/aria-valid-attr-value?application=playwright) — 1 node
- [Elements must meet minimum color contrast ratio thresholds](https://dequeuniversity.com/rules/axe/4.11/color-contrast?application=playwright) — 16 nodes
- [<video> elements must have captions](https://dequeuniversity.com/rules/axe/4.11/video-caption?application=playwright) — 2 nodes

### Manual checks
- Keyboard-only navigation flow + visible focus indicators on every interactive element.
- Screen reader output (NVDA, VoiceOver) for actual auditory experience.
- Modal focus trapping and restoration on close.
- Touch target sizes (44×44 px minimum per WCAG 2.5.8).
- Color contrast for elements with alpha-transparency or gradients (axe skips these).

## Browser Runtime
_Captured in 4517 ms._

**Capture summary:** 1 console events · 0 mixed-content requests · 56 network requests · 69.19 MB total

**Network bytes by resource type:**
| Type | Count | Bytes |
| --- | --- | --- |
| media | 4 | 55.96 MB |
| image | 21 | 12.30 MB |
| script | 17 | 844.5 KB |
| font | 2 | 67.8 KB |
| stylesheet | 2 | 40.8 KB |
| xhr | 2 | 15 B |
| document | 1 | 0 B |
| fetch | 5 | 0 B |
| ping | 2 | 0 B |

**Third-party origins (by bytes):**
- https://thumbor.larsen.ee — 5 requests, 4.66 MB
- https://www.googletagmanager.com — 4 requests, 649.1 KB
- https://connect.facebook.net — 3 requests, 175.1 KB
- https://fonts.gstatic.com — 1 request, 43.8 KB
- https://www.google-analytics.com — 2 requests, 20.3 KB
- https://www.google.ee — 2 requests, 84 B
- https://fonts.googleapis.com — 2 requests, 0 B
- https://eu-assets.i.posthog.com — 6 requests, 0 B
- https://region1.analytics.google.com — 2 requests, 0 B
- https://stats.g.doubleclick.net — 2 requests, 0 B
- https://static.hotjar.com — 1 request, 0 B
- https://pagead2.googlesyndication.com — 2 requests, 0 B

**Slowest requests (top 5):**
- https://larsen.ee/et (document) — 1.17 s, 0 B
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ (script) — 504 ms, 178.7 KB
- https://connect.facebook.net/en_US/fbevents.js (script) — 504 ms, 97.5 KB
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM (script) — 504 ms, 159.2 KB
- https://eu-assets.i.posthog.com/static/array.js (script) — 337 ms, 0 B

### Priority fixes
1. **failed request** (medium) — media: https://larsen.ee/videos/uus-logota-larsen-video-2.mp4 — net::ERR_ABORTED
2. **failed request** (medium) — media: https://larsen.ee/production/media/2023/video-files/Larsen%20-%20Kokkuvo%CC%83te%20est%20bars.mp4 — net::ERR_ABORTED
3. **failed request** (medium) — fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-9DLXLVKRKQ&gtm=45je6690h2v9128456099za200zd9128456099&_p=1781085893347&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=EAAAAGAC&are=1&cid=1104885881.1781085894&frm=0&ir=1&pscdl=noapi&rcb=0&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115938466~115938468~119061278&sid=1781085893&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2Fet&dt=Larsen%20-%20Tallinna%20vingeim%20majutus&en=page_view&_fv=1&_nsi=1&_ss=1&_ee=1&tfd=1831 — net::ERR_ABORTED

### Findings

#### Failed requests
- media: https://larsen.ee/videos/uus-logota-larsen-video-2.mp4 — net::ERR_ABORTED
- media: https://larsen.ee/production/media/2023/video-files/Larsen%20-%20Kokkuvo%CC%83te%20est%20bars.mp4 — net::ERR_ABORTED
- fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-9DLXLVKRKQ&gtm=45je6690h2v9128456099za200zd9128456099&_p=1781085893347&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=EAAAAGAC&are=1&cid=1104885881.1781085894&frm=0&ir=1&pscdl=noapi&rcb=0&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115938466~115938468~119061278&sid=1781085893&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2Fet&dt=Larsen%20-%20Tallinna%20vingeim%20majutus&en=page_view&_fv=1&_nsi=1&_ss=1&_ee=1&tfd=1831 — net::ERR_ABORTED
- fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=13&frm=0&ae=g&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Fet&scrsrc=www.googletagmanager.com&rnd=1199697145.1781085894&navt=n&npa=1&ep.ads_data_redaction=0&gtm=45He6641h1v847628427za200zd847628427xea&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115938466~115938469&apve=1&apvf=f&apvc=1&tft=1781085894114&tfd=1943 — net::ERR_ABORTED
- fetch: https://pagead2.googlesyndication.com/ccm/collect?rcb=18&frm=0&en=page_view&dl=https%3A%2F%2Flarsen.ee%2Fet&scrsrc=www.googletagmanager.com&rnd=1199697145.1781085894&navt=n&npa=1&gtm=45be6641h1v9218844185z8847628427za20gzb847628427zd847628427xec&gcs=G1--&gcd=13l3l3p2p5l1&dma_cps=-&dma=1&tag_exp=0~115616985~115938466~115938469&apve=1&apvf=f&apvc=0&tids=AW-17042172798&tid=AW-17042172798&tft=1781085894290&tfd=2120 — net::ERR_ABORTED
- fetch: https://region1.analytics.google.com/g/collect?v=2&tid=G-L1DE8WRGT9&gtm=45je6641h1v9119440986z8847628427za20gzb847628427zd847628427&_p=1781085893347&_gaz=1&gcs=G1--&gcd=13l3l3p2p5l1&npa=1&dma_cps=-&dma=1&_eu=AAAAAGAC&are=1&cid=1104885881.1781085894&frm=0&pscdl=noapi&rcb=0&sr=1280x720&uaa=x86&uab=64&uafvl=Chromium%3B148.0.7778.96%7CHeadlessChrome%3B148.0.7778.96%7CNot%252FA)Brand%3B99.0.0.0&uam=&uamb=0&uap=Linux&uapv=&uaw=0&ul=en-us&gaf=2&_s=1&tag_exp=0~115938466~115938469~119061279&sid=1781085894&sct=1&seg=0&dl=https%3A%2F%2Flarsen.ee%2Fet&dt=Larsen%20-%20Tallinna%20vingeim%20majutus&en=page_view&_fv=1&_ss=1&tfd=2171 — net::ERR_ABORTED

#### Console events
- [warning] Hotjar not launching due to suspicious userAgent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/148.0.7778.96 Safari/537.36 (https://static.hotjar.com/c/hotjar-3296638.js?sv=7)

### Manual checks
- Console output during user interaction (load-only capture).
- Behavior on slow networks and constrained devices.
- WebGL / canvas FPS profiling via DevTools Layers panel.
- Service worker / cache behavior on repeat visits.

## HTML Inventory
_Captured in 4517 ms._

**Document:**
- Lang: not set
- Title: Larsen - Tallinna vingeim majutus
- Canonical: not set
- Viewport: width=device-width
- Charset: UTF-8
- HTML bytes: 848985

**Meta tags:**
- Description: Täismöbleeritud majutusruumid lühemaks või pikemaks ajaks - 1. Vali majutusruum välja. 2. Broneeri netist. 3. Tee kontaktivaba check-in.
- Robots: not set
- Theme color: #ffffff
- Open Graph tags: 3 (og:title, og:description, og:image)
- Twitter tags: 0
- hreflang: none
- JSON-LD: none

**Heading outline:**
- Counts: h1 ×1, h2 ×21, h3 ×6, h4 ×14, h5 ×0, h6 ×0
- Sequence (first 20):
  - h1: Broneeri oma peatuspaik Tallinnas hetkega
  - h2: Kõik on siin oodatud – ilma bürokraatia ja liigse jamata.
  - h4: 559 €
  - h3: Sume Loft - rõduga
  - h4: 489 €
  - h3: Sume Twin Studio - rõduga
  - h4: 459 €
  - h3: Sume Studio - rõduga
  - h4: 54 €
  - h4: 419 €
  - h3: Eduard House Studio L
  - h2: Otsid midagi teistsugust?
  - h2: Eduard House
  - h2: Kohene lihtne broneerimine
  - h2: Saa osa Larseni kogukonnast
  - h2: Miks valida Larsen?
  - h4: Paindlik lepingu pikkus
  - h4: Sõlmi leping otse veebist
  - h4: Täismöbleeritud
  - h4: Ühisalad
- Skips:
  - h2 → h4 after "Kõik on siin oodatud – ilma bürokraatia ja liigse jamata."
  - h2 → h4 after "Miks valida Larsen?"

**Landmarks:**
- nav: present
- main: present
- header: **missing**
- footer: present
- Skip-to-content link: **missing**

**Scripts:** 26 total — 0 defer, 16 async, 1 render-blocking. Speculation rules: no.

External scripts (first 15):
- https://static.hotjar.com/c/hotjar-3296638.js?sv=7 (async)
- https://www.google-analytics.com/analytics.js (async)
- https://www.googletagmanager.com/gtag/js?id=AW-17042172798&cx=c&gtm=4e6641h1 (async)
- https://www.googletagmanager.com/gtag/js?id=G-L1DE8WRGT9&cx=c&gtm=4e6641h1 (async)
- https://eu-assets.i.posthog.com/static/array.js (async)
- https://connect.facebook.net/signals/config/1726152210919905?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171%2C231%2C230%2C225%2C227%2C228%2C229%2C226%2C214%2C224%2C196%2C193%2C194%2C188%2C192%2C195%2C191%2C186%2C322%2C199%2C189%2C190%2C218%2C187%2C185%2C238%2C209%2C179%2C180%2C175%2C181%2C178%2C176%2C177%2C174%2C172%2C183%2C184%2C182%2C269%2C321%2C291%2C289%2C290%2C288%2C197%2C241%2C247%2C242%2C244%2C246%2C245%2C243%2C240%2C256%2C251%2C253%2C250%2C257%2C254%2C249%2C255%2C252%2C248%2C284%2C295 (async)
- https://connect.facebook.net/signals/config/1122870719174136?v=2.9.334&r=stable&domain=larsen.ee&hme=d9eb83ce5750216745fae8e2064a8c1ed2255ecaf2468f800b2a146e6168b65e&ex_m=105%2C208%2C156%2C22%2C73%2C74%2C147%2C69%2C68%2C11%2C165%2C91%2C16%2C139%2C128%2C39%2C76%2C79%2C135%2C161%2C167%2C8%2C4%2C5%2C7%2C6%2C3%2C92%2C102%2C168%2C173%2C222%2C30%2C75%2C234%2C233%2C232%2C23%2C33%2C55%2C104%2C61%2C10%2C64%2C98%2C99%2C100%2C106%2C131%2C31%2C29%2C133%2C134%2C130%2C129%2C157%2C77%2C160%2C158%2C159%2C50%2C60%2C124%2C15%2C164%2C45%2C267%2C268%2C266%2C26%2C27%2C28%2C48%2C148%2C78%2C113%2C18%2C20%2C44%2C40%2C42%2C41%2C84%2C93%2C97%2C111%2C146%2C149%2C46%2C112%2C24%2C21%2C120%2C70%2C36%2C151%2C150%2C152%2C143%2C141%2C25%2C35%2C59%2C110%2C163%2C71%2C17%2C154%2C115%2C82%2C67%2C19%2C86%2C87%2C117%2C85%2C137%2C136%2C140%2C162%2C34%2C282%2C298%2C215%2C204%2C62%2C205%2C203%2C301%2C292%2C52%2C216%2C108%2C132%2C81%2C122%2C54%2C47%2C49%2C114%2C121%2C127%2C126%2C58%2C65%2C63%2C153%2C116%2C37%2C32%2C53%2C56%2C101%2C166%2C1%2C125%2C14%2C123%2C12%2C2%2C57%2C94%2C66%2C119%2C90%2C89%2C169%2C170%2C95%2C96%2C9%2C103%2C51%2C144%2C88%2C80%2C72%2C118%2C107%2C43%2C145%2C0%2C83%2C138%2C142%2C155%2C38%2C109%2C13%2C171 (async)
- https://connect.facebook.net/en_US/fbevents.js (async)
- https://www.googletagmanager.com/gtm.js?id=GTM-KWS6MWM (async)
- https://www.googletagmanager.com/gtag/js?id=G-9DLXLVKRKQ (async)
- https://eu-assets.i.posthog.com/static/web-vitals.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/dead-clicks-autocapture.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/surveys.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/static/posthog-recorder.js?v=1.384.1 (async)
- https://eu-assets.i.posthog.com/array/phc_9AAcqE521KLngxSgpVorPQDkU4ENZA9RJXVJnkr12nN/config.js (async)

**Stylesheets:** 1 external, 2 inline (1.2 KB)

**Images:** 16 total — **1 without alt**, **16 without width/height**, 4 without loading="lazy"

Image inventory (first 15):
| src | alt | w×h | loading | srcset |
| --- | --- | --- | --- | --- |
| s://larsen.ee/images/uus-logota-larsen-video-2-thumbnail.jpg | thumbnail of the video | _n/a_ | _n/a_ | ✗ |
| ttps://larsen.ee/production/media/2023/11/maja-fasssad-2.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| s://larsen.ee/production/media/2025/03/rocca-house-drone.png | _(empty)_ | _n/a_ | lazy | ✗ |
| 0)/https://larsen.ee/production/media/2021/12/img-1042-1.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| /larsen.ee/production/media/2024/09/dji-0044-enhanced-nr.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| (90)/https://larsen.ee/production/media/2025/11/ttun8888.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| /https://larsen.ee/production/media/2025/11/ttun8720-hdr.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| /https://larsen.ee/production/media/2025/09/ttun8103-hdr.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| /https://larsen.ee/production/media/2025/09/ttun8394-hdr.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| (90)/https://larsen.ee/production/media/2024/04/-tun4221.jpg | _(empty)_ | _n/a_ | lazy | ✗ |
| ttps://larsen.ee/production/media/2023/11/maja-fasssad-2.jpg | Building image | _n/a_ | lazy | ✗ |
| https://larsen.ee/images/rectangle/Rectangle-158.png | imageOne | _n/a_ | _n/a_ | ✗ |
| https://larsen.ee/images/rectangle/Rectangle-159.png | imageOne | _n/a_ | _n/a_ | ✗ |
| lity(90)/https://larsen.ee/production/media/2024/07/karl.png | _(empty)_ | _n/a_ | lazy | ✗ |
| oduction/media/2022/03/ehrl-liikmem2rgis-sinine-est-002-.png | _(empty)_ | _n/a_ | lazy | ✗ |

**Links:** 36 anchors — 3 external, 1 preconnect, 0 preload.

Vague repeated link text:
- "kasutustingimused" ×2

### Priority fixes
1. **Heading level skips** (medium) — h2→h4 after "Kõik on siin oodatud – ilma bürokraatia "; h2→h4 after "Miks valida Larsen?"
2. **Missing skip-to-content link** (medium) — No anchor link with "skip" / "otse sisu" text found
3. **1 images without alt attribute** (high) — Content images need descriptive alt text; decorative images need empty alt=""
4. **16 images without explicit width/height** (medium) — Missing dimensions can cause layout shifts (CLS)

### Manual checks
- Visual rendering of detected mojibake (browser may auto-correct for display).
- Whether decorative images correctly use empty `alt=""` (vs. content images missing it).
- Whether headings reflect actual document hierarchy semantically.
- Whether vague link text is disambiguated by `aria-label` or surrounding context.

## Optimized-Web Checklist
_Captured in 0 ms._

**Summary:** 1 pass · 3 warn · 3 fail

**Checklist:**
| Item | Status | Detail |
| --- | --- | --- |
| Page caching plugin / CDN active | ✗ fail | No WordPress cache plugin marker or CDN edge cache detected on the document response. |
| Images lazy-loaded | ! warn | 3 of 15 non-hero raster images are not lazy-loaded. |
| Hero image eagerly loaded | ! warn | Hero image has no explicit loading or fetchpriority (inferred from DOM order/size — Lighthouse LCP element unavailable). Browser default is eager but adding fetchpriority="high" helps LCP. |
| Hero is a real <img> (not a CSS background-image) | ! warn | Hero element uses a CSS background-image (no image-set() variants), so the browser always loads the original asset regardless of viewport — there is no srcset equivalent. Move the hero to a real <img> with srcset/sizes (or <picture>) so smaller viewports can fetch a smaller file. |
| Responsive images (srcset / <picture>) | ✗ fail | 16/16 raster images lack srcset and are not inside <picture>. |
| Reasonable number of image sizes | ✗ fail | No raster images use srcset; browsers cannot pick an optimally sized variant. |
| JS scripts not blocking in <head> | ✓ pass | No render-blocking scripts in <head>. |

**Evidence:**
- Images lazy-loaded:
  - `https://larsen.ee/images/rectangle/Rectangle-158.png`
  - `https://larsen.ee/images/rectangle/Rectangle-159.png`
  - `https://larsen.ee/client/Co-Liv.e0807b70.png`
- Hero image eagerly loaded:
  - `hero: https://larsen.ee/images/uus-logota-larsen-video-2-thumbnail.jpg`
  - `loading: (not set)`
  - `fetchpriority: (not set)`
- Hero is a real <img> (not a CSS background-image):
  - `selector: div.buildings-map__map-overlay`
  - `url: https://larsen.ee/client/Eduard_House.e76047f2.png`
  - `box: 520×1021px`
- Responsive images (srcset / <picture>):
  - `https://larsen.ee/images/uus-logota-larsen-video-2-thumbnail.jpg`
  - `…ers:quality(90)/https://larsen.ee/production/media/2023/11/maja-fasssad-2.jpg`
  - `…:quality(90)/https://larsen.ee/production/media/2025/03/rocca-house-drone.png`
  - `…filters:quality(90)/https://larsen.ee/production/media/2021/12/img-1042-1.jpg`
  - `…ality(90)/https://larsen.ee/production/media/2024/09/dji-0044-enhanced-nr.jpg`

### Priority fixes
1. **Page caching plugin / CDN active** (high) — No WordPress cache plugin marker or CDN edge cache detected on the document response.
2. **Responsive images (srcset / <picture>)** (high) — 16/16 raster images lack srcset and are not inside <picture>.
3. **Reasonable number of image sizes** (high) — No raster images use srcset; browsers cannot pick an optimally sized variant.
4. **Images lazy-loaded** (medium) — 3 of 15 non-hero raster images are not lazy-loaded.
5. **Hero image eagerly loaded** (medium) — Hero image has no explicit loading or fetchpriority (inferred from DOM order/size — Lighthouse LCP element unavailable). Browser default is eager but adding fetchpriority="high" helps LCP.
6. **Hero is a real <img> (not a CSS background-image)** (medium) — Hero element uses a CSS background-image (no image-set() variants), so the browser always loads the original asset regardless of viewport — there is no srcset equivalent. Move the hero to a real <img> with srcset/sizes (or <picture>) so smaller viewports can fetch a smaller file.

### Manual checks
- Cart / checkout / logged-in pages must bypass the page cache or load dynamic regions via AJAX.
- Verify the cache is warmed for the canonical URL on initial deploy (first visitor should not pay the cold-start cost).
- Inspect "hero" image visually — heuristic above picks the first/largest <img>, which may not match the actual LCP element on JS-heavy pages.
- Confirm scripts marked as defer/async actually tolerate deferred execution (some legacy snippets break when reordered).