Rule handbook metadata

Rule
DET.NAV.DEPTH · lane deterministic
Page status
current
page_version
bd3562025ebc5525d93f3f5d235936a70a33683cf2056afc850e561df77f8aee
generated_at
2026-05-25T18:00:00.000Z
registry_fingerprint
2ce40848effce579d3e4879f6ca85535183a14db201870a6c007da424624550c

How this rule is fixed

Pilot deterministic fixer: handbook_after · harness mode standalone · verify expect_rule_clean.

  • Harness: apply-harness-fixture-remediation.py copies the After example HTML from this handbook page onto the defect fixture, then invoke-det-ruleset-remediation-verify.sh re-audits and expects zero findings for this rule.
  • Production sites: run-website-ux-remediation-loop.sh runs handbook_html_patch (HTML patches in lib/ux-deterministic-fixers/fixers/patches/) before invoking the Cursor agent when the quality gate still fails.

Detection module: docs/design/ux-audit/deterministic-design-rules.md#det-nav-depth. Scroll down for Before / After examples and Evidence and remediation steps.

Purpose

Curated global navigation (Kpn, nav.fs-primary-nav-global; marketing landing-nav) must stay shallow so first-time visitors scan one horizon of site IA. Nested flyouts beyond top level + one tier force hover chains, obscure keyboard paths, and compete with handbook side rails (Ksr) that are designed for deep section trees.

This deterministic rule runs during the metrics phase. Playwright evaluates visible nav roots outside main matching:

  • nav.fs-primary-nav-global, [data-ks-hash="Kpn"]
  • nav.landing-nav, header.landing-header .landing-nav
  • header.site-header nav[aria-label*="Site navigation" i]

It measures list depth — nested ul, ol, or [role="menu"] tiers containing a[href] — and applies caps from det-nav-depth.check.js:

Pattern Max list depth
Standard global nav (no mega-menu marker) 2
Explicit mega-menu (.fs-mega-menu, .fs-mega-nav, [data-fs-mega-menu], etc.) 4

Excluded subtrees: theme preference dropdowns (.forge-theme-dropdown, .forge-theme-menu, [data-forge-pref]) — not primary IA.

Sidebar / offcanvas doc rails (aside.forge-sidebar, #ks-sidebar-aside, .fs-sidebar, Ksr) are not global-nav roots; deep handbook trees there are expected and do not satisfy this rule by themselves if the masthead still nests flyouts.

Plan: Audit global chrome selectors and list nesting before shipping HTML. Do: Keep Kpn / landing-nav to curated top-level links plus at most one fs-nav-dropdown or Bootstrap dropdown-menu tier; relocate handbook depth to Ksr or mobile Kco offcanvas. Check: navDepthReport.violations is empty and maxListDepth ≤ 2 (or ≤ 4 with mega-menu marker). Adjust: Flatten nested <ul> flyouts; adopt mega-menu contract only when columnar IA is intentional per Kpn.

Passing signals

  • Kpn (nav.fs-primary-nav-global) exposes flat primary links (Overview, Trust, Quickstart) with zero or one flyout tier via fs-nav-dropdown (data-fs-nav-dropdown, .fs-nav-dropdown__trigger, .fs-nav-dropdown__panel-inner) or a single .dropdown-menulist_depth ≤ 2.
  • landing-nav on landing_page / marketing_page uses horizontal .landing-nav-link anchors or one dropdown panel — no nested <ul> chains inside the global root.
  • Deep section IA lives in Ksr (aside.forge-sidebar, #ks-sidebar-aside, .fs-sidebar) or Kco offcanvas (#fsNav) — outside the global-nav depth budget.
  • When a mega-menu is justified, root includes .fs-mega-menu / [data-fs-mega-menu] and total list depth stays ≤ 4.
  • Theme / preference menus (.forge-theme-menu) do not inflate primary-nav depth metrics.
  • Evidence shape: nav_depth list_depth=2 max=2 mega=no kind=nested-flyout-depth absent; report shows maxListDepth within cap.

Failing signals

  • nested-flyout-depth — global nav nests <ul> inside <ul> inside <ul> (list depth 3+) without a mega-menu marker; common smell: full handbook tree copied into landing-nav or Kpn.
  • mega-depth-exceeded — mega-menu marker present but list depth > 4 (column stacks or recursive flyouts still too deep).
  • Nested flyouts in .site-header nav on showcase/handbook shells when Ksr already carries the same tree — often co-fails DET.NAV.DEDUP and DET.CONTEXT.BURDEN.
  • Keyboard/hover traps: third-tier links only reachable through chained :hover panels on fs-primary-nav-global.
  • Severity escalates to major when depth exceeds cap by more than one tier (list_depth > max + 1).
  • Evidence shape: nav_depth list_depth=4 max=2 mega=no kind=nested-flyout-depth hint="nav.landing-nav".

Before example

Before (failing example)

Global nav list_depth=4 — auditor flags nested-flyout-depth on nav.landing-nav.

Failing KS markup: landing-nav nests four list tiers (handbook-style tree in global chrome) — exceeds the primary-nav budget of 2 without a mega-menu pattern.

After example

After (passing example)

Global nav list_depth=2; deep IA in Ksr — passes DET.NAV.DEPTH.

Passing KS markup: shallow Kpn with one fs-nav-dropdown tier; deep handbook links live in Ksr sidebar (outside global-nav roots).

Evidence and remediation

Evidence: Playwright collectNavDepthReportmetrics.navDepthReport with navRootCount, maxListDepth, hasMegaMenu, and violations[] (kind, listDepth, maxAllowed, selectorHint). Findings cite nav_depth list_depth=N max=M mega=yes|no kind=nested-flyout-depth|mega-depth-exceeded hint="nav.fs-primary-nav-global".

Remediate (in order):

  1. Flatten masthead flyouts — remove nested <ul> chains from Kpn / landing-nav; keep at most one fs-nav-dropdown or .dropdown-menu tier per top-level item.
  2. Relocate handbook trees — move section links into Ksr (aside.forge-sidebar, .fs-sidebar) or Kco offcanvas; pair with Kbc breadcrumb for orientation (DET.NAV.BREADCRUMB).
  3. Adopt mega-menu deliberately — when columnar IA is required, add .fs-mega-menu / [data-fs-mega-menu] per Kpn contract and cap column depth at 4 list tiers; do not use mega-menu to hide uncurated link walls.
  4. De-duplicate bands — if the same deep tree appears in global nav and sidebar, remove the masthead copy (DET.NAV.DEDUP).
  5. Verify focus order — after flattening, re-check keyboard traversal through fs-nav-dropdown__trigger and panels (DET.NAV.FOCUS_ORDER).
  6. Re-run analyze-website-ux.mjs; for harness fixtures use auditor-tests/invoke-det-ruleset-harness.sh --only-rule DET.NAV.DEPTH.