{
  "url": "https://m.fabswingers.com",
  "auditedAt": "2026-07-20T21:09:41.013Z",
  "mode": "report",
  "status": "completed",
  "statusDetail": "Atomic audit of seven representative public routes. Authenticated member-only areas, real account creation, payments, messaging, media galleries and destructive account actions were not covered because no credentials or permission to create data were supplied.",
  "page": {
    "appType": "mpa",
    "framework": "ASP.NET server-rendered MPA",
    "notes": "A small mobile-specific public site. Core content is server rendered. Authenticated application templates were outside the unauthenticated scope."
  },
  "evidenceUsed": [
    "screenshot",
    "dom",
    "layout-metrics",
    "evaluate-probe",
    "axe-core",
    "lighthouse",
    "trace",
    "har",
    "discoverability",
    "headers",
    "cookies",
    "trackers",
    "secrets",
    "images",
    "heap-summary",
    "HTTP probes",
    "Modern Web Guidance 0.0.172"
  ],
  "guidanceConsulted": [
    "dark-mode",
    "accessibility",
    "adapt-scrollbar-to-contrast-preferences",
    "same-document-transitions",
    "scrollytelling",
    "physics-based-easing",
    "shrinking-header-on-scroll",
    "anchor-positioning-tab-underline",
    "directional-navigation-transitions",
    "light-dismiss-a-dialog",
    "declarative-dialog-popover-control",
    "complex-shapes",
    "fluid-scaling",
    "size-aware-styling",
    "forms",
    "accessible-error-announcement",
    "identify-inp-causes",
    "visually-stable-font-fallbacks",
    "break-up-long-tasks",
    "optimize-image-priority",
    "identify-heavy-scripts",
    "move-dom-element-without-losing-state",
    "improve-text-layout-and-legibility",
    "css",
    "html",
    "security",
    "privacy",
    "passkeys",
    "flicker-free-client-side-ab-testing",
    "resilient-context-menus-and-nested-dropdowns",
    "translator",
    "support-global-calendar-systems",
    "coordinate-global-events",
    "custom-button-actions",
    "validate-input-after-interaction",
    "autofill-sign-in-form",
    "deliver-optimized-decorative-images",
    "deprioritize-background-fetches",
    "webmcp",
    "language-model",
    "manage-recurring-intervals"
  ],
  "artifacts": [
    {
      "type": "screenshot",
      "path": "evidence/home-mobile.png",
      "caption": "Entry page at 390 by 844.",
      "condition": "viewport: 390x844",
      "findingIds": [
        "F03"
      ]
    },
    {
      "type": "screenshot",
      "path": "evidence/home-desktop.png",
      "caption": "Entry page at 1440 by 900.",
      "condition": "viewport: 1440x900",
      "findingIds": []
    },
    {
      "type": "screenshot",
      "path": "evidence/home-dark-reduced.png",
      "caption": "Entry page remains light under dark color scheme and reduced motion.",
      "condition": "prefers-color-scheme: dark; prefers-reduced-motion: reduce",
      "findingIds": [
        "F01"
      ]
    },
    {
      "type": "screenshot",
      "path": "evidence/register-mobile.png",
      "caption": "Registration form at a mobile viewport.",
      "condition": "viewport: 390x844",
      "findingIds": [
        "F04",
        "F07",
        "F08",
        "F09",
        "F18"
      ]
    },
    {
      "type": "screenshot",
      "path": "evidence/login-mobile.png",
      "caption": "Login form at a mobile viewport.",
      "condition": "viewport: 390x844",
      "findingIds": [
        "F07",
        "F08",
        "F12",
        "F18"
      ]
    },
    {
      "type": "screenshot",
      "path": "evidence/terms-mobile.png",
      "caption": "Long terms content at a mobile viewport.",
      "condition": "viewport: 390x844",
      "findingIds": [
        "F03",
        "F09"
      ]
    },
    {
      "type": "screenshot",
      "path": "evidence/register-forced-colors.png",
      "caption": "Registration remains operable in forced colors.",
      "condition": "forced-colors: active; prefers-contrast: more",
      "findingIds": []
    },
    {
      "type": "layout",
      "path": "evidence/home-layout-mobile.json",
      "caption": "Entry-page mobile layout metrics.",
      "findingIds": []
    },
    {
      "type": "layout",
      "path": "evidence/register-layout-mobile.json",
      "caption": "Registration mobile layout metrics.",
      "findingIds": []
    },
    {
      "type": "dom",
      "path": "evidence/home-dom.json",
      "caption": "Rendered entry-page HTML and CSS.",
      "findingIds": [
        "F01",
        "F02",
        "F08",
        "F10",
        "F12",
        "F14"
      ]
    },
    {
      "type": "other",
      "path": "evidence/home-recon.json",
      "caption": "Entry-page links, metadata, text and forms.",
      "findingIds": []
    },
    {
      "type": "other",
      "path": "evidence/login-recon.json",
      "caption": "Login form and links.",
      "findingIds": [
        "F07",
        "F12",
        "F18"
      ]
    },
    {
      "type": "other",
      "path": "evidence/register-recon.json",
      "caption": "Registration form and links.",
      "findingIds": [
        "F07",
        "F18"
      ]
    },
    {
      "type": "other",
      "path": "evidence/contact-recon.json",
      "caption": "Contact and content-removal routes.",
      "findingIds": []
    },
    {
      "type": "other",
      "path": "evidence/terms-recon.json",
      "caption": "Terms content and heading structure.",
      "findingIds": []
    },
    {
      "type": "other",
      "path": "evidence/age-recon.json",
      "caption": "Age-assurance content and heading structure.",
      "findingIds": []
    },
    {
      "type": "other",
      "path": "evidence/axe-home.json",
      "caption": "axe-core results for the entry page.",
      "findingIds": [
        "F04",
        "F07",
        "F08"
      ]
    },
    {
      "type": "other",
      "path": "evidence/axe-login.json",
      "caption": "axe-core results for login.",
      "findingIds": [
        "F04",
        "F07",
        "F08",
        "F12"
      ]
    },
    {
      "type": "other",
      "path": "evidence/axe-register.json",
      "caption": "axe-core results for registration.",
      "findingIds": [
        "F04",
        "F07",
        "F08"
      ]
    },
    {
      "type": "other",
      "path": "evidence/axe-terms.json",
      "caption": "axe-core results for terms.",
      "findingIds": [
        "F04",
        "F08"
      ]
    },
    {
      "type": "lighthouse",
      "path": "evidence/lighthouse-home.json",
      "caption": "Lighthouse report for the entry page.",
      "findingIds": [
        "F04",
        "F06",
        "F07",
        "F08",
        "F10",
        "F11",
        "F12",
        "F19"
      ]
    },
    {
      "type": "trace",
      "path": "evidence/home-trace.json",
      "caption": "DevTools performance trace.",
      "findingIds": []
    },
    {
      "type": "trace-summary",
      "path": "evidence/home-trace-summary.json",
      "caption": "Trace summary with FCP, LCP and main-thread work.",
      "findingIds": []
    },
    {
      "type": "har",
      "path": "evidence/home.har",
      "caption": "HAR 1.2 network capture.",
      "findingIds": [
        "F06",
        "F19"
      ]
    },
    {
      "type": "har-summary",
      "path": "evidence/home-summary.json",
      "caption": "Compact HAR summary.",
      "findingIds": [
        "F06",
        "F19"
      ]
    },
    {
      "type": "other",
      "path": "evidence/home-images.json",
      "caption": "Image sizing, format and alternative text inventory.",
      "findingIds": [
        "F06",
        "F07",
        "F10",
        "F19"
      ]
    },
    {
      "type": "other",
      "path": "evidence/headers.json",
      "caption": "Main-document security header inspection.",
      "findingIds": [
        "F15"
      ]
    },
    {
      "type": "other",
      "path": "evidence/cookies.json",
      "caption": "Cookie attribute audit.",
      "findingIds": [
        "F15"
      ]
    },
    {
      "type": "other",
      "path": "evidence/trackers.json",
      "caption": "Third-party origin and tracker inventory.",
      "findingIds": []
    },
    {
      "type": "other",
      "path": "evidence/secrets.json",
      "caption": "Client-visible secret scan.",
      "findingIds": []
    },
    {
      "type": "discoverability",
      "path": "evidence/home-discoverability.json",
      "caption": "Raw HTML versus rendered entry page comparison.",
      "findingIds": [
        "F12"
      ]
    },
    {
      "type": "screenshot",
      "path": "evidence/home-discoverability-rendered.png",
      "caption": "Rendered entry page.",
      "condition": "JavaScript enabled",
      "findingIds": []
    },
    {
      "type": "screenshot",
      "path": "evidence/home-discoverability-crawler.png",
      "caption": "Crawler entry page.",
      "condition": "JavaScript disabled",
      "findingIds": []
    },
    {
      "type": "discoverability",
      "path": "evidence/register-discoverability.json",
      "caption": "Raw HTML versus rendered registration comparison.",
      "findingIds": []
    },
    {
      "type": "screenshot",
      "path": "evidence/register-discoverability-rendered.png",
      "caption": "Rendered registration.",
      "condition": "JavaScript enabled",
      "findingIds": []
    },
    {
      "type": "screenshot",
      "path": "evidence/register-discoverability-crawler.png",
      "caption": "Crawler registration.",
      "condition": "JavaScript disabled",
      "findingIds": []
    },
    {
      "type": "discoverability",
      "path": "evidence/terms-discoverability.json",
      "caption": "Raw HTML versus rendered terms comparison.",
      "findingIds": []
    },
    {
      "type": "screenshot",
      "path": "evidence/terms-discoverability-rendered.png",
      "caption": "Rendered terms page.",
      "condition": "JavaScript enabled",
      "findingIds": []
    },
    {
      "type": "screenshot",
      "path": "evidence/terms-discoverability-crawler.png",
      "caption": "Crawler terms page.",
      "condition": "JavaScript disabled",
      "findingIds": []
    },
    {
      "type": "other",
      "path": "evidence/crawl-pwa.json",
      "caption": "robots.txt, sitemap, manifest, service worker and doctype probe.",
      "findingIds": [
        "F13"
      ]
    },
    {
      "type": "other",
      "path": "evidence/home-platform-probe.json",
      "caption": "Metadata, semantic primitives, animation and platform probe.",
      "findingIds": [
        "F01",
        "F02",
        "F08",
        "F12",
        "F14"
      ]
    },
    {
      "type": "other",
      "path": "evidence/register-platform-probe.json",
      "caption": "Registration focus, target, labels, autofill and modern CSS probe.",
      "findingIds": [
        "F04",
        "F07",
        "F18"
      ]
    },
    {
      "type": "other",
      "path": "evidence/register-validation.json",
      "caption": "Invalid registration invokes an alert with no live error region.",
      "findingIds": [
        "F05",
        "F17"
      ]
    },
    {
      "type": "screenshot",
      "path": "evidence/not-found-mobile.png",
      "caption": "Minimal 404 recovery page.",
      "condition": "viewport: 390x844",
      "findingIds": [
        "F16"
      ]
    },
    {
      "type": "other",
      "path": "evidence/not-found.json",
      "caption": "404 page text and recovery link.",
      "findingIds": [
        "F16"
      ]
    },
    {
      "type": "other",
      "path": "evidence/http-probes-headers.txt",
      "caption": "HTTP 404 status and response headers.",
      "findingIds": [
        "F15",
        "F16"
      ]
    },
    {
      "type": "heap",
      "path": "evidence/register-heap-baseline.json",
      "caption": "Baseline registration heap summary.",
      "findingIds": []
    },
    {
      "type": "heap",
      "path": "evidence/register-heap-post.json",
      "caption": "Heap summary after ten repeated form-control interactions.",
      "findingIds": []
    },
    {
      "type": "other",
      "path": "evidence/register-heap-comparison.json",
      "caption": "Before and after heap comparison.",
      "findingIds": []
    },
    {
      "type": "other",
      "path": "evidence/terms-i18n.json",
      "caption": "Language, date and logical-property probe.",
      "findingIds": []
    }
  ],
  "config": {
    "loaded": false
  },
  "coverage": {
    "catalogVersion": "modern-web-guidance@0.0.172",
    "catalogChecksum": "sha256:78ccfdb2d483f4c57d9dafed80fd86c6265585a56457c8dcfddc254b80fb44d7",
    "expected": 58,
    "recorded": 58,
    "judged": 58,
    "blocked": 0,
    "notRun": 0,
    "missing": 0,
    "unknown": 0,
    "duplicates": 0,
    "complete": true
  },
  "checkOutcomes": [
    {
      "principleId": "respect-user-preferences",
      "checkId": "respects-color-scheme",
      "status": "issues",
      "confidence": "high",
      "method": "HINT (not mandatory): a screenshot or computed background under an emulated prefers-color-scheme: dark condition will reveal whether surfaces re-tint; the page CSS / a color-scheme declaration is corroborating evidence. The model chooses the method.",
      "evidence": "The dark-mode screenshot is byte-identical in appearance to the light capture, and the platform probe reports colorScheme \"normal\" with no prefers-color-scheme rule.",
      "pathIds": [
        "home"
      ],
      "findingIds": [
        "F01"
      ]
    },
    {
      "principleId": "respect-user-preferences",
      "checkId": "respects-reduced-motion",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: a transition video, or an in-page probe of getAnimations()/computed animation under an emulated prefers-reduced-motion: reduce condition, can show whether motion stops. The model chooses.",
      "evidence": "DOM/platform probes report zero active animations on home and registration under reduced-motion emulation, so no motion persists against the preference.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "respect-user-preferences",
      "checkId": "respects-contrast",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: a screenshot under emulated prefers-contrast: more / forced-colors, or an axe/contrast probe, can show whether controls and text survive. The model chooses.",
      "evidence": "The forced-colors registration capture preserves visible text, controls, links and focus affordances; Lighthouse contrast audits did not report a failing node.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "implement-natural-interactions",
      "checkId": "view-transitions",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: a transition video of a route/state change shows whether it animates; the page source / ::view-transition usage corroborates. The model chooses.",
      "evidence": "DOM and platform probes show ordinary multi-page links, zero active animations, and no view-transition CSS or meta opt-in.",
      "pathIds": [
        "home"
      ],
      "findingIds": [
        "F02"
      ]
    },
    {
      "principleId": "implement-natural-interactions",
      "checkId": "scroll-driven-animations",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: source/CSS inspection for animation-timeline: scroll()/view(); a long-task / scroll-handler probe can flag the main-thread anti-pattern. The model chooses.",
      "evidence": "CSS inspection found no scroll-linked JavaScript or animation timeline; trace recorded zero long tasks, so native scrolling is not replaced by a main-thread anti-pattern.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "implement-natural-interactions",
      "checkId": "physical-gestures",
      "status": "not-applicable",
      "confidence": "high",
      "method": "HINT: CSS inspection for scroll-snap / overscroll-behavior / physics-based easing vs custom pointermove listeners. The model chooses.",
      "evidence": "No carousel, draggable item, swipe action or other gesture-controlled surface exists on the audited public templates.",
      "reason": "No carousel, draggable item, swipe action or other gesture-controlled surface exists on the audited public templates."
    },
    {
      "principleId": "provide-guided-navigation",
      "checkId": "scroll-state-aware-chrome",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: a transition video of scrolling, or CSS inspection for scroll-state container queries. The model chooses.",
      "evidence": "The mobile terms screenshot shows dense continuous content while DOM/CSS inspection found no sticky section navigation, progress indicator, or scroll-state query.",
      "pathIds": [
        "terms"
      ],
      "findingIds": [
        "F03"
      ]
    },
    {
      "principleId": "provide-guided-navigation",
      "checkId": "anchored-positioning",
      "status": "not-applicable",
      "confidence": "high",
      "method": "HINT: CSS inspection for anchor-name / position-anchor / position-try on overlays; a screenshot of an open overlay near a viewport edge can show drift. The model chooses.",
      "evidence": "No tooltip, menu, popover or other anchored overlay exists on the audited public templates.",
      "reason": "No tooltip, menu, popover or other anchored overlay exists on the audited public templates."
    },
    {
      "principleId": "provide-guided-navigation",
      "checkId": "directs-attention",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: CSS inspection for ::highlight / scroll-marker; a transition video can show whether attention is cued after navigation. The model chooses.",
      "evidence": "Mobile captures show clear primary login/join links and the contact page presents descriptive, task-specific content-removal choices.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "maximize-content-reduce-noise",
      "checkId": "no-intrusive-interruptions",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: a screenshot on load, or a DOM probe for full-viewport overlays present before interaction. The model chooses.",
      "evidence": "Screenshots after load show core content immediately with no interstitial, consent wall, autoplay or full-viewport overlay.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "maximize-content-reduce-noise",
      "checkId": "semantic-dismissible-primitives",
      "status": "not-applicable",
      "confidence": "high",
      "method": "HINT: DOM/source inspection for popover / <dialog> / <details> vs custom overlay divs with manual dismiss handling. The model chooses.",
      "evidence": "No dialog, popover, disclosure or interruptive overlay exists on the audited public templates.",
      "reason": "No dialog, popover, disclosure or interruptive overlay exists on the audited public templates."
    },
    {
      "principleId": "maximize-content-reduce-noise",
      "checkId": "reduced-chrome",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: a screenshot plus layout metrics can show the proportion of the viewport given to chrome vs content. The model chooses.",
      "evidence": "Entry, login and registration captures devote nearly all space to core content and controls with minimal navigation chrome.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "adapt-to-the-form-factor",
      "checkId": "responsive-no-horizontal-scroll",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: layout metrics (scrollWidth vs innerWidth) and a screenshot at an emulated narrow mobile viewport reveal overflow. The model chooses.",
      "evidence": "Layout metrics at 390 by 844 report 0 pixels of horizontal overflow on home and registration.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "adapt-to-the-form-factor",
      "checkId": "component-level-responsiveness",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: CSS inspection for @container / container-type; a computed-style probe of the same component in a wide vs narrow container shows whether it adapts. The model chooses.",
      "evidence": "The same public templates fit both 390 and 1440 pixel captures using fluid logo and form widths, with no clipping or overflow.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "adapt-to-the-form-factor",
      "checkId": "input-modality-aware",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: a focus probe (focus an element, read the computed outline) or an axe target-size check; a screenshot of a focused control corroborates. The model chooses.",
      "evidence": "axe flags maximum-scale=1 as a critical meta-viewport failure on all four templates. The registration probe measures radio buttons and checkboxes at 13 by 13 CSS pixels.",
      "pathIds": [
        "register"
      ],
      "findingIds": [
        "F04"
      ]
    },
    {
      "principleId": "support-core-task-success",
      "checkId": "clear-purpose-and-primary-action",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: screenshot the first viewport and key scrolled states; inspect heading structure, nav labels, button text, and visual hierarchy; a task walkthrough can show whether the next action is obvious. The model chooses.",
      "evidence": "The entry viewport states member/non-member choices and exposes direct Login and Join for free actions; contact choices use descriptive labels.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "support-core-task-success",
      "checkId": "primary-flow-completion",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: run the flow manually with screenshots/DOM snapshots at each step; compare expected vs actual path length; inspect form requirements, navigation continuity, and blockers. The model chooses.",
      "evidence": "The unauthenticated journey was walked from entry to login, password recovery link, registration fields, age consent and final submit control; no account was created to avoid external side effects.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "support-core-task-success",
      "checkId": "clear-system-state-and-recovery",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: exercise network delay/failure, invalid input, empty data and success states; screenshot the state messaging and recovery controls; inspect whether browser history and focus remain sensible. The model chooses.",
      "evidence": "Calling the page’s own checkForm() on an empty form returned false and raised only “You need to enter a username to use on the site!”; there were no :invalid controls, aria-invalid states, role=alert elements, or live regions.",
      "pathIds": [
        "register"
      ],
      "findingIds": [
        "F05"
      ]
    },
    {
      "principleId": "be-fast-and-stable",
      "checkId": "good-core-web-vitals",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: Lighthouse reports LCP/CLS/TBT directly and the model may run it; layout metrics + a layout-shift observer + a long-task observer (the evidence primitives) give the same signal first-party. The model chooses.",
      "evidence": "Trace reports FCP 530 ms, LCP 742 ms and 0 ms TBT; Lighthouse reports LCP 1.7 s, CLS 0.028 and TBT 0 ms.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-fast-and-stable",
      "checkId": "visual-stability",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: the layout primitive's CLS observer captures shifts; a transition video of the first seconds shows content jumping. The model chooses.",
      "evidence": "Mobile layout observers report CLS 0 on home and registration, while Lighthouse reports CLS 0.028, within the good threshold.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-fast-and-stable",
      "checkId": "efficient-main-thread",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: the layout primitive records long tasks; a heap summary shows the object population; Lighthouse reports TBT. The model chooses.",
      "evidence": "Trace records no long tasks and 0 ms total blocking time; the entry page loads no application JavaScript.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-fast-and-stable",
      "checkId": "efficient-resource-delivery",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: a HAR summary can reveal cache headers, redirects, render-blocking candidates, weight offenders and dependency shape; a trace/Lighthouse insight report can corroborate LCP discovery, render-blocking, font-display and document latency. The model chooses.",
      "evidence": "The image primitive reports 8 of 8 images without dimensions and no responsive source for the logo. Lighthouse flags unsized and low-resolution images plus short cache opportunities, although the whole page transfers only 22.9 KB.",
      "pathIds": [
        "home"
      ],
      "findingIds": [
        "F06"
      ]
    },
    {
      "principleId": "be-fast-and-stable",
      "checkId": "trim-unused-and-duplicate-code",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: Lighthouse/trace/code-coverage style evidence can flag unused JS/CSS, duplicated JavaScript and legacy code; a HAR summary shows third-party byte cost and request count. The model chooses.",
      "evidence": "HAR contains no script resources and only 8 requests totaling 22.9 KB; no duplicate or unused code payload is evident.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-inclusive",
      "checkId": "names-roles-labels",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: axe-core (injectable via the evaluate primitive) or Lighthouse's a11y audits enumerate these; a DOM probe of the accessibility-relevant attributes is a first-party alternative. The model chooses.",
      "evidence": "axe reports unlabeled username, email, password, all three date selects, and the login persistence checkbox. The home image audit also finds 7 decorative icons without alt text.",
      "pathIds": [
        "register"
      ],
      "findingIds": [
        "F07"
      ]
    },
    {
      "principleId": "be-inclusive",
      "checkId": "sufficient-contrast",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: axe contrast rules, a Lighthouse contrast audit, or an in-page probe computing contrast ratios from computed colours. The model chooses.",
      "evidence": "Forced-colors capture remains readable and Lighthouse/axe report no definite color-contrast violation on the entry and terms templates.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-inclusive",
      "checkId": "structure-and-focus",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: axe/Lighthouse structural audits; a focus-walk probe (tab through, read activeElement + computed outline) is a first-party alternative. The model chooses.",
      "evidence": "axe reports no main landmark across the sampled templates and no H1 on home, login and registration. DOM probes confirm zero main/nav elements and zero headings on the entry page.",
      "pathIds": [
        "home"
      ],
      "findingIds": [
        "F08"
      ]
    },
    {
      "principleId": "be-inclusive",
      "checkId": "legible-text",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: a screenshot of body and heading text, plus CSS inspection for text-wrap / text alignment / font fallback handling. The model chooses.",
      "evidence": "The 390-pixel screenshot shows 13-pixel Arial paragraphs spanning nearly the full viewport width; the terms page has one H1 but numbered sections are mostly bold paragraphs rather than navigable headings.",
      "pathIds": [
        "terms"
      ],
      "findingIds": [
        "F09"
      ]
    },
    {
      "principleId": "be-inclusive",
      "checkId": "zoom-reflow-targets-and-media",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: Lighthouse/axe target-size, meta-viewport and media-caption audits are useful signals; screenshots at narrow and zoomed conditions plus DOM/media inspection can corroborate. The model chooses.",
      "evidence": "axe flags maximum-scale=1 as a critical meta-viewport failure on all four templates. The registration probe measures radio buttons and checkboxes at 13 by 13 CSS pixels.",
      "pathIds": [
        "register"
      ],
      "findingIds": [
        "F04"
      ]
    },
    {
      "principleId": "follow-best-practices",
      "checkId": "no-console-errors",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: capture Runtime/Log CDP events, or a probe that reads collected errors; Lighthouse reports this too. The model chooses.",
      "evidence": "Lighthouse’s errors-in-console audit passed and no application JavaScript runs on the entry template.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "follow-best-practices",
      "checkId": "sound-document-and-assets",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: a DOM/source probe for doctype/charset/img dimensions; CSS inspection for repetition; Lighthouse best-practices audits cover the rest. The model chooses.",
      "evidence": "Rendered HTML uses layout tables, align, hspace and vspace attributes and inline presentational styles; the image inventory reports all eight images without width and height.",
      "pathIds": [
        "home"
      ],
      "findingIds": [
        "F10"
      ]
    },
    {
      "principleId": "follow-best-practices",
      "checkId": "browser-platform-hygiene",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: Lighthouse best-practices audits and DevTools inspector/deprecation signals can surface these; DOM/source probes can verify paste handlers and prompt timing. The model chooses.",
      "evidence": "Lighthouse reports one bfcache failure reason on the entry page.",
      "pathIds": [
        "home"
      ],
      "findingIds": [
        "F11"
      ]
    },
    {
      "principleId": "be-discoverable",
      "checkId": "title-and-description",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: a DOM probe reads <title> and meta[name=description]; Lighthouse SEO audits cover the same ground. The model chooses.",
      "evidence": "Login has an empty document title, registration is titled only “register”, and no sampled page provides a meta description. Lighthouse fails the entry page meta-description audit.",
      "pathIds": [
        "login"
      ],
      "findingIds": [
        "F12"
      ]
    },
    {
      "principleId": "be-discoverable",
      "checkId": "crawlable-and-mobile-friendly",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: a DOM probe for anchor hrefs, viewport meta, and robots; Lighthouse SEO audits corroborate. The model chooses.",
      "evidence": "Discoverability captures show 100% content coverage without JavaScript on home, registration and terms; links use hrefs, robots.txt exists, and mobile layout has no overflow.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-discoverable",
      "checkId": "canonical-and-indexing-signals",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: inspect response status and headers, <link rel=canonical>, hreflang links, robots meta, robots.txt and sitemap.xml; Lighthouse SEO audits cover several of these. The model chooses.",
      "evidence": "The active fetch probe received HTTP 404 for /sitemap.xml. robots.txt exists and intentionally excludes private, login and registration routes.",
      "pathIds": [
        "home"
      ],
      "findingIds": [
        "F13"
      ]
    },
    {
      "principleId": "be-discoverable",
      "checkId": "structured-and-shareable-metadata",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: inspect JSON-LD/microdata and social preview tags against visible content; Lighthouse has a manual structured-data audit, and ad-hoc probes can parse schema.org blocks. The model chooses.",
      "evidence": "The platform probe finds zero JSON-LD blocks and zero Open Graph metadata on the entry and registration pages.",
      "pathIds": [
        "home"
      ],
      "findingIds": [
        "F14"
      ]
    },
    {
      "principleId": "be-private-and-secure",
      "checkId": "secure-transport-and-headers",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: inspect response headers / page protocol via an evaluate probe or the network layer; Lighthouse best-practices flags HTTPS and CSP issues. The model chooses.",
      "evidence": "The headers primitive finds no CSP, HSTS, nosniff, Referrer-Policy or Permissions-Policy. Cookie inspection finds AWSALB, AWSALBTG, tc, m and ASP.NET_SessionId without Secure, with several SameSite=None cookies and two 400-day cookies.",
      "pathIds": [
        "home"
      ],
      "findingIds": [
        "F15"
      ]
    },
    {
      "principleId": "be-private-and-secure",
      "checkId": "data-minimisation-and-third-parties",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: inspect network requests and third-party origins; a probe of analytics/beacon calls. The model chooses.",
      "evidence": "HAR transfers only 22.9 KB, with one same-site asset origin and no known trackers; secret scan reports zero findings.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-private-and-secure",
      "checkId": "in-context-permissions-and-modern-auth",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: a probe for permission requests fired on load; source inspection for passkey / WebAuthn / navigator.credentials usage in auth flows. The model chooses.",
      "evidence": "Login DOM contains only username/email, password, persistence and submit controls; there is no WebAuthn or navigator.credentials integration and no permission prompt is made on load.",
      "pathIds": [
        "login"
      ],
      "findingIds": [
        "F20"
      ]
    },
    {
      "principleId": "be-private-and-secure",
      "checkId": "defensive-browser-policies",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: inspect response headers and browser security state; Lighthouse/DevTools security audits can corroborate HSTS, clickjacking, Trusted Types, origin isolation and third-party cookie findings. The model chooses.",
      "evidence": "The headers primitive finds no CSP, HSTS, nosniff, Referrer-Policy or Permissions-Policy. Cookie inspection finds AWSALB, AWSALBTG, tc, m and ASP.NET_SessionId without Secure, with several SameSite=None cookies and two 400-day cookies.",
      "pathIds": [
        "home"
      ],
      "findingIds": [
        "F15"
      ]
    },
    {
      "principleId": "be-resilient",
      "checkId": "progressive-enhancement",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: load with scripting disabled or compare a no-JS fetch of the HTML against the rendered page; check for Baseline-aware fallbacks in source. The model chooses.",
      "evidence": "Raw HTML contains 100% of rendered content across three archetypes and registration remains visible without JavaScript.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-resilient",
      "checkId": "resilient-runtime-behaviour",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: exercise menus near viewport edges with a screenshot; a probe of async/visibility behaviour. The model chooses.",
      "evidence": "The public MPA uses native links and form controls, no async dependencies or custom overlays, and offers contact/content-removal routes without script.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-resilient",
      "checkId": "offline-and-installable",
      "status": "not-applicable",
      "confidence": "high",
      "method": "HINT: a probe for a service worker registration and a web app manifest; test behaviour offline. The model chooses.",
      "evidence": "This account-based adult web service does not present an installable or offline use case on its public surface; server-rendered fallback remains applicable and was tested.",
      "reason": "This account-based adult web service does not present an installable or offline use case on its public surface; server-rendered fallback remains applicable and was tested."
    },
    {
      "principleId": "be-resilient",
      "checkId": "network-and-http-failure-states",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: simulate failed fetches/offline mode or inspect representative 404/500 routes; screenshots and DOM snapshots of error/loading/empty states show whether recovery is possible. The model chooses.",
      "evidence": "The server correctly returns HTTP 404, but the page contains only “File not found” and one home link, with no search, context, navigation or contact route.",
      "pathIds": [
        "not-found"
      ],
      "findingIds": [
        "F16"
      ]
    },
    {
      "principleId": "be-internationalised",
      "checkId": "lang-dir-and-logical-properties",
      "status": "not-applicable",
      "confidence": "high",
      "method": "HINT: a DOM probe for <html lang>/dir and CSS inspection for logical vs physical properties. The model chooses.",
      "evidence": "The terms explicitly state that the service is English-only, so translation and bidi adaptation are outside current product scope; missing lang is still reported under inclusivity.",
      "reason": "The terms explicitly state that the service is English-only, so translation and bidi adaptation are outside current product scope; missing lang is still reported under inclusivity."
    },
    {
      "principleId": "be-internationalised",
      "checkId": "locale-aware-data",
      "status": "not-applicable",
      "confidence": "high",
      "method": "HINT: source inspection for Intl.* usage vs hand-rolled formatting; a probe of rendered dates/numbers under a different locale. The model chooses.",
      "evidence": "The audited public templates expose no locale-dependent numeric, currency or interactive date formatting; the only dates are English legal copy.",
      "reason": "The audited public templates expose no locale-dependent numeric, currency or interactive date formatting; the only dates are English legal copy."
    },
    {
      "principleId": "be-internationalised",
      "checkId": "time-zone-correctness",
      "status": "not-applicable",
      "confidence": "high",
      "method": "HINT: source inspection for time-zone-aware date handling vs naive local Date math. The model chooses.",
      "evidence": "No event scheduling or user-facing time-zone-sensitive date/time surface is present on the audited public templates.",
      "reason": "No event scheduling or user-facing time-zone-sensitive date/time surface is present on the audited public templates."
    },
    {
      "principleId": "be-trustworthy",
      "checkId": "no-dark-patterns",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: a screenshot of consent/upsell/cancel flows; source inspection for declarative button actions vs misleading controls. The model chooses.",
      "evidence": "Registration clearly identifies public versus private data, age consent and free status; terms provide cancellation and content-removal routes.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-trustworthy",
      "checkId": "humane-error-handling",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: exercise a form, submit invalid input, and observe timing and clarity of errors via a screenshot or a :user-invalid / aria-invalid probe. The model chooses.",
      "evidence": "The empty-form test triggers a modal JavaScript alert for the first missing field and exposes no inline invalid state or live announcement.",
      "pathIds": [
        "register"
      ],
      "findingIds": [
        "F17"
      ]
    },
    {
      "principleId": "be-trustworthy",
      "checkId": "trustworthy-input-assistance",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: source/DOM inspection for autocomplete attributes on form fields; a probe of autofill affordances. The model chooses.",
      "evidence": "The login username and password have no autocomplete tokens; registration email has none, username disables autocomplete, and the password is DOM type=text despite autocomplete=new-password. “Keep logged in” is preselected.",
      "pathIds": [
        "login"
      ],
      "findingIds": [
        "F18"
      ]
    },
    {
      "principleId": "be-trustworthy",
      "checkId": "safe-commercial-and-account-flows",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: walkthrough checkout/subscription/auth/account flows when present; screenshot pricing, confirmation, cancellation and reauthentication states; inspect passkey/autocomplete support for sign-in and payment. The model chooses.",
      "evidence": "Public login includes password recovery; registration states age, privacy and rules before account creation; no payment or subscription step is presented in scope.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-sustainable",
      "checkId": "optimised-assets",
      "status": "issues",
      "confidence": "high",
      "method": "HINT: inspect transferred image bytes vs displayed size; source inspection for modern formats and resolution handling. The model chooses.",
      "evidence": "The image audit reports 8 legacy JPG/PNG/GIF resources, no modern formats, 8 missing dimensions and a missing responsive source for the logo. Total transfer remains an excellent 22.9 KB.",
      "pathIds": [
        "home"
      ],
      "findingIds": [
        "F19"
      ]
    },
    {
      "principleId": "be-sustainable",
      "checkId": "no-wasteful-work",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: a long-task / network probe for background fetches and processing while idle or backgrounded. The model chooses.",
      "evidence": "Trace records no long tasks and HAR records no background fetches, analytics or script work during the observation window.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-sustainable",
      "checkId": "third-party-and-media-budget",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: a HAR summary shows third-party bytes, font/media weight and caching; screenshots/video reveal autoplay and decorative media; trace/layout evidence shows whether media/animation keeps work running. The model chooses.",
      "evidence": "The page transfers 22.9 KB in 8 requests, contains no autoplay media or tracker, and only 16.9 KB comes from the dedicated static asset host.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-agent-ready",
      "checkId": "structured-agent-capabilities",
      "status": "not-applicable",
      "confidence": "high",
      "method": "HINT: source inspection for WebMCP / agentic-tool registration and agent-readable affordances. The model chooses.",
      "evidence": "This is a sensitive, authenticated adult social service. Exposing account actions to autonomous agents is not an appropriate public-surface requirement without an explicit safety model.",
      "reason": "This is a sensitive, authenticated adult social service. Exposing account actions to autonomous agents is not an appropriate public-surface requirement without an explicit safety model."
    },
    {
      "principleId": "be-agent-ready",
      "checkId": "on-device-inference",
      "status": "not-applicable",
      "confidence": "high",
      "method": "HINT: source inspection for built-in AI (language model / summariser) usage. The model chooses.",
      "evidence": "No user-facing summarisation, generation or inference feature exists on the audited public templates.",
      "reason": "No user-facing summarisation, generation or inference feature exists on the audited public templates."
    },
    {
      "principleId": "be-memory-efficient",
      "checkId": "no-leak-under-repeated-interaction",
      "status": "pass",
      "confidence": "high",
      "method": "HINT (not mandatory): compare heap snapshots for retained growth - a baseline, then one taken after repeating the interaction with `--interact` about 10x (the memory-tracer methodology: baseline -> repeat -> post -> compare). Performance.getMetrics (JSHeapUsedSize, Nodes) across the same before/after window is corroboration. If Chrome DevTools MCP is available, follow its memory-leak-debugging skill: capture baseline, target, and final snapshots, then use memlab or the provided comparison workflow rather than reading raw .heapsnapshot files directly. The package-native `heap` primitive remains the default path. This check is only meaningful where the page has a real interaction to repeat; for a static page with none, mark it not-applicable with a rationale rather than fabricating one. The model chooses.",
      "evidence": "Ten repeated radio/select interactions increased the fresh-profile snapshot by only 14,958 bytes and 174 nodes, with no Detached constructor population.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-memory-efficient",
      "checkId": "bounded-footprint",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: a single `heap` summary's totals (nodeCount, totalSelfSizeBytes, constructor population) plus Performance.getMetrics (Nodes, JSHeapUsedSize) give the current footprint to judge against the page's purpose. Chrome DevTools MCP heap snapshots and memlab snapshot analysis can provide the same memory distribution when available. Read summaries or derived analysis, never raw snapshots unless a dedicated heap-analysis tool is doing the analysis. The model chooses.",
      "evidence": "Registration heap is about 1.72 MB baseline and 1.74 MB post-interaction, proportionate to a small server-rendered form.",
      "pathIds": [
        "home"
      ]
    },
    {
      "principleId": "be-memory-efficient",
      "checkId": "no-detached-dom-or-unbounded-listeners",
      "status": "pass",
      "confidence": "high",
      "method": "HINT: the `heap` summary by constructor (Detached* nodes) compared across a before/after pair shows a growing detached-DOM population; an `evaluate` probe can sample listener/timer counts (e.g. getEventListeners-style counting, or instrumenting addEventListener/setInterval) before and after the repeated interaction to spot growth. Chrome DevTools MCP heap snapshots plus the memory-leak-debugging skill's common-leak guidance can corroborate detached DOM, listeners, closures, globals, and unbounded caches. Caveat from the memory-tracer and Chrome DevTools MCP guidance: detached nodes can be intentional caches, so judge confidence rather than asserting a bug. The model chooses.",
      "evidence": "Before/after summaries contain no Detached constructors and repeated controls do not create DOM subtrees; observed growth is small and bounded.",
      "pathIds": [
        "home"
      ]
    }
  ],
  "principleOutcomes": [
    {
      "principleId": "respect-user-preferences",
      "expectation": "default",
      "status": "issues",
      "findingIds": [
        "F01"
      ]
    },
    {
      "principleId": "implement-natural-interactions",
      "expectation": "default",
      "status": "issues",
      "findingIds": [
        "F02"
      ]
    },
    {
      "principleId": "provide-guided-navigation",
      "expectation": "default",
      "status": "issues",
      "findingIds": [
        "F03"
      ]
    },
    {
      "principleId": "maximize-content-reduce-noise",
      "expectation": "default",
      "status": "pass"
    },
    {
      "principleId": "adapt-to-the-form-factor",
      "expectation": "default",
      "status": "issues",
      "findingIds": [
        "F04"
      ]
    },
    {
      "principleId": "support-core-task-success",
      "expectation": "default",
      "status": "issues",
      "findingIds": [
        "F05"
      ]
    },
    {
      "principleId": "be-fast-and-stable",
      "expectation": "default",
      "status": "issues",
      "findingIds": [
        "F06"
      ]
    },
    {
      "principleId": "be-inclusive",
      "expectation": "default",
      "status": "issues",
      "findingIds": [
        "F07",
        "F08",
        "F09",
        "F04"
      ]
    },
    {
      "principleId": "follow-best-practices",
      "expectation": "default",
      "status": "issues",
      "findingIds": [
        "F10",
        "F11"
      ]
    },
    {
      "principleId": "be-discoverable",
      "expectation": "default",
      "status": "issues",
      "findingIds": [
        "F12",
        "F13",
        "F14"
      ]
    },
    {
      "principleId": "be-private-and-secure",
      "expectation": "default",
      "status": "issues",
      "findingIds": [
        "F15",
        "F20"
      ]
    },
    {
      "principleId": "be-resilient",
      "expectation": "contextual",
      "status": "issues",
      "findingIds": [
        "F16"
      ]
    },
    {
      "principleId": "be-internationalised",
      "expectation": "contextual",
      "status": "not-applicable",
      "reason": "The terms explicitly state that the service is English-only, so translation and bidi adaptation are outside current product scope; missing lang is still reported under inclusivity. The audited public templates expose no locale-dependent numeric, currency or interactive date formatting; the only dates are English legal copy. No event scheduling or user-facing time-zone-sensitive date/time surface is present on the audited public templates."
    },
    {
      "principleId": "be-trustworthy",
      "expectation": "default",
      "status": "issues",
      "findingIds": [
        "F17",
        "F18"
      ]
    },
    {
      "principleId": "be-sustainable",
      "expectation": "contextual",
      "status": "issues",
      "findingIds": [
        "F19"
      ]
    },
    {
      "principleId": "be-agent-ready",
      "expectation": "contextual",
      "status": "not-applicable",
      "reason": "This is a sensitive, authenticated adult social service. Exposing account actions to autonomous agents is not an appropriate public-surface requirement without an explicit safety model. No user-facing summarisation, generation or inference feature exists on the audited public templates."
    },
    {
      "principleId": "be-memory-efficient",
      "expectation": "default",
      "status": "pass"
    }
  ],
  "paths": [
    {
      "id": "home",
      "description": "Entry and acquisition template: purpose, primary actions, responsive presentation, global network/security/performance and metadata.",
      "url": "https://m.fabswingers.com/",
      "conditions": [
        "390x844",
        "1440x900",
        "prefers-color-scheme: dark",
        "prefers-reduced-motion: reduce",
        "JavaScript disabled"
      ],
      "result": "issues"
    },
    {
      "id": "login",
      "description": "Authentication template: labels, autofill, account recovery and document metadata.",
      "url": "https://m.fabswingers.com/login.aspx",
      "conditions": [
        "390x844",
        "keyboard focus",
        "axe-core"
      ],
      "result": "issues"
    },
    {
      "id": "register",
      "description": "Primary registration form: controls, consent, validation, accessibility, forced colors, responsiveness and repeated-interaction memory.",
      "url": "https://m.fabswingers.com/register.aspx?tip=signupffm",
      "conditions": [
        "390x844",
        "forced-colors: active",
        "keyboard focus",
        "JavaScript disabled",
        "10 repeated interactions"
      ],
      "result": "issues"
    },
    {
      "id": "contact",
      "description": "Safety/contact routing template: content-removal choices and owner contact.",
      "url": "https://m.fabswingers.com/contact-us",
      "conditions": [
        "rendered DOM"
      ],
      "result": "pass"
    },
    {
      "id": "terms",
      "description": "Long-form legal content template: headings, legibility, navigation, language/date handling and no-JS delivery.",
      "url": "https://m.fabswingers.com/articles/terms",
      "conditions": [
        "390x844",
        "JavaScript disabled",
        "axe-core"
      ],
      "result": "issues"
    },
    {
      "id": "age-assurance",
      "description": "Sensitive informational content: age-check methods, privacy explanation and heading structure.",
      "url": "https://m.fabswingers.com/content/age-assurance",
      "conditions": [
        "rendered DOM"
      ],
      "result": "pass"
    },
    {
      "id": "not-found",
      "description": "HTTP/network failure recovery using a deliberately nonexistent route.",
      "url": "https://m.fabswingers.com/not-a-real-route-web-uplift",
      "conditions": [
        "390x844",
        "HTTP status probe"
      ],
      "result": "issues"
    }
  ],
  "findings": [
    {
      "id": "F01",
      "pathId": "home",
      "url": "https://m.fabswingers.com/",
      "principleId": "respect-user-preferences",
      "principleCheckId": "respects-color-scheme",
      "guidanceId": "dark-mode",
      "guidanceCategory": "user-experience",
      "severity": "medium",
      "confidence": "high",
      "summary": "The site does not adapt to the user’s dark color scheme.",
      "evidence": "The dark-mode screenshot is byte-identical in appearance to the light capture, and the platform probe reports colorScheme \"normal\" with no prefers-color-scheme rule.",
      "artifacts": [
        "evidence/home-dark-reduced.png",
        "evidence/home-platform-probe.json"
      ],
      "suggestedFix": "Declare color-scheme and provide dark surface, text, link, border and image treatments through prefers-color-scheme or light-dark().",
      "effort": "medium"
    },
    {
      "id": "F02",
      "pathId": "home",
      "url": "https://m.fabswingers.com/",
      "principleId": "implement-natural-interactions",
      "principleCheckId": "view-transitions",
      "guidanceId": "cross-document-transitions",
      "guidanceCategory": "user-experience",
      "severity": "low",
      "confidence": "medium",
      "summary": "Primary cross-document navigation has no visual continuity.",
      "evidence": "DOM and platform probes show ordinary multi-page links, zero active animations, and no view-transition CSS or meta opt-in.",
      "artifacts": [
        "evidence/home-dom.json",
        "evidence/home-platform-probe.json"
      ],
      "suggestedFix": "Use cross-document view transitions for same-origin navigation, with a reduced-motion-safe fallback and restrained shared-element treatment.",
      "effort": "small"
    },
    {
      "id": "F03",
      "pathId": "terms",
      "url": "https://m.fabswingers.com/articles/terms",
      "principleId": "provide-guided-navigation",
      "principleCheckId": "scroll-state-aware-chrome",
      "guidanceId": "scroll-progress-indicator",
      "guidanceCategory": "user-experience",
      "severity": "low",
      "confidence": "medium",
      "summary": "The very long terms page provides no position or progress cue.",
      "evidence": "The mobile terms screenshot shows dense continuous content while DOM/CSS inspection found no sticky section navigation, progress indicator, or scroll-state query.",
      "artifacts": [
        "evidence/terms-mobile.png",
        "evidence/home-mobile.png"
      ],
      "suggestedFix": "Add a compact table of contents and an accessible scroll-driven progress cue that respects reduced motion.",
      "effort": "medium"
    },
    {
      "id": "F04",
      "pathId": "register",
      "url": "https://m.fabswingers.com/register.aspx?tip=signupffm",
      "principleId": "be-inclusive",
      "principleCheckId": "zoom-reflow-targets-and-media",
      "guidanceId": "accessibility",
      "guidanceCategory": "accessibility",
      "severity": "high",
      "confidence": "high",
      "summary": "The viewport policy restricts zoom and several controls have undersized visual targets.",
      "evidence": "axe flags maximum-scale=1 as a critical meta-viewport failure on all four templates. The registration probe measures radio buttons and checkboxes at 13 by 13 CSS pixels.",
      "artifacts": [
        "evidence/axe-register.json",
        "evidence/register-platform-probe.json",
        "evidence/register-mobile.png"
      ],
      "suggestedFix": "Remove maximum-scale and minimum-scale restrictions, preserve user zoom, and give compact controls and footer links at least a 24 by 24 CSS pixel target with spacing, preferably 44 by 44 for primary touch actions.",
      "effort": "small"
    },
    {
      "id": "F05",
      "pathId": "register",
      "url": "https://m.fabswingers.com/register.aspx?tip=signupffm",
      "principleId": "support-core-task-success",
      "principleCheckId": "clear-system-state-and-recovery",
      "guidanceId": "accessible-error-announcement",
      "guidanceCategory": "accessibility",
      "severity": "medium",
      "confidence": "high",
      "summary": "Registration errors are delivered as blocking alerts without field-level recovery guidance.",
      "evidence": "Calling the page’s own checkForm() on an empty form returned false and raised only “You need to enter a username to use on the site!”; there were no :invalid controls, aria-invalid states, role=alert elements, or live regions.",
      "artifacts": [
        "evidence/register-validation.json"
      ],
      "suggestedFix": "Use native constraints and inline field errors after interaction, focus the first invalid field, set aria-invalid and connect messages with aria-describedby or a live error summary.",
      "effort": "medium"
    },
    {
      "id": "F06",
      "pathId": "home",
      "url": "https://m.fabswingers.com/",
      "principleId": "be-fast-and-stable",
      "principleCheckId": "efficient-resource-delivery",
      "guidanceId": "optimize-image-priority",
      "guidanceCategory": "performance",
      "severity": "low",
      "confidence": "high",
      "summary": "Image delivery misses basic sizing and responsive-image hygiene despite a very small page.",
      "evidence": "The image primitive reports 8 of 8 images without dimensions and no responsive source for the logo. Lighthouse flags unsized and low-resolution images plus short cache opportunities, although the whole page transfers only 22.9 KB.",
      "artifacts": [
        "evidence/home-images.json",
        "evidence/lighthouse-home.json",
        "evidence/home-summary.json"
      ],
      "suggestedFix": "Add intrinsic width and height, provide a resolution-appropriate srcset for the logo, and retain long immutable caching for static image assets.",
      "effort": "small"
    },
    {
      "id": "F07",
      "pathId": "register",
      "url": "https://m.fabswingers.com/register.aspx?tip=signupffm",
      "principleId": "be-inclusive",
      "principleCheckId": "names-roles-labels",
      "guidanceId": "accessibility",
      "guidanceCategory": "accessibility",
      "severity": "high",
      "confidence": "high",
      "summary": "Important form controls lack programmatic labels and decorative images are announced as unnamed content.",
      "evidence": "axe reports unlabeled username, email, password, all three date selects, and the login persistence checkbox. The home image audit also finds 7 decorative icons without alt text.",
      "artifacts": [
        "evidence/axe-register.json",
        "evidence/axe-login.json",
        "evidence/axe-home.json",
        "evidence/home-images.json"
      ],
      "suggestedFix": "Associate visible labels with every input/select, use a fieldset and legend for grouped choices, fix the login checkbox id/for pair, and give decorative icons alt=\"\".",
      "effort": "small"
    },
    {
      "id": "F08",
      "pathId": "home",
      "url": "https://m.fabswingers.com/",
      "principleId": "be-inclusive",
      "principleCheckId": "structure-and-focus",
      "guidanceId": "accessibility",
      "guidanceCategory": "accessibility",
      "severity": "medium",
      "confidence": "high",
      "summary": "Most public templates lack headings and landmarks.",
      "evidence": "axe reports no main landmark across the sampled templates and no H1 on home, login and registration. DOM probes confirm zero main/nav elements and zero headings on the entry page.",
      "artifacts": [
        "evidence/axe-home.json",
        "evidence/axe-login.json",
        "evidence/axe-register.json",
        "evidence/home-platform-probe.json"
      ],
      "suggestedFix": "Introduce header, main, nav and footer landmarks, add one descriptive H1 per template, and keep a logical heading hierarchy.",
      "effort": "medium"
    },
    {
      "id": "F09",
      "pathId": "terms",
      "url": "https://m.fabswingers.com/articles/terms",
      "principleId": "be-inclusive",
      "principleCheckId": "legible-text",
      "guidanceId": "improve-text-layout-and-legibility",
      "guidanceCategory": "css",
      "severity": "medium",
      "confidence": "high",
      "summary": "Long-form legal content is dense and uses small text with little reading structure.",
      "evidence": "The 390-pixel screenshot shows 13-pixel Arial paragraphs spanning nearly the full viewport width; the terms page has one H1 but numbered sections are mostly bold paragraphs rather than navigable headings.",
      "artifacts": [
        "evidence/terms-mobile.png",
        "evidence/terms-recon.json"
      ],
      "suggestedFix": "Use at least 1rem body text, a comfortable line-height and measure, and semantic H2/H3 section headings with a table of contents.",
      "effort": "medium"
    },
    {
      "id": "F10",
      "pathId": "home",
      "url": "https://m.fabswingers.com/",
      "principleId": "follow-best-practices",
      "principleCheckId": "sound-document-and-assets",
      "guidanceId": "html",
      "guidanceCategory": "html",
      "severity": "low",
      "confidence": "high",
      "summary": "The public templates retain obsolete presentational markup and omit intrinsic image dimensions.",
      "evidence": "Rendered HTML uses layout tables, align, hspace and vspace attributes and inline presentational styles; the image inventory reports all eight images without width and height.",
      "artifacts": [
        "evidence/home-dom.json",
        "evidence/home-images.json"
      ],
      "suggestedFix": "Replace layout tables and obsolete attributes with semantic HTML and CSS, then set intrinsic dimensions on images.",
      "effort": "medium"
    },
    {
      "id": "F11",
      "pathId": "home",
      "url": "https://m.fabswingers.com/",
      "principleId": "follow-best-practices",
      "principleCheckId": "browser-platform-hygiene",
      "guidanceId": "html",
      "guidanceCategory": "html",
      "severity": "low",
      "confidence": "medium",
      "summary": "The entry page is not eligible for back-forward cache restoration.",
      "evidence": "Lighthouse reports one bfcache failure reason on the entry page.",
      "artifacts": [
        "evidence/lighthouse-home.json"
      ],
      "suggestedFix": "Inspect the Lighthouse bfcache failure reason and remove unload handlers, cache-blocking responses, or other disqualifying behavior where safe for authenticated state.",
      "effort": "medium"
    },
    {
      "id": "F12",
      "pathId": "login",
      "url": "https://m.fabswingers.com/login.aspx",
      "principleId": "be-discoverable",
      "principleCheckId": "title-and-description",
      "guidanceId": "html",
      "guidanceCategory": "html",
      "severity": "medium",
      "confidence": "high",
      "summary": "Public templates have weak or missing search snippets and page titles.",
      "evidence": "Login has an empty document title, registration is titled only “register”, and no sampled page provides a meta description. Lighthouse fails the entry page meta-description audit.",
      "artifacts": [
        "evidence/login-recon.json",
        "evidence/home-discoverability.json",
        "evidence/lighthouse-home.json"
      ],
      "suggestedFix": "Give each public template a unique descriptive title and concise meta description aligned with its visible purpose.",
      "effort": "small"
    },
    {
      "id": "F13",
      "pathId": "home",
      "url": "https://m.fabswingers.com/",
      "principleId": "be-discoverable",
      "principleCheckId": "canonical-and-indexing-signals",
      "guidanceId": "html",
      "guidanceCategory": "html",
      "severity": "low",
      "confidence": "high",
      "summary": "The public site provides no XML sitemap.",
      "evidence": "The active fetch probe received HTTP 404 for /sitemap.xml. robots.txt exists and intentionally excludes private, login and registration routes.",
      "artifacts": [
        "evidence/crawl-pwa.json"
      ],
      "suggestedFix": "Publish a sitemap containing only indexable public content and reference it from robots.txt.",
      "effort": "small"
    },
    {
      "id": "F14",
      "pathId": "home",
      "url": "https://m.fabswingers.com/",
      "principleId": "be-discoverable",
      "principleCheckId": "structured-and-shareable-metadata",
      "guidanceId": "html",
      "guidanceCategory": "html",
      "severity": "low",
      "confidence": "high",
      "summary": "Public pages provide no structured data or social-preview metadata.",
      "evidence": "The platform probe finds zero JSON-LD blocks and zero Open Graph metadata on the entry and registration pages.",
      "artifacts": [
        "evidence/home-platform-probe.json",
        "evidence/register-platform-probe.json"
      ],
      "suggestedFix": "Add accurate Organization/WebSite metadata where appropriate and Open Graph/Twitter preview tags for public informational pages.",
      "effort": "small"
    },
    {
      "id": "F15",
      "pathId": "home",
      "url": "https://m.fabswingers.com/",
      "principleId": "be-private-and-secure",
      "principleCheckId": "secure-transport-and-headers",
      "guidanceId": "security",
      "guidanceCategory": "security",
      "severity": "high",
      "confidence": "high",
      "summary": "Security headers are incomplete and sensitive-site cookies are not consistently Secure.",
      "evidence": "The headers primitive finds no CSP, HSTS, nosniff, Referrer-Policy or Permissions-Policy. Cookie inspection finds AWSALB, AWSALBTG, tc, m and ASP.NET_SessionId without Secure, with several SameSite=None cookies and two 400-day cookies.",
      "artifacts": [
        "evidence/headers.json",
        "evidence/cookies.json",
        "evidence/http-probes-headers.txt"
      ],
      "suggestedFix": "Set HSTS, a restrictive CSP, nosniff, Referrer-Policy and Permissions-Policy; mark all HTTPS cookies Secure, choose Lax/Strict unless cross-site use is essential, and reduce unnecessary lifetimes.",
      "effort": "medium"
    },
    {
      "id": "F16",
      "pathId": "not-found",
      "url": "https://m.fabswingers.com/not-a-real-route-web-uplift",
      "principleId": "be-resilient",
      "principleCheckId": "network-and-http-failure-states",
      "guidanceId": "persistent-toast-notifications",
      "guidanceCategory": "user-experience",
      "severity": "low",
      "confidence": "high",
      "summary": "The 404 state is functional but offers almost no recovery help.",
      "evidence": "The server correctly returns HTTP 404, but the page contains only “File not found” and one home link, with no search, context, navigation or contact route.",
      "artifacts": [
        "evidence/not-found-mobile.png",
        "evidence/not-found.json",
        "evidence/http-probes-headers.txt"
      ],
      "suggestedFix": "Keep the correct status while rendering the normal shell, helpful copy, primary navigation, search or relevant destinations, and a contact option.",
      "effort": "small"
    },
    {
      "id": "F17",
      "pathId": "register",
      "url": "https://m.fabswingers.com/register.aspx?tip=signupffm",
      "principleId": "be-trustworthy",
      "principleCheckId": "humane-error-handling",
      "guidanceId": "validate-input-after-interaction",
      "guidanceCategory": "forms",
      "severity": "medium",
      "confidence": "high",
      "summary": "Registration validation is interruptive and not assistive-technology friendly.",
      "evidence": "The empty-form test triggers a modal JavaScript alert for the first missing field and exposes no inline invalid state or live announcement.",
      "artifacts": [
        "evidence/register-validation.json"
      ],
      "suggestedFix": "Validate after interaction or submit using persistent, specific inline messages and an accessible summary instead of alert().",
      "effort": "medium"
    },
    {
      "id": "F18",
      "pathId": "login",
      "url": "https://m.fabswingers.com/login.aspx",
      "principleId": "be-trustworthy",
      "principleCheckId": "trustworthy-input-assistance",
      "guidanceId": "autofill-sign-in-form",
      "guidanceCategory": "forms",
      "severity": "medium",
      "confidence": "high",
      "summary": "Authentication and registration fields do not consistently expose standard autofill semantics.",
      "evidence": "The login username and password have no autocomplete tokens; registration email has none, username disables autocomplete, and the password is DOM type=text despite autocomplete=new-password. “Keep logged in” is preselected.",
      "artifacts": [
        "evidence/login-recon.json",
        "evidence/register-platform-probe.json",
        "evidence/register-mobile.png"
      ],
      "suggestedFix": "Use autocomplete=username/email/current-password/new-password as appropriate, use type=password for secrets, and make persistent-login consent an explicit informed choice.",
      "effort": "small"
    },
    {
      "id": "F19",
      "pathId": "home",
      "url": "https://m.fabswingers.com/",
      "principleId": "be-sustainable",
      "principleCheckId": "optimised-assets",
      "guidanceId": "deliver-optimized-decorative-images",
      "guidanceCategory": "performance",
      "severity": "low",
      "confidence": "high",
      "summary": "All sampled images use legacy formats and omit responsive sizing metadata.",
      "evidence": "The image audit reports 8 legacy JPG/PNG/GIF resources, no modern formats, 8 missing dimensions and a missing responsive source for the logo. Total transfer remains an excellent 22.9 KB.",
      "artifacts": [
        "evidence/home-images.json",
        "evidence/home-summary.json"
      ],
      "suggestedFix": "Where it reduces bytes, serve AVIF/WebP variants and responsive sources, while retaining the site’s strong overall weight budget.",
      "effort": "small"
    },
    {
      "id": "F20",
      "pathId": "login",
      "url": "https://m.fabswingers.com/login.aspx",
      "principleId": "be-private-and-secure",
      "principleCheckId": "in-context-permissions-and-modern-auth",
      "guidanceId": "passkeys",
      "guidanceCategory": "security",
      "severity": "medium",
      "confidence": "high",
      "summary": "The sign-in surface offers password-only authentication with no passkey option.",
      "evidence": "Login DOM contains only username/email, password, persistence and submit controls; there is no WebAuthn or navigator.credentials integration and no permission prompt is made on load.",
      "artifacts": [
        "evidence/login-recon.json",
        "evidence/home-platform-probe.json"
      ],
      "suggestedFix": "Offer passkeys as a phishing-resistant sign-in option, retain password recovery as fallback, and request any device capability only after a clear user action.",
      "effort": "large"
    }
  ],
  "taskList": [
    {
      "id": "T01",
      "title": "Fix form labels, landmarks, headings, zoom and touch targets",
      "priority": 1,
      "findingIds": [
        "F04",
        "F07",
        "F08"
      ],
      "guidanceId": "accessibility",
      "status": "open"
    },
    {
      "id": "T02",
      "title": "Harden security headers and cookie attributes",
      "priority": 2,
      "findingIds": [
        "F15"
      ],
      "guidanceId": "security",
      "status": "open"
    },
    {
      "id": "T03",
      "title": "Replace alert validation with accessible inline recovery",
      "priority": 3,
      "findingIds": [
        "F05",
        "F17"
      ],
      "guidanceId": "accessible-error-announcement",
      "status": "open"
    },
    {
      "id": "T04",
      "title": "Modernise authentication with passkeys and correct autofill/password semantics",
      "priority": 4,
      "findingIds": [
        "F18",
        "F20"
      ],
      "guidanceId": "passkeys",
      "status": "open"
    },
    {
      "id": "T05",
      "title": "Improve titles, descriptions, sitemap and share metadata",
      "priority": 5,
      "findingIds": [
        "F12",
        "F13",
        "F14"
      ],
      "guidanceId": "html",
      "status": "open"
    },
    {
      "id": "T06",
      "title": "Add dark color-scheme support",
      "priority": 6,
      "findingIds": [
        "F01"
      ],
      "guidanceId": "dark-mode",
      "status": "open"
    },
    {
      "id": "T07",
      "title": "Improve long-form terms navigation and typography",
      "priority": 7,
      "findingIds": [
        "F03",
        "F09"
      ],
      "guidanceId": "improve-text-layout-and-legibility",
      "status": "open"
    },
    {
      "id": "T08",
      "title": "Modernise and size image assets",
      "priority": 8,
      "findingIds": [
        "F06",
        "F10",
        "F19"
      ],
      "guidanceId": "optimize-image-priority",
      "status": "open"
    },
    {
      "id": "T09",
      "title": "Render a useful 404 recovery shell",
      "priority": 9,
      "findingIds": [
        "F16"
      ],
      "guidanceId": "persistent-toast-notifications",
      "status": "open"
    },
    {
      "id": "T10",
      "title": "Investigate bfcache eligibility and add restrained page transitions",
      "priority": 10,
      "findingIds": [
        "F02",
        "F11"
      ],
      "guidanceId": "cross-document-transitions",
      "status": "open"
    }
  ],
  "budget": {
    "pathCount": 7,
    "auditPasses": 1
  },
  "agent": "pi",
  "runId": "2026-07-20T21-09-41-013Z"
}
