Heading text always 2.5 cm from left margin?

I would like to achieve that the text of a heading, regardless if there is a number or not, always would be placed 2.5cm from the left margin. If possible, this also should apply to the table of contents.

 1.0          Heading
 1.1          Other Heading
 1.1.1        Just another Heading
 1.1.1.1      Well again
 ^            ^
 |            +-- Begins at left margin + 2.5cms
 |
 +-- Begins at left margin

Hi. I guess this does what you describe:

// https://github.com/typst/typst/issues/6181
#import "@preview/text-dirr:1.0.0": text-dir

#let heading-left-inset = 2.5cm
#set heading(hanging-indent: heading-left-inset)

// https://github.com/typst/typst/issues/5095#issuecomment-2812970888
#show heading: it => {
  let SPACING_TO_NUMBERING = 0.3em
  let realized = it.body
  let indent = if it.hanging-indent == auto { 0pt } else { it.hanging-indent }

  let prefix
  if it.numbering != none {
    let numbering = counter(heading).display(it.numbering)
    let spacing = h(SPACING_TO_NUMBERING, weak: true)
    if it.hanging-indent == auto {
      indent = measure(numbering).width + SPACING_TO_NUMBERING
    }
    prefix = numbering + spacing
  }

  realized = box(width: heading-left-inset, prefix) + realized

  let start = if text-dir() == ltr { "left" } else { "right" }
  block(inset: ((start): indent), h(-indent) + realized)
}

// https://typst.app/docs/reference/model/outline/#building-an-entry
#show outline.entry: it => link(
  it.element.location(),
  grid(
    columns: (heading-left-inset, auto),
    it.prefix(), it.inner(),
  ),
)

#outline()

= Heading
#lorem(20)

#set heading(numbering: "1.1.")

= Heading
#lorem(20)

== Heading
#lorem(20)

=== Heading
#lorem(20)

= #lorem(15)
#lorem(20)

Though, since you didn’t say how to handle multi-line headings, you can tweak it further yourself.

Many thanks! This was exactly what I was looking for. Now I just need to understand, what it does… :slight_smile: … and looking at the source this doesn’t seem to be that easy.

I just added box(width: 2.5cm) and grid(columns: (2.5cm, auto)) to make the required space, that’s it. And heading.hanging-indent. The rest are default element implementations.