(define
  find-current
  (fn
    (items slug)
    (when
      slug
      (some
        (fn
          (item)
          (when
            (ends-with? (get item "href") (str "." slug "))"))
            (get item "label")))
        items))))

(defcomp
  ~nav-data/section-nav
  (&key items current)
  (<>
    (map
      (fn
        (item)
        (~shared:layout/nav-link
          :href (get item "href")
          :label (get item "label")
          :is-selected (when (= (get item "label") current) "true")
          :select-colours "aria-selected:bg-violet-200 aria-selected:text-violet-900"))
      items)))

(define
  sx-nav-tree
  (dict
    :href "/sx/"
    :label "sx"
    :children (list
      (dict
        :href "/sx/(geography)"
        :label "Geography"
        :children (list
          (dict
            :href "/sx/(geography.(reactive))"
            :label "Reactive Islands"
            :children reactive-islands-nav-items)
          (dict
            :href "/sx/(geography.(hypermedia))"
            :label "Hypermedia Lakes"
            :children (list
              (dict
                :href "/sx/(geography.(hypermedia.(reference)))"
                :label "Reference"
                :children reference-nav-items)
              (dict
                :href "/sx/(geography.(hypermedia.(example)))"
                :label "Examples"
                :children examples-nav-items)))
          (dict
            :href "/sx/(geography.(scopes))"
            :label "Scopes"
            :summary "The unified primitive beneath provide, collect!, spreads, and islands. Named scope with downward value, upward accumulation, and a dedup flag.")
          (dict
            :href "/sx/(geography.(provide))"
            :label "Provide / Emit!"
            :summary "Sugar for scope-with-value. Render-time dynamic scope — the substrate beneath spreads, CSSX, and script collection.")
          (dict
            :href "/sx/(geography.(spreads))"
            :label "Spreads"
            :summary "Child-to-parent communication across render boundaries — spread, collect!, reactive-spread, built on scopes.")
          (dict
            :href "/sx/(geography.(marshes))"
            :label "Marshes"
            :children marshes-examples-nav-items
            :summary "Where reactivity and hypermedia interpenetrate — server writes to signals, reactive transforms reshape server content, client state modifies how hypermedia is interpreted.")
          (dict
            :href "/sx/(geography.(isomorphism))"
            :label "Isomorphism"
            :children isomorphism-nav-items)
          (dict
            :href "/sx/(geography.(cek))"
            :label "CEK Machine"
            :children cek-nav-items)
          (dict :href "/sx/(geography.(capabilities))" :label "Capabilities")
          (dict
            :href "/sx/(geography.(reactive-runtime))"
            :label "Reactive Runtime"
            :children reactive-runtime-nav-items)))
      (dict
        :href "/sx/(language)"
        :label "Language"
        :children (list
          (dict
            :href "/sx/(language.(doc))"
            :label "Docs"
            :children docs-nav-items)
          (dict
            :href "/sx/(language.(spec))"
            :label "Specs"
            :children specs-nav-items)
          (dict
            :href "/sx/(language.(spec.(explore.evaluator)))"
            :label "Spec Explorer")
          (dict
            :href "/sx/(language.(bootstrapper))"
            :label "Bootstrappers"
            :children bootstrappers-nav-items)
          (dict
            :href "/sx/(language.(test))"
            :label "Testing"
            :children testing-nav-items)))
      (dict
        :href "/sx/(applications)"
        :label "Applications"
        :children (list
          (dict :href "/sx/(applications.(sx-urls))" :label "SX URLs")
          (dict
            :href "/sx/(applications.(cssx))"
            :label "CSSX"
            :children cssx-nav-items)
          (dict
            :href "/sx/(applications.(protocol))"
            :label "Protocols"
            :children protocols-nav-items)
          (dict :href "/sx/(applications.(sx-pub))" :label "sx-pub")
          (dict
            :href "/sx/(applications.(native-browser))"
            :label "Native Browser")
          (dict :href "/sx/(applications.(sxtp))" :label "SXTP Protocol")
          (dict :href "/sx/(applications.(pretext))" :label "Pretext")
          (dict
            :href "/sx/(applications.(htmx))"
            :label "htmx"
            :children htmx-nav-items)
          (dict
            :href "/sx/(applications.(hyperscript))"
            :label "_hyperscript"
            :children hyperscript-nav-items)))
      (dict :href "/sx/(tools)" :label "Tools" :children tools-nav-items)
      (dict
        :href "/sx/(etc)"
        :label "Etc"
        :children (list
          (dict
            :href "/sx/(etc.(essay))"
            :label "Essays"
            :children essays-nav-items)
          (dict
            :href "/sx/(etc.(philosophy))"
            :label "Philosophy"
            :children philosophy-nav-items)
          (dict
            :href "/sx/(etc.(plan))"
            :label "Plans"
            :children plans-nav-items))))))

(define
  has-descendant-href?
  (fn
    (node path)
    (let
      ((children (get node "children")))
      (when
        children
        (some
          (fn
            (child)
            (or
              (= (get child "href") path)
              (has-descendant-href? child path)))
          children)))))

(define
  find-nav-match
  (fn
    (items path)
    (or
      (some (fn (item) (when (= (get item "href") path) item)) items)
      (some (fn (item) (when (has-descendant-href? item path) item)) items))))

(define
  resolve-nav-path
  (fn
    (tree path)
    (let
      ((trail (list)))
      (define
        walk
        (fn
          (node)
          (let
            ((children (get node "children")))
            (when
              children
              (let
                ((match (find-nav-match children path)))
                (when
                  match
                  (append! trail {:siblings children :node match})
                  (when (not (= (get match "href") path)) (walk match))))))))
      (walk tree)
      (let
        ((depth (len trail)))
        (if
          (= depth 0)
          {:children (get tree "children") :depth 0 :trail trail}
          (let ((deepest (nth trail (- depth 1)))) {:children (get (get deepest "node") "children") :depth depth :trail trail}))))))

(define
  find-nav-index
  (fn
    (items node)
    (let
      ((target-href (get node "href")) (count (len items)))
      (define
        find-loop
        (fn
          (i)
          (if
            (>= i count)
            0
            (if
              (= (get (nth items i) "href") target-href)
              i
              (find-loop (+ i 1))))))
      (find-loop 0))))
