           (.attr "font-weight" (fn [node]
                                  (if (identical? node selected-node) "bold" "normal")))
           (.text #(:title %))))
-    (.classed detail-button "invisible" (or (nil? selected-node)
-                                            (= projection :zoom-out)))
     (when animate?
       (.onNext animation-subject :animation-start)
       (js/setTimeout

        current-state (atom (initial-state svg
                                           detail-button
                                           animation-subject))]
    (setup-detail-button! detail-button)
    (sync-on-window-size! current-state)
    (load-graph "miserables.json"
                (fn [graph]

(defn swap-state! [current-state f & args]
  (apply swap! current-state f args)
  (enforce-state-invariants! current-state)
  (sync-graph! @current-state)
  (sync-detail-button! @current-state))

(defn swap-state-animated! [current-state f & args]
  (apply swap! current-state f args)
  (enforce-state-invariants! current-state)
  (sync-graph! @current-state :animate? true)
  (sync-detail-button! @current-state))

(defn move-camera! [current-state d]
  (swap-state! current-state update :camera-pos v/add
