;; ---------------------------------------------------------------------------
;; js.sx — Self-Hosting JavaScript Bootstrapper
;; ---------------------------------------------------------------------------

(defcomp ()
  (~docs/page :title "js.sx — JavaScript Bootstrapper"

    ;; -----------------------------------------------------------------------
    ;; Overview
    ;; -----------------------------------------------------------------------

    (~docs/section :title "Overview" :id "overview"
      (p (code "bootstrap_js.py") " is a 4,361-line Python program that reads the "
         (code ".sx") " spec files and emits " (code "sx-ref.js") " — the entire "
         "browser runtime. Parser, evaluator, three rendering adapters (HTML, SX wire, DOM), "
         "the engine (fetch/swap/trigger), orchestration, boot, signals, router, component "
         "dependency analysis — all transpiled from " (code ".sx") " spec files into JavaScript.")
      (p (code "js.sx") " replaces that Python program with an SX program. "
         "Like " (code "py.sx") " for Python, " (code "js.sx") " is an SX-to-JavaScript "
         "translator written in SX. But it goes further.")
      (p "Because the JS bootstrapper produces " (em "browser code") ", " (code "js.sx")
         " can also compile " (em "any") " SX component tree into a standalone JavaScript "
         "program. The server evaluates an " (code ".sx") " page definition, calls "
         (code "#js") " on the result, and gets a self-contained JS bundle that renders "
         "the same output in the browser — no SX runtime needed."))

    ;; -----------------------------------------------------------------------
    ;; Two Modes
    ;; -----------------------------------------------------------------------

    (~docs/section :title "Two Compilation Modes" :id "modes"

      (~docs/subsection :title "Mode 1: Spec Bootstrapper"
        (p "Same job as " (code "bootstrap_js.py") ". Read spec " (code ".sx") " files, "
           "emit " (code "sx-ref.js") ".")
        (~docs/code :src (highlight ";; Translate eval.sx to JavaScript
(js-translate-file (parse-file \"eval.sx\"))
;; → \"function evalExpr(expr, env) { ... }\"

;; Full bootstrap: all spec modules → sx-ref.js
(js-bootstrap
  :adapters (list \"html\" \"sx\" \"dom\" \"engine\" \"boot\")
  :modules (list \"deps\" \"router\" \"signals\"))" "lisp"))
        (p "The output is identical to " (code "python bootstrap_js.py") ". "
           "Verification: " (code "diff <(python bootstrap_js.py) <(python run_js_sx.py)") "."))

      (~docs/subsection :title "Mode 2: Component Compiler"
        (p "Server-side SX evaluation + " (code "js.sx") " translation = static JS output. "
           "Given a component tree that the server has already evaluated (data fetched, "
           "conditionals resolved, loops expanded), " (code "js.sx") " compiles the "
           "resulting DOM description into a JavaScript program that builds the same DOM.")
        (~docs/code :src (highlight ";; Server evaluates the page (fetches data, expands components)
;; Result is a resolved SX tree: (div :class \"...\" (h1 \"Hello\") ...)

;; js.sx compiles that tree to standalone JS
(js-compile-component evaluated-tree)
;; → \"(function(){
;;      var el = document.createElement('div');
;;      el.className = '...';
;;      var h1 = document.createElement('h1');
;;      h1.textContent = 'Hello';
;;      el.appendChild(h1);
;;      return el;
;;    })()\"" "lisp"))
        (p "This is ahead-of-time compilation. The browser receives JavaScript, "
           "not s-expressions. No parser, no evaluator, no runtime. "
           "Just DOM construction code.")))

    ;; -----------------------------------------------------------------------
    ;; Architecture
    ;; -----------------------------------------------------------------------

    (~docs/section :title "Architecture" :id "architecture"
      (p "The JS bootstrapper has more moving parts than the Python one because "
         "JavaScript is the " (em "client") " host. The browser runtime includes "
         "things Python never needs:")
      (div (~tw :tokens "overflow-x-auto rounded border border-stone-200 my-4")
        (table (~tw :tokens "w-full text-sm")
          (thead (~tw :tokens "bg-stone-50")
            (tr
              (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "Spec Module")
              (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "Purpose")
              (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "Python?")
              (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "Browser?")))
          (tbody
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2 font-mono") "eval.sx")
              (td (~tw :tokens "px-4 py-2") "Core evaluator, special forms, TCO")
              (td (~tw :tokens "px-4 py-2 text-center") "Yes") (td (~tw :tokens "px-4 py-2 text-center") "Yes"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2 font-mono") "render.sx")
              (td (~tw :tokens "px-4 py-2") "Tag registry, void elements, boolean attrs")
              (td (~tw :tokens "px-4 py-2 text-center") "Yes") (td (~tw :tokens "px-4 py-2 text-center") "Yes"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2 font-mono") "parser.sx")
              (td (~tw :tokens "px-4 py-2") "Tokenizer, parser, serializer")
              (td (~tw :tokens "px-4 py-2 text-center") "—") (td (~tw :tokens "px-4 py-2 text-center") "Yes"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2 font-mono") "adapter-html.sx")
              (td (~tw :tokens "px-4 py-2") "Render to HTML string")
              (td (~tw :tokens "px-4 py-2 text-center") "Yes") (td (~tw :tokens "px-4 py-2 text-center") "Yes"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2 font-mono") "adapter-sx.sx")
              (td (~tw :tokens "px-4 py-2") "Serialize to SX wire format")
              (td (~tw :tokens "px-4 py-2 text-center") "Yes") (td (~tw :tokens "px-4 py-2 text-center") "Yes"))
            (tr (~tw :tokens "border-t border-stone-100 bg-blue-50")
              (td (~tw :tokens "px-4 py-2 font-mono") "adapter-dom.sx")
              (td (~tw :tokens "px-4 py-2") "Render to live DOM nodes")
              (td (~tw :tokens "px-4 py-2 text-center") "—") (td (~tw :tokens "px-4 py-2 text-center") "Yes"))
            (tr (~tw :tokens "border-t border-stone-100 bg-blue-50")
              (td (~tw :tokens "px-4 py-2 font-mono") "engine.sx")
              (td (~tw :tokens "px-4 py-2") "Fetch, swap, trigger, history")
              (td (~tw :tokens "px-4 py-2 text-center") "—") (td (~tw :tokens "px-4 py-2 text-center") "Yes"))
            (tr (~tw :tokens "border-t border-stone-100 bg-blue-50")
              (td (~tw :tokens "px-4 py-2 font-mono") "orchestration.sx")
              (td (~tw :tokens "px-4 py-2") "Element scanning, attribute processing")
              (td (~tw :tokens "px-4 py-2 text-center") "—") (td (~tw :tokens "px-4 py-2 text-center") "Yes"))
            (tr (~tw :tokens "border-t border-stone-100 bg-blue-50")
              (td (~tw :tokens "px-4 py-2 font-mono") "boot.sx")
              (td (~tw :tokens "px-4 py-2") "Script processing, mount, hydration")
              (td (~tw :tokens "px-4 py-2 text-center") "—") (td (~tw :tokens "px-4 py-2 text-center") "Yes"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2 font-mono") "signals.sx")
              (td (~tw :tokens "px-4 py-2") "Reactive signal runtime")
              (td (~tw :tokens "px-4 py-2 text-center") "Yes") (td (~tw :tokens "px-4 py-2 text-center") "Yes"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2 font-mono") "deps.sx")
              (td (~tw :tokens "px-4 py-2") "Component dependency analysis")
              (td (~tw :tokens "px-4 py-2 text-center") "Yes") (td (~tw :tokens "px-4 py-2 text-center") "Yes"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2 font-mono") "router.sx")
              (td (~tw :tokens "px-4 py-2") "Client-side route matching")
              (td (~tw :tokens "px-4 py-2 text-center") "Yes") (td (~tw :tokens "px-4 py-2 text-center") "Yes")))))
      (p "Blue rows are browser-only modules. " (code "js.sx") " must handle all of them. "
         "The platform interface is also larger: DOM primitives (" (code "dom-create-element")
         ", " (code "dom-append") ", " (code "dom-set-attr") ", ...), "
         "browser APIs (" (code "fetch") ", " (code "history") ", " (code "localStorage")
         "), and event handling."))

    ;; -----------------------------------------------------------------------
    ;; Translation Rules
    ;; -----------------------------------------------------------------------

    (~docs/section :title "Translation Rules" :id "translation"
      (p (code "js.sx") " shares the same pattern as " (code "py.sx") " — expression translator, "
         "statement translator, name mangling — but with JavaScript-specific mappings:")

      (~docs/subsection :title "Name Mangling"
        (p "SX uses kebab-case. JavaScript uses camelCase.")
        (div (~tw :tokens "overflow-x-auto rounded border border-stone-200 my-4")
          (table (~tw :tokens "w-full text-sm")
            (thead (~tw :tokens "bg-stone-50")
              (tr
                (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "SX")
                (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "JavaScript")
                (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "Rule")))
            (tbody
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "eval-expr")
                (td (~tw :tokens "px-4 py-2 font-mono") "evalExpr")
                (td (~tw :tokens "px-4 py-2") "kebab → camelCase"))
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "nil?")
                (td (~tw :tokens "px-4 py-2 font-mono") "isNil")
                (td (~tw :tokens "px-4 py-2") "predicate → is-prefix"))
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "empty?")
                (td (~tw :tokens "px-4 py-2 font-mono") "isEmpty")
                (td (~tw :tokens "px-4 py-2") "? → is-prefix (general)"))
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "set!")
                (td (~tw :tokens "px-4 py-2 font-mono") "—")
                (td (~tw :tokens "px-4 py-2") "assignment (no rename)"))
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "dom-create-element")
                (td (~tw :tokens "px-4 py-2 font-mono") "domCreateElement")
                (td (~tw :tokens "px-4 py-2") "platform function rename"))
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "delete")
                (td (~tw :tokens "px-4 py-2 font-mono") "delete_")
                (td (~tw :tokens "px-4 py-2") "JS reserved word escape"))))))

      (~docs/subsection :title "Special Forms → JavaScript"
        (div (~tw :tokens "overflow-x-auto rounded border border-stone-200 my-4")
          (table (~tw :tokens "w-full text-sm")
            (thead (~tw :tokens "bg-stone-50")
              (tr
                (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "SX")
                (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "JavaScript")))
            (tbody
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "(if c t e)")
                (td (~tw :tokens "px-4 py-2 font-mono") "(sxTruthy(c) ? t : e)"))
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "(when c body)")
                (td (~tw :tokens "px-4 py-2 font-mono") "(sxTruthy(c) ? body : NIL)"))
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "(let ((a 1)) body)")
                (td (~tw :tokens "px-4 py-2 font-mono") "(function(a) { return body; })(1)"))
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "(fn (x) body)")
                (td (~tw :tokens "px-4 py-2 font-mono") "function(x) { return body; }"))
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "(define name val)")
                (td (~tw :tokens "px-4 py-2 font-mono") "var name = val;"))
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "(and a b c)")
                (td (~tw :tokens "px-4 py-2 font-mono") "(sxTruthy(a) ? (sxTruthy(b) ? c : b) : a)"))
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "(case x \"a\" 1 ...)")
                (td (~tw :tokens "px-4 py-2 font-mono") "sxCase(x, [[\"a\", () => 1], ...])"))
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "(str a b c)")
                (td (~tw :tokens "px-4 py-2 font-mono") "sxStr(a, b, c)"))
              (tr (~tw :tokens "border-t border-stone-100")
                (td (~tw :tokens "px-4 py-2 font-mono") "&rest args")
                (td (~tw :tokens "px-4 py-2 font-mono") "...args (rest params)"))))))

      (~docs/subsection :title "JavaScript Advantages"
        (p "JavaScript is easier to target than Python in two key ways:")
        (ul (~tw :tokens "list-disc pl-6 space-y-2 text-stone-700")
          (li (strong "No mutation problem. ")
              "JavaScript closures capture by reference, not by value. "
              (code "set!") " from a nested function Just Works — no cell variable "
              "hack needed. This eliminates the hardest part of " (code "py.sx") ".")
          (li (strong "Expression-oriented. ")
              "JavaScript's comma operator, ternary, and IIFEs make "
              "almost everything expressible as an expression. "
              "The statement/expression duality is less painful than Python."))))

    ;; -----------------------------------------------------------------------
    ;; Component Compilation
    ;; -----------------------------------------------------------------------

    (~docs/section :title "Component Compilation" :id "component-compiler"
      (p "Mode 2 is the interesting one. The server already evaluates SX page "
         "definitions — it fetches data, resolves conditionals, expands components, "
         "and produces a complete DOM description as an SX tree. Currently this tree "
         "is either:")
      (ul (~tw :tokens "list-disc pl-6 space-y-1 text-stone-700")
        (li "Rendered to HTML server-side (" (code "render-to-html") ")")
        (li "Serialized as SX wire format for the client to render (" (code "aser") ")"))
      (p "A third option: " (strong "compile it to JavaScript") ". "
         "The SX tree is already fully resolved — no data to fetch, no conditionals "
         "to evaluate. It's just a description of DOM nodes. " (code "js.sx")
         " walks this tree and emits imperative JavaScript that constructs the same DOM.")

      (~docs/subsection :title "What Gets Compiled"
        (p "A resolved SX tree like:")
        (~docs/code :src (highlight "(div :class \"container\"
  (h1 \"Hello\")
  (ul (map (fn (item)
    (li :class \"item\" (get item \"name\")))
    items)))" "lisp"))
        (p "After server-side evaluation (with " (code "items") " = "
           (code "[{\"name\": \"Alice\"}, {\"name\": \"Bob\"}]") "):")
        (~docs/code :src (highlight "(div :class \"container\"
  (h1 \"Hello\")
  (ul
    (li :class \"item\" \"Alice\")
    (li :class \"item\" \"Bob\")))" "lisp"))
        (p "Compiles to:")
        (~docs/code :src (highlight "var _0 = document.createElement('div');
_0.className = 'container';
var _1 = document.createElement('h1');
_1.textContent = 'Hello';
_0.appendChild(_1);
var _2 = document.createElement('ul');
var _3 = document.createElement('li');
_3.className = 'item';
_3.textContent = 'Alice';
_2.appendChild(_3);
var _4 = document.createElement('li');
_4.className = 'item';
_4.textContent = 'Bob';
_2.appendChild(_4);
_0.appendChild(_2);" "javascript")))

      (~docs/subsection :title "Why Not Just Use HTML?"
        (p "HTML already does this — " (code "innerHTML") " parses and builds DOM. "
           "Why compile to JS instead?")
        (ul (~tw :tokens "list-disc pl-6 space-y-2 text-stone-700")
          (li (strong "Event handlers. ")
              "HTML can't express " (code ":on-click") " or " (code ":sx-get")
              " — those need JavaScript. The compiled JS can wire up event "
              "listeners inline during construction.")
          (li (strong "Reactive islands. ")
              "Signal bindings (" (code "deref") "), reactive text nodes, and "
              "reactive attributes need to register subscriptions during construction. "
              "Compiled JS can create signals and wire subscriptions as it builds the DOM.")
          (li (strong "No parse overhead. ")
              "The browser doesn't need to parse HTML or SX source. "
              "The JavaScript engine JIT-compiles the DOM construction code. "
              "For large pages, this can be faster than " (code "innerHTML") ".")
          (li (strong "Tree-shakeable. ")
              "The compiled output only contains what the page uses. "
              "No SX parser, no evaluator, no rendering runtime. "
              "A static page compiles to pure DOM API calls — zero framework overhead.")
          (li (strong "Portable. ")
              "The output is a JavaScript module. It works in any JS environment: "
              "browser, Node, Deno, Bun. Server-side rendered pages become "
              "testable JavaScript programs.")))

      (~docs/subsection :title "Hybrid Mode"
        (p "Not every page is fully static. Some parts are server-rendered, "
           "some are interactive. " (code "js.sx") " handles this with a hybrid approach:")
        (ul (~tw :tokens "list-disc pl-6 space-y-2 text-stone-700")
          (li (strong "Static subtrees") " → compiled to DOM construction code (no runtime)")
          (li (strong "Reactive islands") " → compiled with signal creation + subscriptions "
              "(needs signal runtime, ~2KB)")
          (li (strong "Hypermedia attributes") " (" (code "sx-get") ", " (code "sx-post")
              ") → compiled with event listeners + fetch calls "
              "(needs engine, ~5KB)")
          (li (strong "Client-routed pages") " → full SX runtime included"))
        (p "The compiler analyzes the tree and includes only the runtime slices needed. "
           "A purely static page ships zero SX runtime. "
           "A page with one reactive counter ships just the signal runtime.")))

    ;; -----------------------------------------------------------------------
    ;; The Bootstrap Chain
    ;; -----------------------------------------------------------------------

    (~docs/section :title "The Bootstrap Chain" :id "chain"
      (p "With both " (code "py.sx") " and " (code "js.sx") ", the full picture:")
      (div (~tw :tokens "overflow-x-auto rounded border border-stone-200 my-4")
        (table (~tw :tokens "w-full text-sm")
          (thead (~tw :tokens "bg-stone-50")
            (tr
              (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "Translator")
              (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "Written in")
              (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "Outputs")
              (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "Replaces")))
          (tbody
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2 font-mono") "z3.sx")
              (td (~tw :tokens "px-4 py-2") "SX")
              (td (~tw :tokens "px-4 py-2") "SMT-LIB")
              (td (~tw :tokens "px-4 py-2 text-stone-400 italic") "(none — new capability)"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2 font-mono") "prove.sx")
              (td (~tw :tokens "px-4 py-2") "SX")
              (td (~tw :tokens "px-4 py-2") "Constraint proofs")
              (td (~tw :tokens "px-4 py-2 text-stone-400 italic") "(none — new capability)"))
            (tr (~tw :tokens "border-t border-stone-100 bg-violet-50")
              (td (~tw :tokens "px-4 py-2 font-mono text-violet-700") "py.sx")
              (td (~tw :tokens "px-4 py-2") "SX")
              (td (~tw :tokens "px-4 py-2") "Python")
              (td (~tw :tokens "px-4 py-2 font-mono") "bootstrap_py.py"))
            (tr (~tw :tokens "border-t border-stone-100 bg-blue-50")
              (td (~tw :tokens "px-4 py-2 font-mono text-blue-700") "js.sx")
              (td (~tw :tokens "px-4 py-2") "SX")
              (td (~tw :tokens "px-4 py-2") "JavaScript")
              (td (~tw :tokens "px-4 py-2 font-mono") "bootstrap_js.py"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2 font-mono text-stone-400") "go.sx")
              (td (~tw :tokens "px-4 py-2") "SX")
              (td (~tw :tokens "px-4 py-2") "Go")
              (td (~tw :tokens "px-4 py-2 text-stone-400 italic") "(future host)"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2 font-mono text-stone-400") "rs.sx")
              (td (~tw :tokens "px-4 py-2") "SX")
              (td (~tw :tokens "px-4 py-2") "Rust")
              (td (~tw :tokens "px-4 py-2 text-stone-400 italic") "(future host)")))))
      (p "Every translator is an SX program. The only Python left is the platform "
         "interface (types, DOM primitives, runtime support functions) and the thin "
         "runner script that loads " (code "py.sx") " or " (code "js.sx")
         " and feeds it the spec files."))

    ;; -----------------------------------------------------------------------
    ;; Implementation Plan
    ;; -----------------------------------------------------------------------

    (~docs/section :title "Implementation" :id "implementation"

      (~docs/subsection :title "Phase 1: Expression Translator"
        (p "Core SX-to-JavaScript expression translation.")
        (ul (~tw :tokens "list-disc pl-6 space-y-1 text-stone-700")
          (li (code "js-mangle") " — SX name → JavaScript identifier (RENAMES + kebab→camelCase)")
          (li (code "js-literal") " — atoms: numbers, strings, booleans, nil, symbols, keywords")
          (li (code "js-expr") " — recursive expression translator")
          (li "Ternary: " (code "if") ", " (code "when") ", " (code "cond") ", " (code "and") ", " (code "or"))
          (li (code "let") " → IIFE: " (code "(function(a) { return body; })(val)"))
          (li (code "fn") " → " (code "function(x) { return body; }"))
          (li (code "str") " → " (code "sxStr(...)"))
          (li "Infix: " (code "+") ", " (code "-") ", " (code "*") ", " (code "/") ", "
              (code "===") ", " (code "!==") ", " (code "%"))
          (li (code "&rest") " → " (code "...args") " (rest parameters)")))

      (~docs/subsection :title "Phase 2: Statement Translator"
        (p "Top-level and function body statement emission.")
        (ul (~tw :tokens "list-disc pl-6 space-y-1 text-stone-700")
          (li (code "js-statement") " — emit as JavaScript statement")
          (li (code "define") " → " (code "var name = expr;"))
          (li (code "set!") " → direct assignment (closures capture by reference)")
          (li (code "for-each") " → " (code "for (var i = 0; i < arr.length; i++)") " loop")
          (li (code "do") "/" (code "begin") " → comma expression or block")
          (li "Function bodies with multiple expressions → explicit " (code "return"))))

      (~docs/subsection :title "Phase 3: Spec Bootstrapper"
        (p "Process spec files identically to " (code "bootstrap_js.py") ".")
        (ul (~tw :tokens "list-disc pl-6 space-y-1 text-stone-700")
          (li (code "js-extract-defines") " — parse .sx source, collect top-level defines")
          (li (code "js-translate-file") " — translate a list of define expressions")
          (li "Adapter selection: parser, html, sx, dom, engine, orchestration, boot")
          (li "Dependency resolution: engine requires dom, boot requires engine + parser")
          (li "Static sections (IIFE wrapper, platform interface) stay as string templates")))

      (~docs/subsection :title "Phase 4: Component Compiler"
        (p "Ahead-of-time compilation of evaluated SX trees to JavaScript.")
        (ul (~tw :tokens "list-disc pl-6 space-y-1 text-stone-700")
          (li (code "js-compile-element") " — emit " (code "createElement") " + attribute setting")
          (li (code "js-compile-text") " — emit " (code "textContent") " or " (code "createTextNode"))
          (li (code "js-compile-component") " — inline-expand or emit component call")
          (li (code "js-compile-island") " — emit signal creation + reactive DOM subscriptions")
          (li (code "js-compile-fragment") " — emit " (code "DocumentFragment") " construction")
          (li "Runtime slicing: analyze tree → include only necessary runtime modules")))

      (~docs/subsection :title "Phase 5: Verification"
        (~docs/code :src (highlight "# Mode 1: spec bootstrapper parity
python bootstrap_js.py > sx-ref-g0.js
python run_js_sx.py > sx-ref-g1.js
diff sx-ref-g0.js sx-ref-g1.js  # must be empty

# Mode 2: component compilation correctness
# Server renders page → SX tree → compile to JS
# Compare DOM output: runtime-rendered vs compiled
python test_js_compile.py  # renders both, diffs DOM" "bash")))

    ;; -----------------------------------------------------------------------
    ;; Comparison with py.sx
    ;; -----------------------------------------------------------------------

    (~docs/section :title "Comparison with py.sx" :id "comparison"
      (div (~tw :tokens "overflow-x-auto rounded border border-stone-200 my-4")
        (table (~tw :tokens "w-full text-sm")
          (thead (~tw :tokens "bg-stone-50")
            (tr
              (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") "Concern")
              (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") (code "py.sx"))
              (th (~tw :tokens "px-4 py-2 text-left font-semibold text-stone-700") (code "js.sx"))))
          (tbody
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2") "Naming convention")
              (td (~tw :tokens "px-4 py-2") "snake_case")
              (td (~tw :tokens "px-4 py-2") "camelCase"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2") "Closures & mutation")
              (td (~tw :tokens "px-4 py-2") "Cell variable hack")
              (td (~tw :tokens "px-4 py-2") "Direct (reference capture)"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2") "Spec modules")
              (td (~tw :tokens "px-4 py-2") "eval, render, html, sx, deps, signals")
              (td (~tw :tokens "px-4 py-2") "All 12 modules"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2") "Platform interface")
              (td (~tw :tokens "px-4 py-2") "~300 lines")
              (td (~tw :tokens "px-4 py-2") "~1500 lines (DOM, browser APIs)"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2") "RENAMES table")
              (td (~tw :tokens "px-4 py-2") "~200 entries")
              (td (~tw :tokens "px-4 py-2") "~350 entries"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2") "Component compilation")
              (td (~tw :tokens "px-4 py-2 text-stone-400") "N/A")
              (td (~tw :tokens "px-4 py-2") "Ahead-of-time DOM compiler"))
            (tr (~tw :tokens "border-t border-stone-100")
              (td (~tw :tokens "px-4 py-2") "Estimated size")
              (td (~tw :tokens "px-4 py-2") "~800-1000 lines")
              (td (~tw :tokens "px-4 py-2") "~1200-1500 lines"))))))

    ;; -----------------------------------------------------------------------
    ;; Implications
    ;; -----------------------------------------------------------------------

    (~docs/section :title "Implications" :id "implications"
      (~docs/subsection :title "Zero-Runtime Static Sites"
        (p "A static page written in SX compiles to a JavaScript program with "
           "no SX runtime dependency. The output is just DOM API calls — "
           (code "createElement") ", " (code "appendChild") ", " (code "textContent")
           ". This gives SX a compilation target competitive with Svelte's "
           "approach: components compile away, the framework disappears.")
        (p "Combined with the " (a :href "/sx/(etc.(plan.content-addressed-components))" "content-addressed components")
           " plan, a page's compiled JS could be stored on IPFS by its content hash. "
           "The server returns a CID. The browser fetches and executes pre-compiled JavaScript. "
           "No parser, no evaluator, no network round-trip for component definitions."))

      (~docs/subsection :title "Progressive Enhancement Layers"
        (p "The component compiler naturally supports progressive enhancement:")
        (ol (~tw :tokens "list-decimal pl-6 space-y-1 text-stone-700")
          (li (strong "HTML") " — server renders to HTML string. No JS needed. Works everywhere.")
          (li (strong "Compiled JS") " — server compiles to DOM construction code. "
              "Event handlers work. No SX runtime. Kilobytes, not megabytes.")
          (li (strong "SX runtime") " — full evaluator + engine. Client-side routing, "
              "component caching, reactive islands. The current architecture.")
          (li (strong "SX + signals") " — full reactive islands. Fine-grained DOM updates."))
        (p "Each layer adds capability and weight. The right layer depends on the page. "
           "A blog post needs layer 1. An interactive form needs layer 2. "
           "A single-page app needs layer 3. A real-time dashboard needs layer 4. "
           (code "js.sx") " makes layer 2 possible — it didn't exist before."))

      (~docs/subsection :title "The Bootstrap Completion"
        (p "With " (code "py.sx") " and " (code "js.sx") " both written in SX:")
        (ul (~tw :tokens "list-disc pl-6 space-y-2 text-stone-700")
          (li "The " (em "spec") " defines SX semantics (" (code "eval.sx") ", " (code "render.sx") ", ...)")
          (li "The " (em "translators") " convert the spec to host languages (" (code "py.sx") ", " (code "js.sx") ")")
          (li "The " (em "prover") " verifies the spec's properties (" (code "z3.sx") ", " (code "prove.sx") ")")
          (li "All four are written " (em "in") " SX, executable " (em "by") " any SX evaluator"))
        (p "The language defines itself, verifies itself, and compiles itself. "
           "The Python and JavaScript \"bootstrappers\" are not programs that produce SX — "
           "they are SX programs that produce Python and JavaScript. "
           "The arrow points the other way."))))))
