// would also be interesting to try out IBM Plex Mono/Sans sometime
#let atk = "Atkinson Hyperlegible"
#let fonts = (
  main: (font: atk, size: 12pt),

  title: (font: atk, size: 20pt),
  subtitle: (font: atk, size: 10pt),
  heading: (font: "Montserrat", weight: "regular"),
)

#let expand(it) = {
  ("("
  + upper(it.first())
  + "|"
  + it.first()
  + ")"
  + it.clusters().slice(1).join()
  + "s?")
}
#let singlify(it) = {
  it = lower(it)
  if it.ends-with("s") {
    it = it.slice(0, -1)
  }
  it
}
#let terminate-recursion(it) = {
  let clusters = it.text.clusters()
  clusters.insert(1, "\u{FEFF}")
  clusters.join()
}
// even though it looks like this could be automated with a `query`,
// this'd require wrapping the whole document in a show rule
// at which point `query` doesn't find anything anymore
#let terms = (
  "processing stage",
  "source",
  "AST",
  "graph IR",
  "runtime",

  "optimizer",
  "scheduler",
  "evaluator",
  "evaluation",

  "function",
  "instruction",
  "input", "argument", "consumer",
  "output", "streamer",
  "modifier",
  "pipeline",
)
// yes, the shadowing is intentional to avoid accidentally using the list
#let terms = regex("\\b(" + terms.map(expand).join("|") + ")\\b")

#let conf(
  title: none,
  subtitle: none,
  render-outline: true,
  doc,
) = {
  set page(
      numbering: "1 / 1",
        margin: 3.25cm,
          header: locate(loc => {
      datetime.today().display()

      if counter(page).at(loc).first() > 1 {
        // on all pages other than the first, the title is useful to have at hand
        h(1fr)
        title
      }
    }),
  )
  set par(justify: true)
  set text(..fonts.main)
  set heading(numbering: "A.1")

  show heading: it => text(..fonts.heading, it)
  // color links
  show link: text.with(fill: blue)
  // prettify codeblocks
  show raw.where(block: true): box.with(
    fill: luma(95%),
    inset: 1.25em,
    radius: 0.75em,
    width: 45em,
  )
  show raw.where(block: false): box.with(
    fill: luma(95%),
    outset: (y: 0.25em),
    inset: (x: 0.15em),
    radius: 0.25em,
  )
  show raw.where(block: true): it => {
    // don't try to put codeblocks into blocktext
    set par(justify: false)
    it
  }

  // semi-strategically place pagebreaks for better orientation
  let pagebreak-before(it) = pagebreak() + it
  show heading.where(outlined: true): it => {
    if it.level <= 2 {
      pagebreak(weak: true)
    }

    it
  }

  // highlight important terms in bold
  show raw: it => {
    // avoid making terms in codeblocks bold
    show terms: terminate-recursion
    it
  }
  show terms: strong

  // color codeblocks
  // haskell hl seems to work ok for this
  show raw.where(lang: "iowo", block: true): it => {
    raw(it.text, lang: "haskell", block: true)
  }

  // document title
  if title != none {
    align(
      right,
      text(..fonts.title, title)
      + v(-12pt)
      + text(..fonts.subtitle, subtitle)
    )

    v(0.25cm)
  }

  // outline and other prelude info
  if render-outline {
    outline(
      indent: auto,
      fill: line(
        length: 100%,
        stroke: (
          cap: "round",
          join: "round",
          thickness: 0.5pt,
          paint: luma(75%),
        ),
      ),
    )
  }

  // content itself
  doc
}
