;; ---------------------------------------------------------------------------
;; CSS Delivery
;; ---------------------------------------------------------------------------
(defcomp ()
  (~docs/page :title "CSS Delivery"

    (~docs/section :title "Multiple Strategies" :id "strategies"
      (p "A CSSX component chooses its own styling strategy — and each strategy has its "
         "own delivery path:")
      (ul (~tw :tokens "list-disc pl-5 space-y-1 text-stone-700")
        (li (strong "Tailwind classes: ") "Delivered via the on-demand protocol below. "
            "The server ships only the rules the page actually uses.")
        (li (strong "Inline styles: ") "No delivery needed — " (code ":style") " attributes "
            "are part of the markup.")
        (li (strong "Emitted " (code "<style>") " blocks: ") "Components can emit CSS rules "
            "directly. They arrive as part of the rendered HTML — keyframes, custom properties, "
            "scoped rules, anything.")
        (li (strong "External stylesheets: ") "Components can reference pre-loaded CSS files "
            "or lazy-load them via " (code "~shared:pages/suspense") " (see " (a :href "/sx/(applications.(cssx.async))" "Async CSS") ").")
        (li (strong "Custom properties: ") "A " (code "~cssx/theme") " component sets "
            (code "--color-primary") " etc. via a " (code "<style>") " block. Everything "
            "using " (code "var()") " repaints automatically."))
      (p "The protocol below handles the Tailwind utility class case — the most common "
         "strategy — but it's not the only game in town."))

    (~docs/section :title "On-Demand Tailwind Delivery" :id "on-demand"
      (p "When components use Tailwind utility classes, SX ships " (em "only the CSS rules "
         "actually used on the page") ", computed at render time. No build step, no purging, "
         "no unused CSS.")
      (p "The server pre-parses the full Tailwind CSS file into an in-memory registry at "
         "startup. When a response is rendered, SX scans all " (code ":class") " values in "
         "the output, looks up only those classes, and embeds the matching rules."))

    (~docs/section :title "The Protocol" :id "protocol"
      (p "First page load gets the full set of used rules. Subsequent navigations send a "
         "hash of what the client already has, and the server ships only the delta:")
      (highlight
        "# First page load:\nGET / HTTP/1.1\n\nHTTP/1.1 200 OK\nContent-Type: text/html\n# Full CSS in <style id=\"sx-css\"> + hash in <meta name=\"sx-css-classes\">\n\n# Subsequent navigation:\nGET /about HTTP/1.1\nSX-Css: a1b2c3d4\n\nHTTP/1.1 200 OK\nContent-Type: text/sx\nSX-Css-Hash: e5f6g7h8\nSX-Css-Add: bg-blue-500,text-white,rounded-lg\n# Only new rules in <style data-sx-css>"
        "bash")
      (p "The client merges new rules into the existing " (code "<style id=\"sx-css\">")
         " block and updates its hash. No flicker, no duplicate rules."))

    (~docs/section :title "Component-Aware Scanning" :id "scanning"
      (p "CSS scanning happens at two levels:")
      (ul (~tw :tokens "list-disc pl-5 space-y-1 text-stone-700")
        (li (strong "Registration time: ") "When a component is defined via " (code "defcomp")
            ", its body is scanned for class strings. The component records which CSS classes "
            "it uses.")
        (li (strong "Render time: ") "The rendered output is scanned for any classes the "
            "static scan missed — dynamically constructed class strings, conditional classes, etc."))
      (p "This means the CSS registry knows roughly what a page needs before rendering, "
         "and catches any stragglers after."))

    (~docs/section :title "Trade-offs" :id "tradeoffs"
      (ul (~tw :tokens "list-disc pl-5 space-y-2 text-stone-700")
        (li (strong "Full Tailwind in memory: ") "The parsed CSS registry is ~4MB. This is "
            "a one-time startup cost per app instance.")
        (li (strong "Regex scanning: ") "Class detection uses regex, so dynamically "
            "constructed class names (e.g. " (code "(str \"bg-\" color \"-500\")") ") can be "
            "missed. Use complete class strings in " (code "case") "/" (code "cond") " branches.")
        (li (strong "No @apply: ") "Tailwind's " (code "@apply") " is a build-time feature. "
            "On-demand delivery works with utility classes directly.")
        (li (strong "Tailwind-shaped: ") "The registry parser understands Tailwind's naming "
            "conventions. Non-Tailwind CSS works via " (code "<style>") " blocks in components.")))))
