   ([class attrs]
    (merge (*stylesheet* class {}) attrs)))
 
-(defn simple-page-master
+(defn heading [level title path]
+  [:fo:block (style level
+                    {:id (hash path)})
+   (layout/translations title)])
+
+(def ^:private running-header-class-name "running-header")
+
+(defn- retrieve-marker []
+  [:fo:inline
+   [:fo:retrieve-marker {:retrieve-class-name running-header-class-name
+                         :retrieve-position "last-ending-within-page"
+                         :retrieve-boundary "page-sequence"}]])
+
+(defn- set-marker [title]
+  [:fo:block {:keep-with-next "always"}
+   [:fo:marker {:marker-class-name running-header-class-name} title]])
+
+(defn- order
+  "Return `items` ordered. Checks first if `items` are either a subset
+  of `layout/formats`, `layout/braille-genres` or `layout/subgenres`
+  and consequently orders accordingly. Return nil if `items` are not a
+  subset of either."
+  [items]
+  (let [items (set (remove nil? items))]
+    (cond
+      (set/subset? items (set layout/formats))
+      (keep items layout/formats)
+      (set/subset? items (set layout/braille-genres))
+      (keep items layout/braille-genres)
+      (set/subset? items (set layout/subgenres))
+      (keep items layout/subgenres))))
+
+(defn- toc-entry [items path to-depth]
+  (let [depth (count path)]
+    [:fo:block (if (<= depth 2)
+                 {:text-align-last "justify"}
+                 {:text-align-last "justify" :start-indent "1em"})
+     [:fo:basic-link {:internal-destination (hash path)}
+      (layout/translations (last path))
+      " " [:fo:leader {:leader-pattern "dots"}] " "
+      [:fo:page-number-citation {:ref-id (hash path)}]]
+     (when (and (map? items) (< depth to-depth))
+       (keep #(toc-entry (% items) (conj path %) to-depth) (order (keys items))))]))
+
+(defn toc [items path to-depth & {:keys [heading?]}]
+  (when (map? items)
+    [:fo:block {:line-height "150%"}
+     (when heading? (heading :h1 :inhalt []))
+     (keep #(toc-entry (% items) (conj path %) to-depth) (order (keys items)))]))
+
+(defn- to-url
+  "Return an url given a `record-id`"
+  [record-id]
+  (let [api-key "c97386a2-914a-40c2-bd8d-df4c273175e6"]
+    (format "http://online.sbs.ch/iguana/www.main.cls?v=%s&amp;sUrl=search%%23RecordId=%s"
+            api-key
+            (string/replace record-id "/" "."))))
+
+(defn- external-link [record-id title]
+  [:fo:basic-link {:external-destination (to-url record-id)
+                   :indicate-destination true}
+   title])
+
+(defn- block [& args]
+  (if (map? (first args))
+    [:fo:block (style :block (first args)) (rest args)]
+    [:fo:block (style :block) args]))
+
+(defn- inline [& args]
+  (let [default {}]
+    (if (map? (first args))
+      [:fo:inline (merge default (first args)) (rest args)]
+      [:fo:inline default args])))
+
+(defn- list-item [& args]
+  [:fo:list-item {:space-after "1em"}
+   [:fo:list-item-label [:fo:block]]
+   [:fo:list-item-body
+    args]])
+
+(defn- bold [& args]
+  (inline {:font-weight "bold"} args))
+
+(defn- narrators-sexp [narrators]
+  (let [narrator (first narrators)]
+    (if (> (count narrators) 1)
+      (wrap narrator "gelesen von: " " u.a. " false)
+      (wrap narrator "gelesen von: "))))
+
+(defn- entry-heading-sexp
+  [creator record-id title subtitles name-of-part source-publisher source-date]
+  (block {:keep-with-next "always"}
+     (bold (wrap creator "" ": " false)
+           (external-link record-id (layout/periodify title)))
+     (when (or subtitles name-of-part) " ")
+     (layout/render-subtitles subtitles)
+     (layout/periodify name-of-part)
+     (when (or source-publisher source-date) " - ")
+     (wrap source-publisher "" (if source-date ", " "") false)
+     (wrap (layout/year source-date))))
+
+(defn- ausleihe [signature]
+  (when signature
+    (block {:keep-with-previous "always"} (bold "Ausleihe:") " " signature)))
+
+(defn- ausleihe-multi [signatures]
+  (when signatures
+    (block {:keep-with-previous "always"}
+           (bold "Ausleihe:") " " (layout/braille-signatures signatures))))
+
+(defn- verkauf [product-number price]
+  (when product-number
+    (block {:keep-with-previous "always"}
+           (bold "Verkauf:") " " price ", " (layout/braille-signatures product-number))))
+
+(defmulti entry-sexp (fn [{fmt :format}] fmt))
+
+(defmethod entry-sexp :hörbuch
+  [{:keys [creator record-id title subtitles name-of-part source-publisher
+           source-date genre-text description duration narrators producer-brief
+           produced-commercially? library-signature product-number price]}]
+  (list-item
+   (entry-heading-sexp creator record-id title subtitles name-of-part source-publisher source-date)
+   (block (wrap genre-text "Genre: "))
+   (block (wrap description))
+   (block (wrap duration "" " Min., " false) (narrators-sexp narrators))
+   (block producer-brief (if produced-commercially? ", Hörbuch aus dem Handel" "") ".")
+   (ausleihe library-signature)
+   (when product-number
+     (block {:keep-with-previous "always"} (bold "Verkauf:") " " product-number ", " price))))
+
+(defmethod entry-sexp :braille
+  [{:keys [creator record-id title subtitles name-of-part source-publisher source-date
+           genre-text description producer-brief rucksackbuch? rucksackbuch-number
+           library-signature product-number price]}]
+  (list-item
+   (entry-heading-sexp creator record-id title subtitles name-of-part source-publisher source-date)
+   (block (wrap genre-text "Genre: "))
+   (block (wrap description))
+   (block producer-brief (if rucksackbuch? (str ", Rucksackbuch Nr. " rucksackbuch-number) "") ".")
+   (ausleihe-multi library-signature)
+   (verkauf product-number price)))
+
+(defmethod entry-sexp :grossdruck
+  [{:keys [creator record-id title subtitles name-of-part source-publisher source-date
+           genre-text description library-signature volumes product-number price]}]
+  (list-item
+   (entry-heading-sexp creator record-id title subtitles name-of-part source-publisher source-date)
+   (block (wrap genre-text "Genre: "))
+   (block (wrap description))
+   (when library-signature
+     (block {:keep-with-previous "always"}
+            (bold "Ausleihe:") " " library-signature (wrap volumes ", " " Bd. " false)))
+   (when product-number
+     (block {:keep-with-previous "always"} (bold "Verkauf:") " " price))))
+
+(defmethod entry-sexp :e-book
+  [{:keys [creator record-id title subtitles name-of-part source-publisher source-date
+           genre-text description library-signature]}]
+  (list-item
+   (entry-heading-sexp creator record-id title subtitles name-of-part source-publisher source-date)
+   (block (wrap genre-text "Genre: "))
+   (block (wrap description))
+   (ausleihe library-signature)))
+
+(defmethod entry-sexp :hörfilm
+  [{:keys [record-id title subtitles directed-by actors movie_country genre-text
+           description producer library-signature]}]
+  (list-item
+   (block {:keep-with-next "always"}
+     (bold (external-link record-id (layout/periodify title)))
+     (layout/render-subtitles subtitles))
+   (block (wrap directed-by "Regie: " "") (wrap actors " Schauspieler: " ""))
+   (block (wrap movie_country))
+   (block (wrap genre-text))
+   (block (wrap description))
+   (block (wrap producer))
+   (ausleihe library-signature)))
+
+(defmethod entry-sexp :ludo
+  [{:keys [record-id title subtitles creator source-publisher genre-text description
+           game-description accompanying-material library-signature]}]
+  (list-item
+   (block {:keep-with-next "always"}
+     (bold (external-link record-id (layout/periodify title)))
+     (layout/render-subtitles subtitles)
+     (layout/wrap creator " "))
+   (block (wrap source-publisher))
+   (block (wrap genre-text))
+   (block (wrap description))
+   (block (wrap game-description))
+   (ausleihe library-signature)))
+
+(defmethod entry-sexp :musiknoten
+  [{:keys [creator record-id title subtitles name-of-part source-publisher source-date
+           description producer-brief library-signature product-number price]}]
+  (list-item
+   (entry-heading-sexp creator record-id title subtitles name-of-part source-publisher source-date)
+   (block (wrap description))
+   (block (wrap producer-brief))
+   (ausleihe-multi library-signature)
+   (verkauf product-number price)))
+
+(defmethod entry-sexp :taktilesbuch
+  [{:keys [creator record-id title subtitles name-of-part source-publisher source-date
+           description producer-brief library-signature product-number price]}]
+  (list-item
+   (entry-heading-sexp creator record-id title subtitles name-of-part source-publisher source-date)
+   (block (wrap description))
+   (block (wrap producer-brief))
+   (ausleihe-multi library-signature)
+   (verkauf product-number price)))
+
+(defn entries-sexp [items]
+  [:fo:list-block
+   (for [item items] (entry-sexp item))])
+
+(defn subgenre-sexp [items fmt genre subgenre]
+  (when-let [items (subgenre items)]
+    [(heading :h3 subgenre [fmt genre subgenre])
+     (when-not (#{:kinder-und-jugendbücher} genre)
+       (set-marker (layout/translations subgenre)))
+     (entries-sexp items)]))
+
+(defn subgenres-sexp [items fmt genre]
+  (mapcat #(subgenre-sexp items fmt genre %) (order (keys items))))
+
+(defn genre-sexp [items fmt genre]
+  (when-let [items (genre items)]
+    [(heading :h2 genre [fmt genre])
+     (set-marker (layout/translations genre))
+     (cond
+       (#{:kinder-und-jugendbücher} genre) (subgenres-sexp items fmt genre)
+       (#{:hörbuch} fmt) (subgenres-sexp items fmt genre)
+       :else (entries-sexp items))]))
+
+(defn format-sexp [items fmt]
+  (when-let [items (fmt items)]
+    [(heading :h1 fmt [fmt])
+     (toc items [fmt] 3)
+     (set-marker (layout/translations fmt))
+     (case fmt
+       (:hörfilm :ludo) (entries-sexp items)
+       (mapcat #(genre-sexp items fmt %) (order (keys items))))]))
+
+(defn- page-number []
+  [:fo:inline
+   [:fo:page-number]])
+
+(defn- header [side]
+  (let [recto? (= side :recto)]
+    [:fo:static-content {:flow-name (if recto? "xsl-region-before-recto" "xsl-region-before-verso")
+                         :role "artifact"}
+     [:fo:block (style :header)
+      (if recto? (retrieve-marker) (page-number))
+      [:fo:leader]
+      (if recto? (page-number) (retrieve-marker))]]))
+
+(defn- simple-page-master
   [{:keys [master-name page-height page-width
            margin-bottom margin-top
            margin-left margin-right]

                     {:xmlns:fo "http://www.w3.org/1999/XSL/Format"
                      :line-height "130%"
                      :xml:lang "de"})
     [:fo:layout-master-set
      (simple-page-master {:master-name "recto"})
      (simple-page-master {:master-name "verso"})
      [:fo:page-sequence-master {:master-name "main"}
       [:fo:repeatable-page-master-alternatives
        [:fo:conditional-page-master-reference {:master-reference "verso" :odd-or-even "even"}]
        [:fo:conditional-page-master-reference {:master-reference "recto" :odd-or-even "odd"}]]]]
     (declarations title creator description)
     [:fo:page-sequence {:master-reference "main"
                         :initial-page-number "1"

                       ;; extent should be smaller than margin-top of region-body
                       :extent (to-mm (dec region-body-margin-top))}]])

(defn- layout-master-set []
  [:fo:layout-master-set
   (simple-page-master {:master-name "recto"})
   (simple-page-master {:master-name "verso"})
   (simple-page-master {:master-name "blank"})
   (simple-page-master {:master-name "first"})
   [:fo:page-sequence-master {:master-name "main"}
    [:fo:repeatable-page-master-alternatives
     [:fo:conditional-page-master-reference
      {:master-reference "first" :page-position "first"}]
     [:fo:conditional-page-master-reference
      {:master-reference "verso" :odd-or-even "even" :blank-or-not-blank "not-blank"}]
     [:fo:conditional-page-master-reference
      {:master-reference "recto" :odd-or-even "odd" :blank-or-not-blank "not-blank"}]
     [:fo:conditional-page-master-reference
      {:master-reference "blank" :blank-or-not-blank "blank"}]]]])

(defn- declarations
  [title creator description]
