;; Spec viewer components — display canonical SX specification source

;; ---------------------------------------------------------------------------
;; Architecture intro page
;; ---------------------------------------------------------------------------

(defcomp ~spec-architecture-content ()
  (~doc-page :title "Spec Architecture"
    (div :class "space-y-8"

      (div :class "space-y-4"
        (p :class "text-lg text-stone-600"
          "SX is defined in SX. The canonical specification is a set of s-expression files that are both documentation and executable definition. Bootstrap compilers read these files to generate native implementations in JavaScript, Python, Rust, or any other target.")
        (p :class "text-stone-600"
          "The spec is split into two layers: a "
          (strong "core") " that defines the language itself, and "
          (strong "adapters") " that connect it to specific environments."))

      (div :class "space-y-3"
        (h2 :class "text-2xl font-semibold text-stone-800" "Core")
        (p :class "text-stone-600"
          "The core is platform-independent. It defines how SX source is parsed, how expressions are evaluated, what primitives exist, and what shared rendering definitions all adapters use. These four files are the language.")
        (div :class "overflow-x-auto rounded border border-stone-200"
          (table :class "w-full text-left text-sm"
            (thead (tr :class "border-b border-stone-200 bg-stone-100"
              (th :class "px-3 py-2 font-medium text-stone-600" "File")
              (th :class "px-3 py-2 font-medium text-stone-600" "Role")))
            (tbody
              (tr :class "border-b border-stone-100"
                (td :class "px-3 py-2 font-mono text-sm text-violet-700"
                  (a :href "/specs/parser" :class "hover:underline"
                     :sx-get "/specs/parser" :sx-target "#main-panel" :sx-select "#main-panel"
                     :sx-swap "outerHTML" :sx-push-url "true"
                     "parser.sx"))
                (td :class "px-3 py-2 text-stone-700" "Tokenization and parsing of SX source text into AST"))
              (tr :class "border-b border-stone-100"
                (td :class "px-3 py-2 font-mono text-sm text-violet-700"
                  (a :href "/specs/evaluator" :class "hover:underline"
                     :sx-get "/specs/evaluator" :sx-target "#main-panel" :sx-select "#main-panel"
                     :sx-swap "outerHTML" :sx-push-url "true"
                     "eval.sx"))
                (td :class "px-3 py-2 text-stone-700" "Tree-walking evaluation of SX expressions"))
              (tr :class "border-b border-stone-100"
                (td :class "px-3 py-2 font-mono text-sm text-violet-700"
                  (a :href "/specs/primitives" :class "hover:underline"
                     :sx-get "/specs/primitives" :sx-target "#main-panel" :sx-select "#main-panel"
                     :sx-swap "outerHTML" :sx-push-url "true"
                     "primitives.sx"))
                (td :class "px-3 py-2 text-stone-700" "All built-in pure functions and their signatures"))
              (tr :class "border-b border-stone-100"
                (td :class "px-3 py-2 font-mono text-sm text-violet-700"
                  (a :href "/specs/renderer" :class "hover:underline"
                     :sx-get "/specs/renderer" :sx-target "#main-panel" :sx-select "#main-panel"
                     :sx-swap "outerHTML" :sx-push-url "true"
                     "render.sx"))
                (td :class "px-3 py-2 text-stone-700" "Shared rendering registries and utilities used by all adapters"))))))

      (div :class "space-y-3"
        (h2 :class "text-2xl font-semibold text-stone-800" "Adapters")
        (p :class "text-stone-600"
          "Adapters are selectable rendering backends. Each one takes the same evaluated expression tree and produces output for a specific environment. You only need the adapters relevant to your target.")
        (div :class "overflow-x-auto rounded border border-stone-200"
          (table :class "w-full text-left text-sm"
            (thead (tr :class "border-b border-stone-200 bg-stone-100"
              (th :class "px-3 py-2 font-medium text-stone-600" "File")
              (th :class "px-3 py-2 font-medium text-stone-600" "Output")
              (th :class "px-3 py-2 font-medium text-stone-600" "Environment")))
            (tbody
              (tr :class "border-b border-stone-100"
                (td :class "px-3 py-2 font-mono text-sm text-violet-700"
                  (a :href "/specs/adapter-dom" :class "hover:underline"
                     :sx-get "/specs/adapter-dom" :sx-target "#main-panel" :sx-select "#main-panel"
                     :sx-swap "outerHTML" :sx-push-url "true"
                     "adapter-dom.sx"))
                (td :class "px-3 py-2 text-stone-700" "Live DOM nodes")
                (td :class "px-3 py-2 text-stone-500" "Browser"))
              (tr :class "border-b border-stone-100"
                (td :class "px-3 py-2 font-mono text-sm text-violet-700"
                  (a :href "/specs/adapter-html" :class "hover:underline"
                     :sx-get "/specs/adapter-html" :sx-target "#main-panel" :sx-select "#main-panel"
                     :sx-swap "outerHTML" :sx-push-url "true"
                     "adapter-html.sx"))
                (td :class "px-3 py-2 text-stone-700" "HTML strings")
                (td :class "px-3 py-2 text-stone-500" "Server"))
              (tr :class "border-b border-stone-100"
                (td :class "px-3 py-2 font-mono text-sm text-violet-700"
                  (a :href "/specs/adapter-sx" :class "hover:underline"
                     :sx-get "/specs/adapter-sx" :sx-target "#main-panel" :sx-select "#main-panel"
                     :sx-swap "outerHTML" :sx-push-url "true"
                     "adapter-sx.sx"))
                (td :class "px-3 py-2 text-stone-700" "SX wire format")
                (td :class "px-3 py-2 text-stone-500" "Server to client"))))))

      (div :class "space-y-3"
        (h2 :class "text-2xl font-semibold text-stone-800" "Engine")
        (p :class "text-stone-600"
          "The engine is the browser-side fetch/swap/history system. It processes "
          (code :class "text-violet-700 text-sm" "sx-*")
          " attributes on elements to make HTTP requests, swap content, manage browser history, and handle events. It depends on the core evaluator and the DOM adapter.")
        (div :class "overflow-x-auto rounded border border-stone-200"
          (table :class "w-full text-left text-sm"
            (thead (tr :class "border-b border-stone-200 bg-stone-100"
              (th :class "px-3 py-2 font-medium text-stone-600" "File")
              (th :class "px-3 py-2 font-medium text-stone-600" "Role")))
            (tbody
              (tr :class "border-b border-stone-100"
                (td :class "px-3 py-2 font-mono text-sm text-violet-700"
                  (a :href "/specs/engine" :class "hover:underline"
                     :sx-get "/specs/engine" :sx-target "#main-panel" :sx-select "#main-panel"
                     :sx-swap "outerHTML" :sx-push-url "true"
                     "engine.sx"))
                (td :class "px-3 py-2 text-stone-700" "SxEngine — fetch, swap, history, SSE, triggers, indicators"))))))

      (div :class "space-y-3"
        (h2 :class "text-2xl font-semibold text-stone-800" "Dependency graph")
        (div :class "bg-stone-100 rounded-lg p-5 mx-auto max-w-3xl"
          (pre :class "text-sm leading-relaxed whitespace-pre-wrap break-words font-mono text-stone-700"
"parser.sx          (standalone — no dependencies)
primitives.sx       (standalone — declarative registry)
eval.sx             depends on: parser, primitives
render.sx           (standalone — shared registries)

adapter-dom.sx      depends on: render, eval
adapter-html.sx     depends on: render, eval
adapter-sx.sx       depends on: render, eval

engine.sx           depends on: eval, adapter-dom")))

      (div :class "space-y-3"
        (h2 :class "text-2xl font-semibold text-stone-800" "Self-hosting")
        (p :class "text-stone-600"
          "Every spec file is written in the same restricted subset of SX that the evaluator itself defines. A bootstrap compiler for a new target only needs to understand this subset — roughly 20 special forms and 80 primitives — to generate a fully native implementation. The spec files are the single source of truth; implementations are derived artifacts.")
        (p :class "text-stone-600"
          "This is not a theoretical exercise. The JavaScript implementation ("
          (code :class "text-violet-700 text-sm" "sx.js")
          ") and the Python implementation ("
          (code :class "text-violet-700 text-sm" "shared/sx/")
          ") are both generated from these spec files via "
          (code :class "text-violet-700 text-sm" "bootstrap_js.py")
          " and its Python counterpart.")))))

;; ---------------------------------------------------------------------------
;; Overview pages (Core / Adapters) — show truncated previews of each file
;; ---------------------------------------------------------------------------

(defcomp ~spec-overview-content (&key spec-files)
  (~doc-page :title (or spec-title "Specs")
    (p :class "text-stone-600 mb-6"
      (case spec-title
        "Core Language"
          "The core specification defines the language itself — parsing, evaluation, primitives, and shared rendering definitions. These four files are platform-independent and sufficient to implement SX on any target."
        "Adapters & Engine"
          "Adapters connect the core language to specific environments. Each adapter takes evaluated expression trees and produces output for its target. The engine adds browser-side fetch/swap behaviour."
        :else ""))
    (div :class "space-y-8"
      (map (fn (spec)
        (div :class "space-y-3"
          (div :class "flex items-baseline gap-3"
            (h2 :class "text-2xl font-semibold text-stone-800"
              (a :href (get spec "href")
                 :sx-get (get spec "href") :sx-target "#main-panel" :sx-select "#main-panel"
                 :sx-swap "outerHTML" :sx-push-url "true"
                 :class "text-violet-700 hover:text-violet-900 underline"
                 (get spec "title")))
            (span :class "text-sm text-stone-400 font-mono" (get spec "filename")))
          (p :class "text-stone-600" (get spec "desc"))
          (div :class "bg-stone-100 rounded-lg p-5 max-h-72 overflow-y-auto"
            (pre :class "text-xs leading-relaxed whitespace-pre-wrap break-words"
              (code (highlight (get spec "source") "sx"))))))
        spec-files))))

;; ---------------------------------------------------------------------------
;; Detail page — full source of a single spec file
;; ---------------------------------------------------------------------------

(defcomp ~spec-detail-content (&key spec-title spec-desc spec-filename spec-source)
  (~doc-page :title spec-title
    (div :class "flex items-baseline gap-3 mb-4"
      (span :class "text-sm text-stone-400 font-mono" spec-filename)
      (span :class "text-sm text-stone-500" spec-desc))
    (div :class "bg-stone-100 rounded-lg p-5 mx-auto max-w-3xl"
      (pre :class "text-sm leading-relaxed whitespace-pre-wrap break-words"
        (code (highlight spec-source "sx"))))))

;; ---------------------------------------------------------------------------
;; Not found
;; ---------------------------------------------------------------------------

(defcomp ~spec-not-found (&key slug)
  (~doc-page :title "Spec Not Found"
    (p :class "text-stone-600"
      "No specification found for \"" slug "\". This spec may not exist yet.")))
